Sharedwww / macbook / imac-2.6.16.patchOpen in CoCalc
Author: William A. Stein
1
diff -uNr linux-2.6.16/Makefile linux-2.6.16-iMac/Makefile
2
--- linux-2.6.16/Makefile 2006-03-21 23:01:17.000000000 +0100
3
+++ linux-2.6.16-iMac/Makefile 2006-03-20 08:12:47.000000000 +0100
4
@@ -1,7 +1,7 @@
5
VERSION = 2
6
PATCHLEVEL = 6
7
SUBLEVEL = 16
8
-EXTRAVERSION =
9
+EXTRAVERSION = -iMac
10
NAME=Sliding Snow Leopard
11
12
# *DOCUMENTATION*
13
diff -uNr linux-2.6.16/arch/i386/kernel/dmi_scan.c linux-2.6.16-iMac/arch/i386/kernel/dmi_scan.c
14
--- linux-2.6.16/arch/i386/kernel/dmi_scan.c 2006-03-21 23:01:17.000000000 +0100
15
+++ linux-2.6.16-iMac/arch/i386/kernel/dmi_scan.c 2006-03-20 08:01:46.000000000 +0100
16
@@ -5,6 +5,7 @@
17
#include <linux/dmi.h>
18
#include <linux/bootmem.h>
19
#include <linux/slab.h>
20
+#include <linux/efi.h>
21
22
static char * __init dmi_string(struct dmi_header *dm, u8 s)
23
{
24
@@ -184,39 +185,66 @@
25
}
26
}
27
28
-void __init dmi_scan_machine(void)
29
+static int __init dmi_present(char __iomem *p)
30
{
31
u8 buf[15];
32
+ memcpy_fromio(buf, p, 15);
33
+ if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
34
+ u16 num = (buf[13] << 8) | buf[12];
35
+ u16 len = (buf[7] << 8) | buf[6];
36
+ u32 base = (buf[11] << 24) | (buf[10] << 16) |
37
+ (buf[9] << 8) | buf[8];
38
+
39
+ /*
40
+ * DMI version 0.0 means that the real version is taken from
41
+ * the SMBIOS version, which we don't know at this point.
42
+ */
43
+ if (buf[14] != 0)
44
+ printk(KERN_INFO "DMI %d.%d present.\n",
45
+ buf[14] >> 4, buf[14] & 0xF);
46
+ else
47
+ printk(KERN_INFO "DMI present.\n");
48
+ if (dmi_table(base,len, num, dmi_decode) == 0)
49
+ return 0;
50
+ }
51
+
52
+ return 1;
53
+}
54
+
55
+void __init dmi_scan_machine(void)
56
+{
57
char __iomem *p, *q;
58
+ int rc;
59
60
- /*
61
- * no iounmap() for that ioremap(); it would be a no-op, but it's
62
- * so early in setup that sucker gets confused into doing what
63
- * it shouldn't if we actually call it.
64
- */
65
- p = ioremap(0xF0000, 0x10000);
66
- if (p == NULL)
67
- goto out;
68
69
- for (q = p; q < p + 0x10000; q += 16) {
70
- memcpy_fromio(buf, q, 15);
71
- if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
72
- u16 num = (buf[13] << 8) | buf[12];
73
- u16 len = (buf[7] << 8) | buf[6];
74
- u32 base = (buf[11] << 24) | (buf[10] << 16) |
75
- (buf[9] << 8) | buf[8];
76
-
77
- /*
78
- * DMI version 0.0 means that the real version is taken from
79
- * the SMBIOS version, which we don't know at this point.
80
- */
81
- if (buf[14] != 0)
82
- printk(KERN_INFO "DMI %d.%d present.\n",
83
- buf[14] >> 4, buf[14] & 0xF);
84
- else
85
- printk(KERN_INFO "DMI present.\n");
86
+ if (efi_enabled) {
87
+ if (!efi.smbios)
88
+ goto out;
89
+
90
+ p = efi.smbios;
91
+
92
+ if (p == NULL)
93
+ goto out;
94
+
95
+ rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
96
97
- if (dmi_table(base,len, num, dmi_decode) == 0)
98
+ if (!rc)
99
+ return;
100
+
101
+ } else {
102
+
103
+ /*
104
+ * no iounmap() for that ioremap(); it would be a no-op, but
105
+ * it's so early in setup that sucker gets confused into doing
106
+ * what it shouldn't if we actually call it.
107
+ */
108
+ p = ioremap(0xF0000, 0x10000);
109
+ if (p == NULL)
110
+ goto out;
111
+
112
+ for (q = p; q < p + 0x10000; q += 16) {
113
+ rc = dmi_present(q);
114
+ if (!rc)
115
return;
116
}
117
}
118
diff -uNr linux-2.6.16/arch/i386/kernel/efi.c linux-2.6.16-iMac/arch/i386/kernel/efi.c
119
--- linux-2.6.16/arch/i386/kernel/efi.c 2006-03-21 23:01:17.000000000 +0100
120
+++ linux-2.6.16-iMac/arch/i386/kernel/efi.c 2006-03-20 08:01:46.000000000 +0100
121
@@ -395,7 +395,7 @@
122
printk(KERN_INFO " ACPI=0x%lx ", config_tables[i].table);
123
} else
124
if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
125
- efi.smbios = (void *) config_tables[i].table;
126
+ efi.smbios = __va(config_tables[i].table);
127
printk(KERN_INFO " SMBIOS=0x%lx ", config_tables[i].table);
128
} else
129
if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
130
diff -uNr linux-2.6.16/drivers/Makefile linux-2.6.16-iMac/drivers/Makefile
131
--- linux-2.6.16/drivers/Makefile 2006-03-21 23:01:18.000000000 +0100
132
+++ linux-2.6.16-iMac/drivers/Makefile 2006-03-26 07:06:49.000000000 +0200
133
@@ -33,7 +33,7 @@
134
obj-y += base/ block/ misc/ mfd/ net/ media/
135
obj-$(CONFIG_NUBUS) += nubus/
136
obj-$(CONFIG_ATM) += atm/
137
-obj-$(CONFIG_PPC_PMAC) += macintosh/
138
+obj-y += macintosh/
139
obj-$(CONFIG_IDE) += ide/
140
obj-$(CONFIG_FC4) += fc4/
141
obj-$(CONFIG_SCSI) += scsi/
142
diff -uNr linux-2.6.16/drivers/acpi/Kconfig linux-2.6.16-iMac/drivers/acpi/Kconfig
143
--- linux-2.6.16/drivers/acpi/Kconfig 2006-03-21 23:01:18.000000000 +0100
144
+++ linux-2.6.16-iMac/drivers/acpi/Kconfig 2006-03-26 07:42:13.000000000 +0200
145
@@ -96,6 +96,13 @@
146
/proc/acpi/battery. If you have a mobile system with a battery,
147
say Y.
148
149
+config ACPI_SBS
150
+ tristate "Smart Battery System"
151
+ depends on ACPI_AC && ACPI_BATTERY && I2C
152
+ default y
153
+ help
154
+ This driver adds support for the Smart Battery System
155
+
156
config ACPI_BUTTON
157
tristate "Button"
158
default y
159
diff -uNr linux-2.6.16/drivers/acpi/Makefile linux-2.6.16-iMac/drivers/acpi/Makefile
160
--- linux-2.6.16/drivers/acpi/Makefile 2006-01-03 04:21:10.000000000 +0100
161
+++ linux-2.6.16-iMac/drivers/acpi/Makefile 2006-03-26 07:42:28.000000000 +0200
162
@@ -39,6 +39,7 @@
163
obj-y += bus.o glue.o
164
obj-$(CONFIG_ACPI_AC) += ac.o
165
obj-$(CONFIG_ACPI_BATTERY) += battery.o
166
+obj-$(CONFIG_ACPI_SBS) += i2c_acpi_ec.o acpi_sbs.o
167
obj-$(CONFIG_ACPI_BUTTON) += button.o
168
obj-$(CONFIG_ACPI_EC) += ec.o
169
obj-$(CONFIG_ACPI_FAN) += fan.o
170
diff -uNr linux-2.6.16/drivers/acpi/ac.c linux-2.6.16-iMac/drivers/acpi/ac.c
171
--- linux-2.6.16/drivers/acpi/ac.c 2006-01-03 04:21:10.000000000 +0100
172
+++ linux-2.6.16-iMac/drivers/acpi/ac.c 2006-03-20 08:01:46.000000000 +0100
173
@@ -324,5 +324,12 @@
174
return_VOID;
175
}
176
177
+struct proc_dir_entry *acpi_get_ac_dir(void)
178
+{
179
+ return (acpi_ac_dir);
180
+}
181
+
182
+EXPORT_SYMBOL(acpi_get_ac_dir);
183
+
184
module_init(acpi_ac_init);
185
module_exit(acpi_ac_exit);
186
diff -uNr linux-2.6.16/drivers/acpi/acpi_sbs.c linux-2.6.16-iMac/drivers/acpi/acpi_sbs.c
187
--- linux-2.6.16/drivers/acpi/acpi_sbs.c 1970-01-01 01:00:00.000000000 +0100
188
+++ linux-2.6.16-iMac/drivers/acpi/acpi_sbs.c 2006-03-21 23:04:03.000000000 +0100
189
@@ -0,0 +1,2268 @@
190
+/*
191
+ * acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.2 $)
192
+ *
193
+ * Copyright (c) 2005 Rich Townsend <[email protected]>
194
+ *
195
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
196
+ *
197
+ * This program is free software; you can redistribute it and/or modify
198
+ * it under the terms of the GNU General Public License as published by
199
+ * the Free Software Foundation; either version 2 of the License, or (at
200
+ * your option) any later version.
201
+ *
202
+ * This program is distributed in the hope that it will be useful, but
203
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
204
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
205
+ * General Public License for more details.
206
+ *
207
+ * You should have received a copy of the GNU General Public License along
208
+ * with this program; if not, write to the Free Software Foundation, Inc.,
209
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
210
+ *
211
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
212
+ */
213
+
214
+#include <linux/init.h>
215
+#include <linux/module.h>
216
+#include <linux/moduleparam.h>
217
+#include <linux/kernel.h>
218
+#include <linux/proc_fs.h>
219
+#include <linux/seq_file.h>
220
+#include <asm/semaphore.h>
221
+#include <asm/uaccess.h>
222
+#include <linux/acpi.h>
223
+#include <linux/i2c.h>
224
+
225
+#include "i2c_acpi_ec.h"
226
+
227
+extern struct proc_dir_entry *acpi_get_ac_dir(void);
228
+extern struct proc_dir_entry *acpi_get_battery_dir(void);
229
+
230
+#define ACPI_SBS_COMPONENT 0x00080000
231
+#define ACPI_SBS_CLASS "sbs"
232
+#define ACPI_SBS_HID "ACPI0002"
233
+#define ACPI_SBS_DRIVER_NAME "ACPI Smart Battery System Driver"
234
+#define ACPI_SBS_DEVICE_NAME "Smart Battery System"
235
+#define ACPI_SBS_FILE_INFO "info"
236
+#define ACPI_SBS_FILE_STATE "state"
237
+#define ACPI_SBS_FILE_ALARM "alarm"
238
+#define ACPI_SB_DEVICE_NAME "Smart Battery"
239
+#define ACPI_SBSM_DEVICE_NAME "Smart Battery System Manager"
240
+#define ACPI_SBSEL_DEVICE_NAME "Smart Battery Selector"
241
+#define ACPI_SBC_DEVICE_NAME "Smart Battery Charger"
242
+#define ACPI_SB_DIR_NAME "SB%d"
243
+#define ACPI_SBSM_DIR_NAME "SBSM"
244
+#define ACPI_SBSEL_DIR_NAME "SBSEL"
245
+#define ACPI_SBC_DIR_NAME "SBC"
246
+#define ACPI_SBSM_CLASS 1
247
+#define ACPI_SBSEL_CLASS 2
248
+#define ACPI_LBATTERY_DIR_NAME "BAT%d"
249
+#define ACPI_LADAPTER_DIR_NAME "AC0"
250
+#define ACPI_SBH_SMBUS_ADDR 0x8
251
+#define ACPI_SBC_SMBUS_ADDR 0x9
252
+#define ACPI_SBSM_SMBUS_ADDR 0xa
253
+#define ACPI_SB_SMBUS_ADDR 0xb
254
+#define ACPI_SBS_TIMEOUT_DELAY HZ/50
255
+
256
+#define _COMPONENT ACPI_SBS_COMPONENT
257
+
258
+ACPI_MODULE_NAME("acpi_sbs")
259
+
260
+MODULE_LICENSE("GPL");
261
+MODULE_AUTHOR("Rich Townsend");
262
+MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
263
+
264
+static u16 capacity_mode = 2;
265
+module_param(capacity_mode, ushort, 2);
266
+
267
+static u16 mac_hack = 0;
268
+module_param(mac_hack, ushort, 0);
269
+
270
+static int acpi_sbs_add(struct acpi_device *device);
271
+static int acpi_sbs_remove(struct acpi_device *device, int type);
272
+
273
+static struct acpi_driver acpi_sbs_driver = {
274
+ .name = ACPI_SBS_DRIVER_NAME,
275
+ .class = ACPI_SBS_CLASS,
276
+ .ids = ACPI_SBS_HID,
277
+ .ops = {
278
+ .add = acpi_sbs_add,
279
+ .remove = acpi_sbs_remove,
280
+ },
281
+};
282
+
283
+struct acpi_sb_info {
284
+ u8 capacity_mode;
285
+ u16 max_error;
286
+ u16 full_charge_capacity;
287
+ u16 charging_amperage;
288
+ u16 charging_voltage;
289
+ u16 cycle_count;
290
+ u16 design_capacity;
291
+ u16 design_voltage;
292
+ u8 specid;
293
+ u16 vscale;
294
+ u16 ipscale;
295
+ u16 manufacture_day;
296
+ u16 manufacture_month;
297
+ u16 manufacture_year;
298
+ u16 serial_number;
299
+ char manufacturer_name[I2C_SMBUS_BLOCK_MAX + 3];
300
+ char device_name[I2C_SMBUS_BLOCK_MAX + 3];
301
+ char device_chemistry[I2C_SMBUS_BLOCK_MAX + 3];
302
+};
303
+
304
+struct acpi_sb_state {
305
+ u8 relearn_flag;
306
+ u16 temperature;
307
+ u16 voltage;
308
+ s16 amperage;
309
+ s16 average_amperage;
310
+ u16 relative_state_of_charge;
311
+ u16 absolute_state_of_charge;
312
+ u16 remaining_capacity;
313
+ u16 run_time_to_empty;
314
+ u16 average_time_to_empty;
315
+ u16 average_time_to_full;
316
+ u16 battery_status;
317
+};
318
+
319
+struct acpi_sb_alarm {
320
+ u16 remaining_capacity;
321
+ u16 remaining_time;
322
+};
323
+
324
+struct acpi_sb {
325
+ u8 id;
326
+ u8 init_state;
327
+ struct acpi_sbs *sbs;
328
+ struct acpi_sb_info info;
329
+ struct acpi_sb_state state;
330
+ struct acpi_sb_alarm alarm;
331
+ struct proc_dir_entry *sb_entry;
332
+ struct proc_dir_entry *lbattery_entry;
333
+};
334
+
335
+struct acpi_sbsm_info {
336
+ u8 batteries_supported;
337
+ u8 battery_system_revision;
338
+ u16 vscale;
339
+ u16 ipscale;
340
+ u8 charging_indicator;
341
+};
342
+
343
+struct acpi_sbsm_state {
344
+ u8 smb_x;
345
+ u8 power_by_x;
346
+ u8 charge_x;
347
+ u8 connected_x;
348
+ u8 present_x;
349
+ u8 ac_present;
350
+ u8 power_not_good;
351
+};
352
+
353
+struct acpi_sbsm {
354
+ u8 class;
355
+ struct acpi_sbs *sbs;
356
+ struct acpi_sbsm_info info;
357
+ struct acpi_sbsm_state state;
358
+ struct proc_dir_entry *sbsm_entry;
359
+};
360
+
361
+struct acpi_sbc_info {
362
+ u8 charger_spec;
363
+ u8 selector_support;
364
+};
365
+
366
+struct acpi_sbc_state {
367
+ u8 power_fail;
368
+ u8 battery_present;
369
+ u8 ac_present;
370
+};
371
+
372
+struct acpi_sbc {
373
+ struct acpi_sbs *sbs;
374
+ struct acpi_sbc_info info;
375
+ struct acpi_sbc_state state;
376
+ struct proc_dir_entry *sbc_entry;
377
+ struct proc_dir_entry *ladapter_entry;
378
+};
379
+
380
+struct acpi_sbs {
381
+ acpi_handle handle;
382
+ struct acpi_device *device;
383
+ struct acpi_ec_smbus *smbus;
384
+ struct acpi_sb *sb;
385
+ struct acpi_sbsm *sbsm;
386
+ struct acpi_sbc *sbc;
387
+ struct semaphore sem;
388
+};
389
+
390
+/* --------------------------------------------------------------------------
391
+ SMBus Communication
392
+ -------------------------------------------------------------------------- */
393
+
394
+static s32
395
+acpi_sbs_smbus_read_word(struct acpi_ec_smbus *smbus, u16 addr, u8 func,
396
+ u16 * word,
397
+ void (*err_handler) (struct acpi_ec_smbus * smbus))
398
+{
399
+ union i2c_smbus_data data;
400
+ s32 result = 0;
401
+
402
+ ACPI_FUNCTION_TRACE("acpi_sbs_smbus_read_word");
403
+
404
+ result =
405
+ smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
406
+ I2C_SMBUS_READ, func,
407
+ I2C_SMBUS_WORD_DATA, &data);
408
+ if (result) {
409
+ if (err_handler)
410
+ err_handler(smbus);
411
+ } else {
412
+ *word = data.word;
413
+ }
414
+
415
+ return_VALUE(result);
416
+}
417
+
418
+static s32
419
+acpi_sbs_smbus_read_str(struct acpi_ec_smbus *smbus, u16 addr, u8 func,
420
+ char *str,
421
+ void (*err_handler) (struct acpi_ec_smbus * smbus))
422
+{
423
+ union i2c_smbus_data data;
424
+ s32 result = 0;
425
+
426
+ ACPI_FUNCTION_TRACE("acpi_sbs_smbus_read_str");
427
+
428
+ result = smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
429
+ I2C_SMBUS_READ, func,
430
+ I2C_SMBUS_BLOCK_DATA, &data);
431
+ if (result) {
432
+ if (err_handler)
433
+ err_handler(smbus);
434
+ } else {
435
+ strncpy(str, (const char *)data.block + 1, data.block[0]);
436
+ str[data.block[0]] = 0;
437
+ }
438
+
439
+ return_VALUE(result);
440
+}
441
+
442
+static void acpi_sb_smbus_err_handler(struct acpi_ec_smbus *smbus)
443
+{
444
+ union i2c_smbus_data data;
445
+ s32 result = 0;
446
+
447
+ ACPI_FUNCTION_TRACE("acpi_sb_smbus_err_handler");
448
+
449
+ result =
450
+ smbus->adapter.algo->smbus_xfer(&smbus->adapter, ACPI_SB_SMBUS_ADDR,
451
+ 0, I2C_SMBUS_READ, 0x16,
452
+ I2C_SMBUS_BLOCK_DATA, &data);
453
+
454
+ switch (data.word & 0x000f) {
455
+ case 0x0000:
456
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "unexpected bus error\n"));
457
+ break;
458
+ case 0x0001:
459
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "busy\n"));
460
+ break;
461
+ case 0x0002:
462
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "reserved command\n"));
463
+ break;
464
+ case 0x0003:
465
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "unsupported command\n"));
466
+ break;
467
+ case 0x0004:
468
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "access denied\n"));
469
+ break;
470
+ case 0x0005:
471
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "overflow/underflow\n"));
472
+ break;
473
+ case 0x0006:
474
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "bad size\n"));
475
+ break;
476
+ case 0x0007:
477
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "unknown error\n"));
478
+ break;
479
+ default:
480
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "unrecognized error\n"));
481
+ }
482
+}
483
+
484
+static s32
485
+acpi_sbs_smbus_write_word(struct acpi_ec_smbus *smbus, u16 addr, u8 func,
486
+ u16 word,
487
+ void (*err_handler) (struct acpi_ec_smbus * smbus))
488
+{
489
+ union i2c_smbus_data data;
490
+ s32 result = 0;
491
+
492
+ ACPI_FUNCTION_TRACE("acpi_sbs_smbus_write_word");
493
+
494
+ data.word = word;
495
+
496
+ result =
497
+ smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
498
+ I2C_SMBUS_WRITE, func,
499
+ I2C_SMBUS_WORD_DATA, &data);
500
+ if (result)
501
+ if (err_handler)
502
+ err_handler(smbus);
503
+
504
+ return_VALUE(result);
505
+}
506
+
507
+/* --------------------------------------------------------------------------
508
+ Smart Battery System Management
509
+ -------------------------------------------------------------------------- */
510
+
511
+/* Smart Battery */
512
+
513
+static int acpi_sb_is_present(struct acpi_sb *sb)
514
+{
515
+ u16 battery_system_state;
516
+ int result;
517
+ int is_present;
518
+
519
+ ACPI_FUNCTION_TRACE("acpi_sbs_is_sb_present");
520
+
521
+ if (sb->sbs->sbsm) {
522
+ result = acpi_sbs_smbus_read_word(sb->sbs->smbus,
523
+ ACPI_SBSM_SMBUS_ADDR, 0x01,
524
+ &battery_system_state, NULL);
525
+ if (!result) {
526
+ is_present =
527
+ (battery_system_state & 0x000f) & (1 << sb->id);
528
+ }
529
+ else
530
+ is_present = 0;
531
+ } else {
532
+ is_present = 0;
533
+ }
534
+
535
+ return_VALUE(is_present);
536
+}
537
+
538
+static int acpi_sb_select(struct acpi_sb *sb)
539
+{
540
+ struct acpi_ec_smbus *smbus = sb->sbs->smbus;
541
+ int result = 0;
542
+ u16 battery_system_state;
543
+
544
+ ACPI_FUNCTION_TRACE("acpi_sb_select");
545
+
546
+ if (sb->sbs->sbsm) {
547
+
548
+ /* Take special care not to knobble other nibbles of
549
+ * battery_system_state (aka selector_state), since
550
+ * it causes charging to halt on SBSELs */
551
+
552
+ result =
553
+ acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01,
554
+ &battery_system_state, NULL);
555
+ if (result)
556
+ goto end;
557
+
558
+ result =
559
+ acpi_sbs_smbus_write_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01,
560
+ (battery_system_state & 0x0fff) |
561
+ (1 << (sb->id + 12)), NULL);
562
+ }
563
+
564
+ end:
565
+ if(mac_hack)
566
+ result = 0;
567
+ return_VALUE(result);
568
+}
569
+
570
+static int acpi_sb_get_info(struct acpi_sb *sb)
571
+{
572
+ struct acpi_ec_smbus *smbus = sb->sbs->smbus;
573
+ int result = 0;
574
+ u16 battery_mode;
575
+ u16 specification_info;
576
+ u16 manufacture_date;
577
+
578
+ ACPI_FUNCTION_TRACE("acpi_sb_get_info");
579
+
580
+ if ((result = acpi_sb_select(sb)))
581
+ goto end;
582
+
583
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03,
584
+ &battery_mode,
585
+ &acpi_sb_smbus_err_handler)))
586
+ goto end;
587
+ sb->info.capacity_mode = (battery_mode & 0x8000) >> 15;
588
+
589
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0c,
590
+ &sb->info.max_error,
591
+ &acpi_sb_smbus_err_handler)))
592
+ goto end;
593
+
594
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x10,
595
+ &sb->info.full_charge_capacity,
596
+ &acpi_sb_smbus_err_handler)))
597
+ goto end;
598
+
599
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x14,
600
+ &sb->info.charging_amperage,
601
+ &acpi_sb_smbus_err_handler)))
602
+ goto end;
603
+
604
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x15,
605
+ &sb->info.charging_voltage,
606
+ &acpi_sb_smbus_err_handler)))
607
+ goto end;
608
+
609
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x17,
610
+ &sb->info.cycle_count,
611
+ &acpi_sb_smbus_err_handler)))
612
+ goto end;
613
+
614
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x18,
615
+ &sb->info.design_capacity,
616
+ &acpi_sb_smbus_err_handler)))
617
+ goto end;
618
+
619
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x19,
620
+ &sb->info.design_voltage,
621
+ &acpi_sb_smbus_err_handler)))
622
+ goto end;
623
+
624
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1a,
625
+ &specification_info,
626
+ &acpi_sb_smbus_err_handler)))
627
+ goto end;
628
+
629
+ sb->info.specid = specification_info & 0x00ff;
630
+
631
+ switch ((specification_info & 0x0f00) >> 8) {
632
+ case 1:
633
+ sb->info.vscale = 10;
634
+ break;
635
+ case 2:
636
+ sb->info.vscale = 100;
637
+ break;
638
+ case 3:
639
+ sb->info.vscale = 1000;
640
+ break;
641
+ default:
642
+ sb->info.vscale = 1;
643
+ }
644
+
645
+ switch ((specification_info & 0xf000) >> 12) {
646
+ case 1:
647
+ sb->info.ipscale = 10;
648
+ break;
649
+ case 2:
650
+ sb->info.ipscale = 100;
651
+ break;
652
+ case 3:
653
+ sb->info.ipscale = 1000;
654
+ break;
655
+ default:
656
+ sb->info.ipscale = 1;
657
+ }
658
+
659
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1b,
660
+ &manufacture_date,
661
+ &acpi_sb_smbus_err_handler)))
662
+ goto end;
663
+
664
+ sb->info.manufacture_day = manufacture_date & 0x001f;
665
+ sb->info.manufacture_month = (manufacture_date & 0x01e0) >> 5;
666
+ sb->info.manufacture_year = ((manufacture_date & 0xfe00) >> 9) + 1980;
667
+
668
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1c,
669
+ &sb->info.serial_number,
670
+ &acpi_sb_smbus_err_handler)))
671
+ goto end;
672
+
673
+ if ((result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x20,
674
+ sb->info.manufacturer_name,
675
+ &acpi_sb_smbus_err_handler)))
676
+ goto end;
677
+
678
+ if ((result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x21,
679
+ sb->info.device_name,
680
+ &acpi_sb_smbus_err_handler)))
681
+ goto end;
682
+
683
+ if ((result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x22,
684
+ sb->info.device_chemistry,
685
+ &acpi_sb_smbus_err_handler)))
686
+ goto end;
687
+
688
+ end:
689
+ return_VALUE(result);
690
+}
691
+
692
+static int acpi_sb_get_state(struct acpi_sb *sb)
693
+{
694
+ struct acpi_ec_smbus *smbus = sb->sbs->smbus;
695
+ int result = 0;
696
+ u16 battery_mode;
697
+
698
+ ACPI_FUNCTION_TRACE("acpi_sb_get_state");
699
+
700
+ if ((result = acpi_sb_select(sb)))
701
+ goto end;
702
+
703
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03,
704
+ &battery_mode,
705
+ &acpi_sb_smbus_err_handler)))
706
+ goto end;
707
+ sb->state.relearn_flag = (battery_mode & 0x0080) >> 7;
708
+
709
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x08,
710
+ &sb->state.temperature,
711
+ &acpi_sb_smbus_err_handler)))
712
+ goto end;
713
+
714
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x09,
715
+ &sb->state.voltage,
716
+ &acpi_sb_smbus_err_handler)))
717
+ goto end;
718
+
719
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0a,
720
+ &sb->state.amperage,
721
+ &acpi_sb_smbus_err_handler)))
722
+ goto end;
723
+
724
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0b,
725
+ &sb->state.average_amperage,
726
+ &acpi_sb_smbus_err_handler)))
727
+ goto end;
728
+
729
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0d,
730
+ &sb->state.
731
+ relative_state_of_charge,
732
+ &acpi_sb_smbus_err_handler)))
733
+ goto end;
734
+
735
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0e,
736
+ &sb->state.
737
+ absolute_state_of_charge,
738
+ &acpi_sb_smbus_err_handler)))
739
+ goto end;
740
+
741
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0f,
742
+ &sb->state.remaining_capacity,
743
+ &acpi_sb_smbus_err_handler)))
744
+ goto end;
745
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x11,
746
+ &sb->state.run_time_to_empty,
747
+ &acpi_sb_smbus_err_handler)))
748
+ goto end;
749
+
750
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x12,
751
+ &sb->state.average_time_to_empty,
752
+ &acpi_sb_smbus_err_handler)))
753
+ goto end;
754
+
755
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x13,
756
+ &sb->state.average_time_to_full,
757
+ &acpi_sb_smbus_err_handler)))
758
+ goto end;
759
+
760
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x16,
761
+ &sb->state.battery_status,
762
+ &acpi_sb_smbus_err_handler)))
763
+ goto end;
764
+
765
+ end:
766
+ return_VALUE(result);
767
+}
768
+
769
+static int acpi_sb_get_alarm(struct acpi_sb *sb)
770
+{
771
+ struct acpi_ec_smbus *smbus = sb->sbs->smbus;
772
+ int result = 0;
773
+
774
+ ACPI_FUNCTION_TRACE("acpi_sb_get_alarm");
775
+
776
+ if ((result = acpi_sb_select(sb)))
777
+ goto end;
778
+
779
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
780
+ &sb->alarm.remaining_capacity,
781
+ &acpi_sb_smbus_err_handler)))
782
+ goto end;
783
+
784
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x02,
785
+ &sb->alarm.remaining_time,
786
+ &acpi_sb_smbus_err_handler)))
787
+ goto end;
788
+ end:
789
+ return_VALUE(result);
790
+}
791
+
792
+static int acpi_sb_set_alarm(struct acpi_sb *sb)
793
+{
794
+ struct acpi_ec_smbus *smbus = sb->sbs->smbus;
795
+ int result = 0;
796
+ u16 battery_mode;
797
+
798
+ ACPI_FUNCTION_TRACE("acpi_sb_set_alarm");
799
+
800
+ if ((result = acpi_sb_select(sb)))
801
+ goto end;
802
+
803
+ /* If necessary, enable the alarm */
804
+
805
+ if (sb->alarm.remaining_capacity > 0 || sb->alarm.remaining_time > 0) {
806
+ if ((result =
807
+ acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03,
808
+ &battery_mode,
809
+ &acpi_sb_smbus_err_handler)))
810
+ goto end;
811
+ if ((result =
812
+ acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
813
+ battery_mode & 0xbfff,
814
+ &acpi_sb_smbus_err_handler)))
815
+ goto end;
816
+ }
817
+
818
+ if ((result = acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
819
+ sb->alarm.remaining_capacity /
820
+ (sb->info.
821
+ capacity_mode ? 10 : 1),
822
+ &acpi_sb_smbus_err_handler)))
823
+ goto end;
824
+
825
+ if ((result = acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x02,
826
+ sb->alarm.remaining_time,
827
+ &acpi_sb_smbus_err_handler)))
828
+ goto end;
829
+ end:
830
+ return_VALUE(result);
831
+}
832
+
833
+static int acpi_sb_init(struct acpi_sb *sb)
834
+{
835
+ int result = 0;
836
+ u16 battery_mode;
837
+
838
+ ACPI_FUNCTION_TRACE("acpi_sb_init");
839
+
840
+ if (capacity_mode) {
841
+ result = acpi_sbs_smbus_read_word(sb->sbs->smbus,
842
+ ACPI_SB_SMBUS_ADDR, 0x03,
843
+ &battery_mode, NULL);
844
+ if (!result) {
845
+ if (capacity_mode == 1) {
846
+ battery_mode &= 0x7fff;
847
+ } else {
848
+ battery_mode |= 0x8000;
849
+ }
850
+ result =
851
+ acpi_sbs_smbus_write_word(sb->sbs->smbus,
852
+ ACPI_SB_SMBUS_ADDR,
853
+ 0x03, battery_mode, NULL);
854
+ if (result) {
855
+ printk(KERN_ALERT PREFIX
856
+ "SBS: problem setting capacity_mode\n");
857
+ goto end;
858
+ }
859
+ } else {
860
+ printk(KERN_ALERT PREFIX
861
+ "SBS: problem setting capacity_mode\n");
862
+ goto end;
863
+ }
864
+ }
865
+
866
+
867
+ result = acpi_sb_get_info(sb);
868
+ if (result) {
869
+ goto end;
870
+ }
871
+
872
+ result = acpi_sb_get_state(sb);
873
+ if (result) {
874
+ goto end;
875
+ }
876
+
877
+ end:
878
+ return_VALUE(result);
879
+}
880
+
881
+static int acpi_sb_check_init_state(struct acpi_sb *sb)
882
+{
883
+ int result = 0;
884
+
885
+ ACPI_FUNCTION_TRACE("acpi_sb_check_init_state");
886
+
887
+ if (!sb->init_state) {
888
+ result = acpi_sb_init(sb);
889
+ if (result) {
890
+ goto end;
891
+ }
892
+ sb->init_state = 1;
893
+ }
894
+ end:
895
+ return_VALUE(result);
896
+}
897
+
898
+/* Smart Battery System Manager / Smart Battery Selector */
899
+
900
+static int acpi_sbsm_get_info(struct acpi_sbsm *sbsm)
901
+{
902
+ struct acpi_ec_smbus *smbus = sbsm->sbs->smbus;
903
+ int result = 0;
904
+ u16 battery_system_info;
905
+
906
+ ACPI_FUNCTION_TRACE("acpi_sbsm_get_info");
907
+
908
+ if ((result =
909
+ acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x04,
910
+ &battery_system_info, NULL)))
911
+ goto end;
912
+
913
+ sbsm->info.batteries_supported = battery_system_info & 0x000f;
914
+ sbsm->info.battery_system_revision =
915
+ (battery_system_info & 0x00f0) >> 4;
916
+
917
+ if (sbsm->class == ACPI_SBSM_CLASS) {
918
+ switch ((battery_system_info & 0x0f00) >> 8) {
919
+ case 1:
920
+ sbsm->info.vscale = 10;
921
+ break;
922
+ case 2:
923
+ sbsm->info.vscale = 100;
924
+ break;
925
+ case 3:
926
+ sbsm->info.vscale = 1000;
927
+ break;
928
+ default:
929
+ sbsm->info.vscale = 1;
930
+ }
931
+
932
+ switch ((battery_system_info & 0xf000) >> 12) {
933
+ case 1:
934
+ sbsm->info.ipscale = 10;
935
+ break;
936
+ case 2:
937
+ sbsm->info.ipscale = 100;
938
+ break;
939
+ case 3:
940
+ sbsm->info.ipscale = 1000;
941
+ break;
942
+ default:
943
+ sbsm->info.ipscale = 1;
944
+ }
945
+
946
+ sbsm->info.charging_indicator = 0;
947
+ } else {
948
+ sbsm->info.vscale = 1;
949
+ sbsm->info.ipscale = 1;
950
+
951
+ sbsm->info.charging_indicator =
952
+ (battery_system_info & 0x0100) >> 8;
953
+ }
954
+
955
+ end:
956
+ return_VALUE(result);
957
+}
958
+
959
+static int acpi_sbsm_get_state(struct acpi_sbsm *sbsm)
960
+{
961
+ struct acpi_ec_smbus *smbus = sbsm->sbs->smbus;
962
+ int result = 0;
963
+ u16 battery_system_state;
964
+
965
+ ACPI_FUNCTION_TRACE("acpi_sbsm_get_state");
966
+
967
+ if ((result =
968
+ acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01,
969
+ &battery_system_state, NULL)))
970
+ goto end;
971
+
972
+ if (sbsm->class == ACPI_SBSM_CLASS) {
973
+ sbsm->state.smb_x = (battery_system_state & 0xf000) >> 12;
974
+ sbsm->state.power_by_x = (battery_system_state & 0x0f00) >> 8;
975
+ sbsm->state.charge_x = (battery_system_state & 0x00f0) >> 4;
976
+ sbsm->state.connected_x = sbsm->state.charge_x;
977
+ sbsm->state.present_x = battery_system_state & 0x000f;
978
+
979
+ if ((result =
980
+ acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x02,
981
+ &battery_system_state, NULL)))
982
+ goto end;
983
+
984
+ sbsm->state.ac_present = battery_system_state & 0x0001;
985
+ sbsm->state.power_not_good = battery_system_state & 0x0002;
986
+ } else {
987
+ sbsm->state.smb_x = (battery_system_state & 0xf000) >> 12;
988
+ sbsm->state.power_by_x = (battery_system_state & 0x0f00) >> 8;
989
+ sbsm->state.connected_x = (battery_system_state & 0x00f0) >> 4;
990
+ sbsm->state.present_x = battery_system_state & 0x000f;
991
+ if (sbsm->state.power_by_x == 0xf) {
992
+ sbsm->state.power_by_x = 0x0;
993
+ sbsm->state.connected_x = ~sbsm->state.connected_x;
994
+ sbsm->state.charge_x = sbsm->state.connected_x;
995
+ sbsm->state.ac_present = 1;
996
+ } else if (sbsm->state.power_by_x == 0x0) {
997
+ sbsm->state.charge_x = 0x0;
998
+ sbsm->state.ac_present = 1;
999
+ } else {
1000
+ sbsm->state.charge_x = 0x0;
1001
+ sbsm->state.ac_present = 0;
1002
+ }
1003
+ sbsm->state.power_not_good = 0;
1004
+ }
1005
+
1006
+ end:
1007
+ return_VALUE(result);
1008
+}
1009
+
1010
+/* Smart Battery Charger */
1011
+
1012
+static int acpi_sbc_get_info(struct acpi_sbc *sbc)
1013
+{
1014
+ struct acpi_ec_smbus *smbus = sbc->sbs->smbus;
1015
+ int result = 0;
1016
+ u16 charger_spec_info;
1017
+
1018
+ ACPI_FUNCTION_TRACE("acpi_sbc_get_info");
1019
+
1020
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SBC_SMBUS_ADDR, 0x11,
1021
+ &charger_spec_info, NULL)))
1022
+ goto end;
1023
+
1024
+ sbc->info.charger_spec = charger_spec_info & 0x000f;
1025
+ sbc->info.selector_support = (charger_spec_info & 0x0010) >> 4;
1026
+
1027
+ end:
1028
+ return_VALUE(result);
1029
+}
1030
+
1031
+static int acpi_sbc_get_state(struct acpi_sbc *sbc)
1032
+{
1033
+ struct acpi_ec_smbus *smbus = sbc->sbs->smbus;
1034
+ int result = 0;
1035
+ u16 charger_status;
1036
+
1037
+ ACPI_FUNCTION_TRACE("acpi_sbc_get_state");
1038
+
1039
+ if ((result = acpi_sbs_smbus_read_word(smbus, ACPI_SBC_SMBUS_ADDR, 0x13,
1040
+ &charger_status, NULL)))
1041
+ goto end;
1042
+
1043
+ sbc->state.power_fail = (charger_status & 0x2000) >> 13;
1044
+ sbc->state.battery_present = (charger_status & 0x4000) >> 14;
1045
+ sbc->state.ac_present = (charger_status & 0x8000) >> 15;
1046
+
1047
+ end:
1048
+ return_VALUE(result);
1049
+}
1050
+
1051
+/* --------------------------------------------------------------------------
1052
+ FS Interface (/proc)
1053
+ -------------------------------------------------------------------------- */
1054
+
1055
+static struct proc_dir_entry *acpi_sbs_dir;
1056
+
1057
+/* Generic Routines */
1058
+
1059
+static int
1060
+acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
1061
+ struct proc_dir_entry *parent_dir,
1062
+ char *dir_name,
1063
+ struct file_operations *info_fops,
1064
+ struct file_operations *state_fops,
1065
+ struct file_operations *alarm_fops, void *data)
1066
+{
1067
+ struct proc_dir_entry *entry = NULL;
1068
+
1069
+ ACPI_FUNCTION_TRACE("acpi_sbs_generic_add_fs");
1070
+
1071
+ if (!*dir) {
1072
+ *dir = proc_mkdir(dir_name, parent_dir);
1073
+ if (!*dir)
1074
+ return_VALUE(-ENODEV);
1075
+ (*dir)->owner = THIS_MODULE;
1076
+ }
1077
+
1078
+ /* 'info' [R] */
1079
+ if (info_fops) {
1080
+ entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
1081
+ if (!entry)
1082
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1083
+ "Unable to create '%s' fs entry\n",
1084
+ ACPI_SBS_FILE_INFO));
1085
+ else {
1086
+ entry->proc_fops = info_fops;
1087
+ entry->data = data;
1088
+ entry->owner = THIS_MODULE;
1089
+ }
1090
+ }
1091
+
1092
+ /* 'state' [R] */
1093
+ if (state_fops) {
1094
+ entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
1095
+ if (!entry)
1096
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1097
+ "Unable to create '%s' fs entry\n",
1098
+ ACPI_SBS_FILE_STATE));
1099
+ else {
1100
+ entry->proc_fops = state_fops;
1101
+ entry->data = data;
1102
+ entry->owner = THIS_MODULE;
1103
+ }
1104
+ }
1105
+
1106
+ /* 'alarm' [R/W] */
1107
+ if (alarm_fops) {
1108
+ entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IFREG | S_IRUGO | S_IWUSR, *dir);
1109
+ if (!entry)
1110
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1111
+ "Unable to create '%s' fs entry\n",
1112
+ ACPI_SBS_FILE_ALARM));
1113
+ else {
1114
+ entry->proc_fops = alarm_fops;
1115
+ entry->data = data;
1116
+ entry->owner = THIS_MODULE;
1117
+ }
1118
+ }
1119
+
1120
+ return_VALUE(0);
1121
+}
1122
+
1123
+static void
1124
+acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir,
1125
+ struct proc_dir_entry *parent_dir)
1126
+{
1127
+ ACPI_FUNCTION_TRACE("acpi_sbs_generic_remove_fs");
1128
+
1129
+ if (*dir) {
1130
+ remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
1131
+ remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
1132
+ remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir);
1133
+ remove_proc_entry((*dir)->name, parent_dir);
1134
+ *dir = NULL;
1135
+ }
1136
+
1137
+}
1138
+
1139
+/* Smart Battery Interface */
1140
+
1141
+static int acpi_sb_read_info(struct seq_file *seq, void *offset)
1142
+{
1143
+ struct acpi_sb *sb = (struct acpi_sb *)seq->private;
1144
+ u32 cscale;
1145
+
1146
+ ACPI_FUNCTION_TRACE("acpi_sb_read_info");
1147
+
1148
+ down(&sb->sbs->sem);
1149
+
1150
+ if (acpi_sb_is_present(sb)) {
1151
+ seq_printf(seq, "present: yes\n");
1152
+ } else {
1153
+ seq_printf(seq, "present: no\n");
1154
+ goto end;
1155
+ }
1156
+
1157
+ if (sb->info.capacity_mode)
1158
+ cscale = sb->info.vscale * sb->info.ipscale;
1159
+ else
1160
+ cscale = sb->info.ipscale;
1161
+
1162
+ seq_printf(seq, "design voltage: %d mV\n",
1163
+ sb->info.design_voltage * sb->info.vscale);
1164
+
1165
+ seq_printf(seq, "design capacity: %d%s",
1166
+ sb->info.design_capacity * cscale,
1167
+ sb->info.capacity_mode ? "0 mWh\n" : " mAh\n");
1168
+
1169
+ seq_printf(seq, "full charge capacity: %d%s",
1170
+ sb->info.full_charge_capacity * cscale,
1171
+ sb->info.capacity_mode ? "0 mWh\n" : " mAh\n");
1172
+
1173
+ seq_printf(seq, "cycle count: %d\n", sb->info.cycle_count);
1174
+
1175
+ seq_printf(seq, "charge reporting error: %d%%\n", sb->info.max_error);
1176
+
1177
+ seq_printf(seq, "SB specification: ");
1178
+ switch (sb->info.specid) {
1179
+ case 0x10:
1180
+ seq_printf(seq, "v1.0\n");
1181
+ break;
1182
+ case 0x21:
1183
+ seq_printf(seq, "v1.1 (without PEC)\n");
1184
+ break;
1185
+ case 0x31:
1186
+ seq_printf(seq, "v1.1 (with PEC)\n");
1187
+ break;
1188
+ default:
1189
+ seq_printf(seq, "unknown\n");
1190
+ }
1191
+
1192
+ seq_printf(seq, "manufacturer name: %s\n",
1193
+ sb->info.manufacturer_name);
1194
+
1195
+ seq_printf(seq, "manufacture date: %4d-%2d-%2d\n",
1196
+ sb->info.manufacture_year,
1197
+ sb->info.manufacture_month, sb->info.manufacture_day);
1198
+
1199
+ seq_printf(seq, "serial number: %d\n",
1200
+ sb->info.serial_number);
1201
+
1202
+ seq_printf(seq, "device name: %s\n", sb->info.device_name);
1203
+
1204
+ seq_printf(seq, "device chemistry: %s\n",
1205
+ sb->info.device_chemistry);
1206
+
1207
+ end:
1208
+ up(&sb->sbs->sem);
1209
+
1210
+ return_VALUE(0);
1211
+}
1212
+
1213
+static int acpi_sb_info_open_fs(struct inode *inode, struct file *file)
1214
+{
1215
+ return single_open(file, acpi_sb_read_info, PDE(inode)->data);
1216
+}
1217
+
1218
+static int acpi_sb_read_state(struct seq_file *seq, void *offset)
1219
+{
1220
+ struct acpi_sb *sb = (struct acpi_sb *)seq->private;
1221
+ int result = 0;
1222
+ u32 cscale;
1223
+
1224
+ ACPI_FUNCTION_TRACE("acpi_sb_read_state");
1225
+
1226
+ down(&sb->sbs->sem);
1227
+
1228
+ if (acpi_sb_is_present(sb)) {
1229
+ seq_printf(seq, "present: yes\n");
1230
+ } else {
1231
+ seq_printf(seq, "present: no\n");
1232
+ goto end;
1233
+ }
1234
+
1235
+ result = acpi_sb_check_init_state(sb);
1236
+ if (result) {
1237
+ seq_printf(seq, "ERROR: Unable to read battery information\n");
1238
+ goto end;
1239
+ }
1240
+ result = acpi_sb_get_state(sb);
1241
+ if (result) {
1242
+ seq_printf(seq, "ERROR: Unable to read battery state\n");
1243
+ goto end;
1244
+ }
1245
+
1246
+ if (sb->info.capacity_mode)
1247
+ cscale = sb->info.vscale * sb->info.ipscale;
1248
+ else
1249
+ cscale = sb->info.ipscale;
1250
+
1251
+ if (sb->state.amperage < 0) {
1252
+ seq_printf(seq, "charging state: discharging\n");
1253
+ seq_printf(seq, "current: %d mA\n",
1254
+ -sb->state.amperage * sb->info.ipscale);
1255
+ } else if (sb->state.amperage > 0) {
1256
+ seq_printf(seq, "charging state: charging\n");
1257
+ seq_printf(seq, "current: %d mA\n",
1258
+ sb->state.amperage * sb->info.ipscale);
1259
+ } else {
1260
+ seq_printf(seq, "charging state: charged\n");
1261
+ seq_printf(seq, "current: 0 mA\n");
1262
+ }
1263
+
1264
+ seq_printf(seq, "average current %d mA\n",
1265
+ abs(sb->state.average_amperage * sb->info.ipscale));
1266
+
1267
+ seq_printf(seq, "voltage: %d mV\n",
1268
+ sb->state.voltage * sb->info.vscale);
1269
+
1270
+ seq_printf(seq, "temperature: %d.%d C\n",
1271
+ sb->state.temperature / 10 - 273,
1272
+ sb->state.temperature % 10 + 1);
1273
+
1274
+ seq_printf(seq, "relative charge: %d%%\n",
1275
+ sb->state.relative_state_of_charge);
1276
+
1277
+ seq_printf(seq, "absolute charge: %d%%\n",
1278
+ sb->state.absolute_state_of_charge);
1279
+
1280
+ seq_printf(seq, "remaining capacity: %d%s",
1281
+ sb->state.remaining_capacity * cscale,
1282
+ sb->info.capacity_mode ? "0 mWh\n" : " mAh\n");
1283
+
1284
+ if (sb->state.run_time_to_empty == 65535)
1285
+ seq_printf(seq, "run time to empty: n/a\n");
1286
+ else
1287
+ seq_printf(seq, "run time to empty: %dh %02dm\n",
1288
+ sb->state.run_time_to_empty / 60,
1289
+ sb->state.run_time_to_empty % 60);
1290
+
1291
+ if (sb->state.average_time_to_empty == 65535)
1292
+ seq_printf(seq, "average time to empty: n/a\n");
1293
+ else
1294
+ seq_printf(seq, "average time to empty: %dh %02dm\n",
1295
+ sb->state.average_time_to_empty / 60,
1296
+ sb->state.average_time_to_empty % 60);
1297
+
1298
+ if (sb->state.average_time_to_full == 65535)
1299
+ seq_printf(seq, "average time to full: n/a\n");
1300
+ else
1301
+ seq_printf(seq, "average time to full: %dh %02dm\n",
1302
+ sb->state.average_time_to_full / 60,
1303
+ sb->state.average_time_to_full % 60);
1304
+
1305
+ end:
1306
+ up(&sb->sbs->sem);
1307
+
1308
+ return_VALUE(result);
1309
+}
1310
+
1311
+static int acpi_sb_state_open_fs(struct inode *inode, struct file *file)
1312
+{
1313
+ return single_open(file, acpi_sb_read_state, PDE(inode)->data);
1314
+}
1315
+
1316
+static int acpi_sb_read_alarm(struct seq_file *seq, void *offset)
1317
+{
1318
+ struct acpi_sb *sb = (struct acpi_sb *)seq->private;
1319
+ int result = 0;
1320
+ u32 cscale;
1321
+
1322
+ ACPI_FUNCTION_TRACE("acpi_sb_read_alarm");
1323
+
1324
+ down(&sb->sbs->sem);
1325
+
1326
+ if (acpi_sb_is_present(sb)) {
1327
+ seq_printf(seq, "present: yes\n");
1328
+ } else {
1329
+ seq_printf(seq, "present: no\n");
1330
+ goto end;
1331
+ }
1332
+
1333
+ result = acpi_sb_check_init_state(sb);
1334
+ if (result) {
1335
+ seq_printf(seq, "ERROR: Unable to read battery information\n");
1336
+ goto end;
1337
+ }
1338
+
1339
+ result = acpi_sb_get_alarm(sb);
1340
+ if (result) {
1341
+ seq_printf(seq, "ERROR: Unable to read battery alarm\n");
1342
+ goto end;
1343
+ }
1344
+
1345
+ if (sb->info.capacity_mode)
1346
+ cscale = sb->info.vscale * sb->info.ipscale;
1347
+ else
1348
+ cscale = sb->info.ipscale;
1349
+
1350
+ seq_printf(seq, "remain capacity alarm: ");
1351
+ if (sb->alarm.remaining_capacity)
1352
+ seq_printf(seq, "%d%s",
1353
+ sb->alarm.remaining_capacity * cscale,
1354
+ sb->info.capacity_mode ? "0 mWh\n" : " mAh\n");
1355
+ else
1356
+ seq_printf(seq, "disabled\n");
1357
+
1358
+ seq_printf(seq, "remain time alarm: ");
1359
+ if (sb->alarm.remaining_time)
1360
+ seq_printf(seq, "%dh %02dm\n",
1361
+ sb->alarm.remaining_time / 60,
1362
+ sb->alarm.remaining_time % 60);
1363
+ else
1364
+ seq_printf(seq, "disabled\n");
1365
+
1366
+ end:
1367
+ up(&sb->sbs->sem);
1368
+
1369
+ return_VALUE(result);
1370
+}
1371
+
1372
+static ssize_t
1373
+acpi_sb_write_alarm(struct file *file, const char __user * buffer,
1374
+ size_t count, loff_t * ppos)
1375
+{
1376
+ struct seq_file *seq = (struct seq_file *)file->private_data;
1377
+ struct acpi_sb *sb = (struct acpi_sb *)seq->private;
1378
+ char alarm_string[16] = { '\0' };
1379
+ int alarm_values[3];
1380
+ char *term;
1381
+ int result;
1382
+
1383
+ ACPI_FUNCTION_TRACE("acpi_sb_write_alarm");
1384
+
1385
+ down(&sb->sbs->sem);
1386
+
1387
+ if (!acpi_sb_is_present(sb)) {
1388
+ result = -ENODEV;
1389
+ goto end;
1390
+ }
1391
+
1392
+ result = acpi_sb_check_init_state(sb);
1393
+ if (result) {
1394
+ seq_printf(seq, "ERROR: Unable to read battery information\n");
1395
+ goto end;
1396
+ }
1397
+
1398
+ if (count > sizeof(alarm_string) - 1) {
1399
+ result = -EINVAL;
1400
+ goto end;
1401
+ }
1402
+
1403
+ if (copy_from_user(alarm_string, buffer, count)) {
1404
+ result = -EFAULT;
1405
+ goto end;
1406
+ }
1407
+
1408
+ alarm_string[count] = 0;
1409
+ term = get_options(alarm_string, 3, alarm_values);
1410
+
1411
+ if (alarm_values[0] > 0) {
1412
+ if (alarm_values[1] >= 0 && alarm_values[1] <= 65535) {
1413
+ sb->alarm.remaining_capacity = alarm_values[1];
1414
+ } else {
1415
+ result = -EINVAL;
1416
+ goto end;
1417
+ }
1418
+ }
1419
+
1420
+ if (alarm_values[0] > 1) {
1421
+ if (alarm_values[2] >= 0 && alarm_values[2] <= 65535) {
1422
+ sb->alarm.remaining_time = alarm_values[2];
1423
+ } else {
1424
+ result = -EINVAL;
1425
+ goto end;
1426
+ }
1427
+ }
1428
+
1429
+ result = acpi_sb_set_alarm(sb);
1430
+
1431
+ end:
1432
+ up(&sb->sbs->sem);
1433
+
1434
+ if (result)
1435
+ return_VALUE(result);
1436
+ else
1437
+ return_VALUE(count);
1438
+}
1439
+
1440
+static int acpi_sb_alarm_open_fs(struct inode *inode, struct file *file)
1441
+{
1442
+ return single_open(file, acpi_sb_read_alarm, PDE(inode)->data);
1443
+}
1444
+
1445
+static struct file_operations acpi_sb_info_fops = {
1446
+ .owner = THIS_MODULE,
1447
+ .open = acpi_sb_info_open_fs,
1448
+ .read = seq_read,
1449
+ .llseek = seq_lseek,
1450
+ .release = single_release,
1451
+};
1452
+
1453
+static struct file_operations acpi_sb_state_fops = {
1454
+ .owner = THIS_MODULE,
1455
+ .open = acpi_sb_state_open_fs,
1456
+ .read = seq_read,
1457
+ .llseek = seq_lseek,
1458
+ .release = single_release,
1459
+};
1460
+
1461
+static struct file_operations acpi_sb_alarm_fops = {
1462
+ .owner = THIS_MODULE,
1463
+ .open = acpi_sb_alarm_open_fs,
1464
+ .read = seq_read,
1465
+ .write = acpi_sb_write_alarm,
1466
+ .llseek = seq_lseek,
1467
+ .release = single_release,
1468
+};
1469
+
1470
+/* Smart Battery System Manager / Smart Battery Selector Interface */
1471
+
1472
+static int acpi_sbsm_read_info(struct seq_file *seq, void *offset)
1473
+{
1474
+ struct acpi_sbsm *sbsm = (struct acpi_sbsm *)seq->private;
1475
+ u8 id;
1476
+
1477
+ ACPI_FUNCTION_TRACE("acpi_sbsm_read_info");
1478
+
1479
+ down(&sbsm->sbs->sem);
1480
+
1481
+ seq_printf(seq, "batteries supported: ");
1482
+ for (id = 0; id <= 3; id++) {
1483
+ if (sbsm->info.batteries_supported & (1 << id))
1484
+ seq_printf(seq, " " ACPI_SB_DIR_NAME, id);
1485
+ }
1486
+ seq_printf(seq, "\n");
1487
+
1488
+ if (sbsm->class == ACPI_SBSM_CLASS) {
1489
+ seq_printf(seq, "SBSM specification: ");
1490
+
1491
+ switch (sbsm->info.battery_system_revision) {
1492
+ case 0x0008:
1493
+ seq_printf(seq, "v1.0 (without PEC)\n");
1494
+ break;
1495
+ case 0x0009:
1496
+ seq_printf(seq, "v1.0 (with PEC)\n");
1497
+ break;
1498
+ default:
1499
+ seq_printf(seq, "unknown\n");
1500
+ }
1501
+ } else {
1502
+ seq_printf(seq, "SBSEL specification: ");
1503
+
1504
+ switch (sbsm->info.battery_system_revision) {
1505
+ case 0x0001:
1506
+ seq_printf(seq, "v1.0\n");
1507
+ break;
1508
+ case 0x0002:
1509
+ seq_printf(seq, "v1.1 (without PEC)\n");
1510
+ break;
1511
+ case 0x0003:
1512
+ seq_printf(seq, "v1.1 (with PEC)\n");
1513
+ break;
1514
+ default:
1515
+ seq_printf(seq, "unknown\n");
1516
+ }
1517
+ }
1518
+
1519
+ up(&sbsm->sbs->sem);
1520
+
1521
+ return_VALUE(0);
1522
+}
1523
+
1524
+static int acpi_sbsm_info_open_fs(struct inode *inode, struct file *file)
1525
+{
1526
+ return single_open(file, acpi_sbsm_read_info, PDE(inode)->data);
1527
+}
1528
+
1529
+static int acpi_sbsm_read_state(struct seq_file *seq, void *offset)
1530
+{
1531
+ struct acpi_sbsm *sbsm = (struct acpi_sbsm *)seq->private;
1532
+ int result = 0;
1533
+ u8 id;
1534
+
1535
+ ACPI_FUNCTION_TRACE("acpi_sbsm_read_state");
1536
+
1537
+ down(&sbsm->sbs->sem);
1538
+
1539
+ result = acpi_sbsm_get_state(sbsm);
1540
+
1541
+ if (result) {
1542
+ seq_printf(seq,
1543
+ "ERROR: Unable to read battery system manager / selector state\n");
1544
+ goto end;
1545
+ }
1546
+
1547
+ if (sbsm->class == ACPI_SBSEL_CLASS) {
1548
+ result = acpi_sbsm_get_state(sbsm);
1549
+ if (result) {
1550
+ seq_printf(seq,
1551
+ "ERROR: Unable to read charger state\n");
1552
+ goto end;
1553
+ }
1554
+ }
1555
+
1556
+ seq_printf(seq, "batteries present: ");
1557
+ if (!sbsm->state.present_x) {
1558
+ seq_printf(seq, " none");
1559
+ } else {
1560
+ for (id = 0; id <= 3; id++) {
1561
+ if (sbsm->state.present_x & (1 << id))
1562
+ seq_printf(seq, " " ACPI_SB_DIR_NAME, id);
1563
+ }
1564
+ }
1565
+ seq_printf(seq, "\n");
1566
+
1567
+ seq_printf(seq, "batteries charging: ");
1568
+ if (sbsm->class == ACPI_SBSEL_CLASS && !sbsm->info.charging_indicator) {
1569
+ if (sbsm->sbs->sbc->state.battery_present)
1570
+ seq_printf(seq, " yes\n");
1571
+ else
1572
+ seq_printf(seq, " no\n");
1573
+ } else {
1574
+ if (!sbsm->state.charge_x) {
1575
+ seq_printf(seq, " none");
1576
+ } else {
1577
+ for (id = 0; id <= 3; id++) {
1578
+ if (sbsm->state.charge_x & (1 << id))
1579
+ seq_printf(seq, " " ACPI_SB_DIR_NAME,
1580
+ id);
1581
+ }
1582
+ }
1583
+ seq_printf(seq, "\n");
1584
+ }
1585
+
1586
+ if (sbsm->state.ac_present) {
1587
+ seq_printf(seq, "system powered by: AC\n");
1588
+ } else {
1589
+ seq_printf(seq, "system powered by: ");
1590
+ for (id = 0; id <= 3; id++) {
1591
+ if (sbsm->state.power_by_x & (1 << id))
1592
+ seq_printf(seq, " " ACPI_SB_DIR_NAME, id);
1593
+ }
1594
+ seq_printf(seq, "\n");
1595
+ }
1596
+
1597
+ if (sbsm->state.ac_present) {
1598
+ if (sbsm->class == ACPI_SBSM_CLASS)
1599
+ seq_printf(seq, "AC sufficient: %s\n",
1600
+ sbsm->state.power_not_good ? "no" : "yes");
1601
+ else
1602
+ seq_printf(seq, "AC sufficient: %s\n",
1603
+ sbsm->sbs->sbc->state.
1604
+ power_fail ? "no" : "yes");
1605
+ } else {
1606
+ seq_printf(seq, "AC sufficient: n/a\n");
1607
+ }
1608
+
1609
+ end:
1610
+ up(&sbsm->sbs->sem);
1611
+
1612
+ return_VALUE(result);
1613
+}
1614
+
1615
+static int acpi_sbsm_state_open_fs(struct inode *inode, struct file *file)
1616
+{
1617
+ return single_open(file, acpi_sbsm_read_state, PDE(inode)->data);
1618
+}
1619
+
1620
+static struct file_operations acpi_sbsm_info_fops = {
1621
+ .owner = THIS_MODULE,
1622
+ .open = acpi_sbsm_info_open_fs,
1623
+ .read = seq_read,
1624
+ .llseek = seq_lseek,
1625
+ .release = single_release,
1626
+};
1627
+
1628
+static struct file_operations acpi_sbsm_state_fops = {
1629
+ .owner = THIS_MODULE,
1630
+ .open = acpi_sbsm_state_open_fs,
1631
+ .read = seq_read,
1632
+ .llseek = seq_lseek,
1633
+ .release = single_release,
1634
+};
1635
+
1636
+/* Smart Battery Charger Interface */
1637
+
1638
+static int acpi_sbc_read_info(struct seq_file *seq, void *offset)
1639
+{
1640
+ struct acpi_sbc *sbc = (struct acpi_sbc *)seq->private;
1641
+
1642
+ ACPI_FUNCTION_TRACE("acpi_sbc_read_info");
1643
+
1644
+ down(&sbc->sbs->sem);
1645
+
1646
+ seq_printf(seq, "SBC specification: ");
1647
+
1648
+ switch (sbc->info.charger_spec) {
1649
+ case 0x0001:
1650
+ seq_printf(seq, "v1.0\n");
1651
+ break;
1652
+ case 0x0002:
1653
+ seq_printf(seq, "v1.1 (without PEC)\n");
1654
+ break;
1655
+ case 0x0003:
1656
+ seq_printf(seq, "v1.1 (with PEC)\n");
1657
+ break;
1658
+ default:
1659
+ seq_printf(seq, "unknown\n");
1660
+ }
1661
+
1662
+ seq_printf(seq, "Embedded SBSEL support: %s\n",
1663
+ sbc->info.selector_support ? "yes" : "no");
1664
+
1665
+ up(&sbc->sbs->sem);
1666
+
1667
+ return_VALUE(0);
1668
+}
1669
+
1670
+static int acpi_sbc_info_open_fs(struct inode *inode, struct file *file)
1671
+{
1672
+ return single_open(file, acpi_sbc_read_info, PDE(inode)->data);
1673
+}
1674
+
1675
+static int acpi_sbc_read_state(struct seq_file *seq, void *offset)
1676
+{
1677
+ struct acpi_sbc *sbc = (struct acpi_sbc *)seq->private;
1678
+ int result = 0;
1679
+
1680
+ ACPI_FUNCTION_TRACE("acpi_sbc_read_state");
1681
+
1682
+ down(&sbc->sbs->sem);
1683
+
1684
+ result = acpi_sbc_get_state(sbc);
1685
+
1686
+ if (result) {
1687
+ seq_printf(seq,
1688
+ "ERROR: Unable to read battery charger state\n");
1689
+ goto end;
1690
+ }
1691
+
1692
+ seq_printf(seq, "battery charging: %s\n",
1693
+ sbc->state.battery_present ? "yes" : "no");
1694
+
1695
+ seq_printf(seq, "system powered by: %s\n",
1696
+ sbc->state.ac_present ? "AC" : "battery");
1697
+
1698
+ if (sbc->state.ac_present)
1699
+ seq_printf(seq, "AC sufficient: %s\n",
1700
+ sbc->state.power_fail ? "no" : "yes");
1701
+ else
1702
+ seq_printf(seq, "AC sufficient: n/a\n");
1703
+
1704
+ end:
1705
+ up(&sbc->sbs->sem);
1706
+
1707
+ return_VALUE(result);
1708
+}
1709
+
1710
+static int acpi_sbc_state_open_fs(struct inode *inode, struct file *file)
1711
+{
1712
+ return single_open(file, acpi_sbc_read_state, PDE(inode)->data);
1713
+}
1714
+
1715
+static struct file_operations acpi_sbc_info_fops = {
1716
+ .owner = THIS_MODULE,
1717
+ .open = acpi_sbc_info_open_fs,
1718
+ .read = seq_read,
1719
+ .llseek = seq_lseek,
1720
+ .release = single_release,
1721
+};
1722
+
1723
+static struct file_operations acpi_sbc_state_fops = {
1724
+ .owner = THIS_MODULE,
1725
+ .open = acpi_sbc_state_open_fs,
1726
+ .read = seq_read,
1727
+ .llseek = seq_lseek,
1728
+ .release = single_release,
1729
+};
1730
+
1731
+/* Legacy Battery Interface */
1732
+
1733
+static struct proc_dir_entry *acpi_lbattery_dir = NULL;
1734
+
1735
+static int acpi_lbattery_read_info(struct seq_file *seq, void *offset)
1736
+{
1737
+ struct acpi_sb *sb = (struct acpi_sb *)seq->private;
1738
+ u32 cscale;
1739
+ int result = 0;
1740
+
1741
+ ACPI_FUNCTION_TRACE("acpi_lbattery_read_info");
1742
+
1743
+ down(&sb->sbs->sem);
1744
+
1745
+ if (acpi_sb_is_present(sb)) {
1746
+ seq_printf(seq, "present: yes\n");
1747
+ } else {
1748
+ seq_printf(seq, "present: no\n");
1749
+ goto end;
1750
+ }
1751
+
1752
+ result = acpi_sb_check_init_state(sb);
1753
+ if (result) {
1754
+ seq_printf(seq, "ERROR: Unable to read battery information\n");
1755
+ goto end;
1756
+ }
1757
+
1758
+ if (sb->info.capacity_mode)
1759
+ cscale = sb->info.vscale * sb->info.ipscale;
1760
+ else
1761
+ cscale = sb->info.ipscale;
1762
+
1763
+ seq_printf(seq, "design capacity: %d%s",
1764
+ sb->info.design_capacity * cscale,
1765
+ sb->info.capacity_mode ? "0 mWh\n" : " mAh\n");
1766
+
1767
+ seq_printf(seq, "last full capacity: %d%s",
1768
+ sb->info.full_charge_capacity * cscale,
1769
+ sb->info.capacity_mode ? "0 mWh\n" : " mAh\n");
1770
+
1771
+ seq_printf(seq, "battery technology: rechargeable\n");
1772
+
1773
+ seq_printf(seq, "design voltage: %d mV\n",
1774
+ sb->info.design_voltage * sb->info.vscale);
1775
+
1776
+ seq_printf(seq, "design capacity warning: unknown\n");
1777
+ seq_printf(seq, "design capacity low: unknown\n");
1778
+ seq_printf(seq, "capacity granularity 1: unknown\n");
1779
+ seq_printf(seq, "capacity granularity 2: unknown\n");
1780
+
1781
+ seq_printf(seq, "model number: %s\n", sb->info.device_name);
1782
+
1783
+ seq_printf(seq, "serial number: %d\n",
1784
+ sb->info.serial_number);
1785
+
1786
+ seq_printf(seq, "battery type: %s\n",
1787
+ sb->info.device_chemistry);
1788
+
1789
+ seq_printf(seq, "OEM info: %s\n",
1790
+ sb->info.manufacturer_name);
1791
+
1792
+ end:
1793
+ up(&sb->sbs->sem);
1794
+
1795
+ return_VALUE(result);
1796
+}
1797
+
1798
+static int acpi_lbattery_info_open_fs(struct inode *inode, struct file *file)
1799
+{
1800
+ return single_open(file, acpi_lbattery_read_info, PDE(inode)->data);
1801
+}
1802
+
1803
+static int acpi_lbattery_read_state(struct seq_file *seq, void *offset)
1804
+{
1805
+ struct acpi_sb *sb = (struct acpi_sb *)seq->private;
1806
+ int result = 0;
1807
+ u32 cscale;
1808
+
1809
+ ACPI_FUNCTION_TRACE("acpi_lbattery_read_state");
1810
+
1811
+ down(&sb->sbs->sem);
1812
+
1813
+ if (acpi_sb_is_present(sb)) {
1814
+ seq_printf(seq, "present: yes\n");
1815
+ } else {
1816
+ seq_printf(seq, "present: no\n");
1817
+ goto end;
1818
+ }
1819
+
1820
+ result = acpi_sb_check_init_state(sb);
1821
+ if (result) {
1822
+ seq_printf(seq, "ERROR: Unable to read battery information\n");
1823
+ goto end;
1824
+ }
1825
+
1826
+ result = acpi_sb_get_state(sb);
1827
+ if (result) {
1828
+ seq_printf(seq, "ERROR: Unable to read battery state\n");
1829
+ goto end;
1830
+ }
1831
+
1832
+ if (sb->info.capacity_mode)
1833
+ cscale = sb->info.vscale * sb->info.ipscale;
1834
+ else
1835
+ cscale = sb->info.ipscale;
1836
+
1837
+ if (sb->state.battery_status & 0x0010)
1838
+ seq_printf(seq, "capacity state: critical\n");
1839
+ else
1840
+ seq_printf(seq, "capacity state: ok\n");
1841
+
1842
+ if ((s16) sb->state.amperage < 0) {
1843
+ seq_printf(seq, "charging state: discharging\n");
1844
+ if (sb->state.average_time_to_empty)
1845
+ seq_printf(seq, "present rate: %d%s\n",
1846
+ sb->state.remaining_capacity * cscale * 60 /
1847
+ sb->state.average_time_to_empty,
1848
+ sb->info.capacity_mode ? "0 mW" : " mA");
1849
+ else
1850
+ seq_printf(seq, "present rate: n/a\n");
1851
+ } else if ((s16) sb->state.amperage > 0) {
1852
+ seq_printf(seq, "charging state: charging\n");
1853
+ if (sb->state.average_time_to_full)
1854
+ seq_printf(seq, "present rate: %d%s\n",
1855
+ (sb->info.full_charge_capacity -
1856
+ sb->state.remaining_capacity) * cscale * 60 /
1857
+ sb->state.average_time_to_full,
1858
+ sb->info.capacity_mode ? "0 mW" : " mA");
1859
+ else
1860
+ seq_printf(seq, "present rate: n/a\n");
1861
+ } else {
1862
+ seq_printf(seq, "charging state: charged\n");
1863
+ seq_printf(seq, "present rate: 0 %s\n",
1864
+ sb->info.capacity_mode ? "mW" : "mA");
1865
+ }
1866
+
1867
+ seq_printf(seq, "remaining capacity: %d%s",
1868
+ sb->state.remaining_capacity * cscale,
1869
+ sb->info.capacity_mode ? "0 mWh\n" : " mAh\n");
1870
+
1871
+ seq_printf(seq, "present voltage: %d mV\n",
1872
+ sb->state.voltage * sb->info.vscale);
1873
+
1874
+ end:
1875
+ up(&sb->sbs->sem);
1876
+
1877
+ return_VALUE(result);
1878
+}
1879
+
1880
+static int acpi_lbattery_state_open_fs(struct inode *inode, struct file *file)
1881
+{
1882
+ return single_open(file, acpi_lbattery_read_state, PDE(inode)->data);
1883
+}
1884
+
1885
+static int acpi_lbattery_read_alarm(struct seq_file *seq, void *offset)
1886
+{
1887
+ struct acpi_sb *sb = (struct acpi_sb *)seq->private;
1888
+ int result = 0;
1889
+ u32 cscale;
1890
+
1891
+ ACPI_FUNCTION_TRACE("acpi_lbattery_read_alarm");
1892
+
1893
+ down(&sb->sbs->sem);
1894
+
1895
+ if (!acpi_sb_is_present(sb)) {
1896
+ seq_printf(seq, "present: no\n");
1897
+ goto end;
1898
+ }
1899
+
1900
+ result = acpi_sb_check_init_state(sb);
1901
+ if (result) {
1902
+ seq_printf(seq, "ERROR: Unable to read battery information\n");
1903
+ goto end;
1904
+ }
1905
+
1906
+ result = acpi_sb_get_alarm(sb);
1907
+
1908
+ if (result) {
1909
+ seq_printf(seq, "ERROR: Unable to read battery alarm\n");
1910
+ goto end;
1911
+ }
1912
+
1913
+ if (sb->info.capacity_mode)
1914
+ cscale = sb->info.vscale * sb->info.ipscale;
1915
+ else
1916
+ cscale = sb->info.ipscale;
1917
+
1918
+ seq_printf(seq, "alarm: ");
1919
+ if (sb->alarm.remaining_capacity)
1920
+ seq_printf(seq, "%d%s",
1921
+ sb->alarm.remaining_capacity * cscale,
1922
+ sb->info.capacity_mode ? "0 mWh\n" : " mAh\n");
1923
+ else
1924
+ seq_printf(seq, "disabled\n");
1925
+
1926
+ end:
1927
+ up(&sb->sbs->sem);
1928
+
1929
+ return_VALUE(result);
1930
+}
1931
+
1932
+static ssize_t
1933
+acpi_lbattery_write_alarm(struct file *file, const char __user * buffer,
1934
+ size_t count, loff_t * ppos)
1935
+{
1936
+ struct seq_file *seq = (struct seq_file *)file->private_data;
1937
+ struct acpi_sb *sb = (struct acpi_sb *)seq->private;
1938
+ char alarm_string[6] = { '\0' };
1939
+ int alarm_values[2];
1940
+ char *term;
1941
+ int result;
1942
+
1943
+ ACPI_FUNCTION_TRACE("acpi_lbattery_write_alarm");
1944
+
1945
+ down(&sb->sbs->sem);
1946
+
1947
+ if (!acpi_sb_is_present(sb)) {
1948
+ result = -ENODEV;
1949
+ goto end;
1950
+ }
1951
+
1952
+ result = acpi_sb_check_init_state(sb);
1953
+ if (result) {
1954
+ seq_printf(seq, "ERROR: Unable to read battery information\n");
1955
+ goto end;
1956
+ }
1957
+
1958
+ if (count > sizeof(alarm_string) - 1) {
1959
+ result = -EINVAL;
1960
+ goto end;
1961
+ }
1962
+
1963
+ if (copy_from_user(alarm_string, buffer, count)) {
1964
+ result = -EFAULT;
1965
+ goto end;
1966
+ }
1967
+
1968
+ alarm_string[count] = 0;
1969
+ term = get_options(alarm_string, 2, alarm_values);
1970
+
1971
+ if (alarm_values[0] > 0) {
1972
+ if (alarm_values[1] >= 0 && alarm_values[1] <= 65535) {
1973
+ sb->alarm.remaining_capacity = alarm_values[1];
1974
+ } else {
1975
+ result = -EINVAL;
1976
+ goto end;
1977
+ }
1978
+ }
1979
+
1980
+ result = acpi_sb_set_alarm(sb);
1981
+
1982
+ end:
1983
+ up(&sb->sbs->sem);
1984
+
1985
+ if (result)
1986
+ return_VALUE(result);
1987
+ else
1988
+ return_VALUE(count);
1989
+}
1990
+
1991
+static int acpi_lbattery_alarm_open_fs(struct inode *inode, struct file *file)
1992
+{
1993
+ return single_open(file, acpi_lbattery_read_alarm, PDE(inode)->data);
1994
+}
1995
+
1996
+static struct file_operations acpi_lbattery_info_fops = {
1997
+ .owner = THIS_MODULE,
1998
+ .open = acpi_lbattery_info_open_fs,
1999
+ .read = seq_read,
2000
+ .llseek = seq_lseek,
2001
+ .release = single_release,
2002
+};
2003
+
2004
+static struct file_operations acpi_lbattery_state_fops = {
2005
+ .owner = THIS_MODULE,
2006
+ .open = acpi_lbattery_state_open_fs,
2007
+ .read = seq_read,
2008
+ .llseek = seq_lseek,
2009
+ .release = single_release,
2010
+};
2011
+
2012
+static struct file_operations acpi_lbattery_alarm_fops = {
2013
+ .owner = THIS_MODULE,
2014
+ .open = acpi_lbattery_alarm_open_fs,
2015
+ .read = seq_read,
2016
+ .write = acpi_lbattery_write_alarm,
2017
+ .llseek = seq_lseek,
2018
+ .release = single_release,
2019
+};
2020
+
2021
+/* Legacy AC Adapter Interface */
2022
+
2023
+static struct proc_dir_entry *acpi_ladapter_dir = NULL;
2024
+
2025
+static int acpi_ladapter_read_state(struct seq_file *seq, void *offset)
2026
+{
2027
+ struct acpi_sbc *sbc = (struct acpi_sbc *)seq->private;
2028
+ int result = 0;
2029
+
2030
+ ACPI_FUNCTION_TRACE("acpi_ladapter_read_state");
2031
+
2032
+ down(&sbc->sbs->sem);
2033
+
2034
+ result = acpi_sbc_get_state(sbc);
2035
+ if (result) {
2036
+ seq_printf(seq, "ERROR: Unable to read charger state\n");
2037
+ goto end;
2038
+ }
2039
+
2040
+ seq_printf(seq, "state: %s\n",
2041
+ sbc->state.ac_present ? "on-line" : "off-line");
2042
+
2043
+ end:
2044
+ up(&sbc->sbs->sem);
2045
+
2046
+ return_VALUE(result);
2047
+}
2048
+
2049
+static int acpi_ladapter_state_open_fs(struct inode *inode, struct file *file)
2050
+{
2051
+ return single_open(file, acpi_ladapter_read_state, PDE(inode)->data);
2052
+}
2053
+
2054
+static struct file_operations acpi_ladapter_state_fops = {
2055
+ .owner = THIS_MODULE,
2056
+ .open = acpi_ladapter_state_open_fs,
2057
+ .read = seq_read,
2058
+ .llseek = seq_lseek,
2059
+ .release = single_release,
2060
+};
2061
+
2062
+/* --------------------------------------------------------------------------
2063
+ Driver Interface
2064
+ -------------------------------------------------------------------------- */
2065
+
2066
+/* Smart Battery */
2067
+
2068
+static int acpi_sb_add(struct acpi_sbs *sbs, u8 id)
2069
+{
2070
+ int is_present;
2071
+ int result;
2072
+ char dir_name[5];
2073
+ struct acpi_sb *sb;
2074
+
2075
+ ACPI_FUNCTION_TRACE("acpi_sb_add");
2076
+
2077
+ sb = &sbs->sb[id];
2078
+
2079
+ sb->init_state = 0;
2080
+ sb->id = id;
2081
+ sb->sbs = sbs;
2082
+
2083
+ is_present = acpi_sb_is_present(sb);
2084
+
2085
+ if (is_present) {
2086
+ result = acpi_sb_init(sb);
2087
+ if (result) {
2088
+ goto end;
2089
+ }
2090
+ sb->init_state = 1;
2091
+ }
2092
+
2093
+ result = sprintf(dir_name, ACPI_SB_DIR_NAME, id);
2094
+ result = acpi_sbs_generic_add_fs(&sb->sb_entry,
2095
+ acpi_device_dir(sbs->device),
2096
+ dir_name,
2097
+ &acpi_sb_info_fops,
2098
+ &acpi_sb_state_fops,
2099
+ &acpi_sb_alarm_fops, sb);
2100
+
2101
+ if (result) {
2102
+ goto end;
2103
+ }
2104
+ printk(KERN_INFO PREFIX "SBS: %s Slot [" ACPI_SB_DIR_NAME "] (battery %s)\n",
2105
+ ACPI_SB_DEVICE_NAME, id, is_present ? "present" : "absent");
2106
+
2107
+ result = sprintf(dir_name, ACPI_LBATTERY_DIR_NAME, id);
2108
+ if (result < 0) {
2109
+ goto end;
2110
+ }
2111
+ result = acpi_sbs_generic_add_fs(&sb->lbattery_entry,
2112
+ acpi_lbattery_dir,
2113
+ dir_name,
2114
+ &acpi_lbattery_info_fops,
2115
+ &acpi_lbattery_state_fops,
2116
+ &acpi_lbattery_alarm_fops, sb);
2117
+ if (result) {
2118
+ goto end;
2119
+ }
2120
+
2121
+ end:
2122
+ return_VALUE(result);
2123
+}
2124
+
2125
+static void acpi_sb_remove(struct acpi_sbs *sbs, u8 id)
2126
+{
2127
+ ACPI_FUNCTION_TRACE("acpi_sb_remove");
2128
+
2129
+ acpi_sbs_generic_remove_fs(&(sbs->sb[id].sb_entry),
2130
+ acpi_device_dir(sbs->device));
2131
+
2132
+ acpi_sbs_generic_remove_fs(&(sbs->sb[id].lbattery_entry),
2133
+ acpi_lbattery_dir);
2134
+}
2135
+
2136
+/* Smart Battery System Manager / Smart Battery Selector */
2137
+
2138
+static int acpi_sbsm_add(struct acpi_sbs *sbs)
2139
+{
2140
+ int result;
2141
+ u16 battery_system_revision;
2142
+
2143
+ ACPI_FUNCTION_TRACE("acpi_sbsm_add");
2144
+
2145
+ sbs->sbsm->sbs = sbs;
2146
+
2147
+ /* Identify whether this is a System Manager or Selector */
2148
+
2149
+ result =
2150
+ acpi_sbs_smbus_read_word(sbs->smbus, ACPI_SBSM_SMBUS_ADDR, 0x04,
2151
+ &battery_system_revision, NULL);
2152
+ if (result)
2153
+ goto end;
2154
+
2155
+ if ((battery_system_revision & 0x00f0) == 0x0080 ||
2156
+ (battery_system_revision & 0x00f0) == 0x0090)
2157
+ sbs->sbsm->class = ACPI_SBSM_CLASS;
2158
+ else
2159
+ sbs->sbsm->class = ACPI_SBSEL_CLASS;
2160
+
2161
+ result = acpi_sbsm_get_info(sbs->sbsm);
2162
+ if (result)
2163
+ goto end;
2164
+
2165
+ result = acpi_sbsm_get_state(sbs->sbsm);
2166
+ if (result)
2167
+ goto end;
2168
+
2169
+ if (sbs->sbsm->class == ACPI_SBSM_CLASS) {
2170
+ result = acpi_sbs_generic_add_fs(&(sbs->sbsm->sbsm_entry),
2171
+ acpi_device_dir(sbs->device),
2172
+ ACPI_SBSM_DIR_NAME,
2173
+ &acpi_sbsm_info_fops,
2174
+ &acpi_sbsm_state_fops,
2175
+ NULL, sbs->sbsm);
2176
+ if (result)
2177
+ goto end;
2178
+
2179
+ printk(KERN_INFO PREFIX "SBS: %s [%s]\n", ACPI_SBSM_DEVICE_NAME,
2180
+ ACPI_SBSM_DIR_NAME);
2181
+ } else {
2182
+ result = acpi_sbs_generic_add_fs(&(sbs->sbsm->sbsm_entry),
2183
+ acpi_device_dir(sbs->device),
2184
+ ACPI_SBSEL_DIR_NAME,
2185
+ &acpi_sbsm_info_fops,
2186
+ &acpi_sbsm_state_fops,
2187
+ NULL, sbs->sbsm);
2188
+ if (result)
2189
+ goto end;
2190
+
2191
+ printk(KERN_INFO PREFIX "SBS: %s [%s]\n", ACPI_SBSEL_DEVICE_NAME,
2192
+ ACPI_SBSEL_DIR_NAME);
2193
+ }
2194
+
2195
+ end:
2196
+ return_VALUE(result);
2197
+}
2198
+
2199
+static void acpi_sbsm_remove(struct acpi_sbs *sbs)
2200
+{
2201
+ ACPI_FUNCTION_TRACE("acpi_sbsm_remove");
2202
+
2203
+ acpi_sbs_generic_remove_fs(&sbs->sbsm->sbsm_entry,
2204
+ acpi_device_dir(sbs->device));
2205
+}
2206
+
2207
+/* Smart Battery Charger */
2208
+
2209
+static int acpi_sbc_add(struct acpi_sbs *sbs)
2210
+{
2211
+ int result;
2212
+
2213
+ ACPI_FUNCTION_TRACE("acpi_sbc_add");
2214
+
2215
+ sbs->sbc->sbs = sbs;
2216
+
2217
+ result = acpi_sbc_get_info(sbs->sbc);
2218
+ if (result)
2219
+ goto end;
2220
+
2221
+ result = acpi_sbc_get_state(sbs->sbc);
2222
+ if (result)
2223
+ goto end;
2224
+
2225
+ result = acpi_sbs_generic_add_fs(&sbs->sbc->sbc_entry,
2226
+ acpi_device_dir(sbs->device),
2227
+ ACPI_SBC_DIR_NAME,
2228
+ &acpi_sbc_info_fops,
2229
+ &acpi_sbc_state_fops, NULL, sbs->sbc);
2230
+ if (result)
2231
+ goto end;
2232
+
2233
+ printk(KERN_INFO PREFIX "SBS: %s [%s]\n", ACPI_SBC_DEVICE_NAME,
2234
+ ACPI_SBC_DIR_NAME);
2235
+
2236
+ result = acpi_sbs_generic_add_fs(&sbs->sbc->ladapter_entry,
2237
+ acpi_ladapter_dir,
2238
+ ACPI_LADAPTER_DIR_NAME,
2239
+ NULL,
2240
+ &acpi_ladapter_state_fops,
2241
+ NULL, sbs->sbc);
2242
+ end:
2243
+ return_VALUE(result);
2244
+}
2245
+
2246
+static void acpi_sbc_remove(struct acpi_sbs *sbs)
2247
+{
2248
+ ACPI_FUNCTION_TRACE("acpi_sbc_remove");
2249
+
2250
+ acpi_sbs_generic_remove_fs(&sbs->sbc->sbc_entry,
2251
+ acpi_device_dir(sbs->device));
2252
+
2253
+ acpi_sbs_generic_remove_fs(&sbs->sbc->ladapter_entry,
2254
+ acpi_ladapter_dir);
2255
+}
2256
+
2257
+/* Smart Battery System */
2258
+
2259
+static int acpi_sbs_add(struct acpi_device *device)
2260
+{
2261
+ struct acpi_sbs *sbs = NULL;
2262
+ struct acpi_ec_hc *ec_hc = NULL;
2263
+ int result, remove_result = 0;
2264
+ unsigned long sbs_obj;
2265
+ u8 id;
2266
+
2267
+ ACPI_FUNCTION_TRACE("acpi_sbs_add");
2268
+
2269
+ sbs = kmalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
2270
+ if (!sbs)
2271
+ return_VALUE(-ENOMEM);
2272
+
2273
+ memset(sbs, 0, sizeof(struct acpi_sbs));
2274
+
2275
+ ec_hc = acpi_get_ec_hc(device);
2276
+ if (!ec_hc) {
2277
+ printk(KERN_ALERT PREFIX "SBS: no driver found for EC HC SMBus\n");
2278
+ result = -ENODEV;
2279
+ goto end;
2280
+ }
2281
+
2282
+ sbs->device = device;
2283
+ sbs->smbus = ec_hc->smbus;
2284
+ sema_init(&sbs->sem, 1);
2285
+
2286
+ strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
2287
+ strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
2288
+ acpi_driver_data(device) = sbs;
2289
+
2290
+ result = acpi_sbs_generic_add_fs(&(acpi_device_dir(device)),
2291
+ acpi_sbs_dir,
2292
+ acpi_device_bid(device),
2293
+ NULL, NULL, NULL, sbs);
2294
+ if (result)
2295
+ goto end;
2296
+
2297
+ printk(KERN_INFO PREFIX "SBS: %s [%s]\n",
2298
+ acpi_device_name(device), acpi_device_bid(device));
2299
+
2300
+ /* Add the SBC */
2301
+
2302
+ sbs->sbc = kmalloc(sizeof(struct acpi_sbc), GFP_KERNEL);
2303
+ if (!sbs->sbc) {
2304
+ result = -ENOMEM;
2305
+ goto end;
2306
+ }
2307
+ memset(sbs->sbc, 0, sizeof(struct acpi_sbc));
2308
+
2309
+ result = acpi_sbc_add(sbs);
2310
+ if (result)
2311
+ goto end;
2312
+
2313
+ /* Add the SBSM / SBSEL, if they are present */
2314
+
2315
+ result = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj);
2316
+ if (ACPI_FAILURE(result)) {
2317
+ printk(KERN_ALERT PREFIX "Error obtaining _SBS object\n");
2318
+ result = -EIO;
2319
+ goto end;
2320
+ }
2321
+
2322
+ sbs->sbsm = NULL;
2323
+
2324
+ if (sbs_obj > 0) {
2325
+ sbs->sbsm = kmalloc(sizeof(struct acpi_sbsm), GFP_KERNEL);
2326
+ if (!sbs->sbsm) {
2327
+ result = -ENOMEM;
2328
+ goto end;
2329
+ }
2330
+ memset(sbs->sbsm, 0, sizeof(struct acpi_sbsm));
2331
+
2332
+ result = acpi_sbsm_add(sbs);
2333
+ if(result) {
2334
+ kfree(sbs->sbsm);
2335
+ sbs->sbsm = NULL;
2336
+ }
2337
+ }
2338
+
2339
+ /* Add the batteries */
2340
+
2341
+ sbs->sb = kmalloc(4 * sizeof(struct acpi_sb), GFP_KERNEL);
2342
+ if (!sbs->sb) {
2343
+ result = -ENOMEM;
2344
+ goto end;
2345
+ }
2346
+ memset(sbs->sb, 0, 4 * sizeof(struct acpi_sb));
2347
+
2348
+ if (!sbs->sbsm) {
2349
+ result = acpi_sb_add(sbs, 0);
2350
+ if (result)
2351
+ goto end;
2352
+ } else {
2353
+ for (id = 0; id <= 3; id++) {
2354
+ if (sbs->sbsm->info.batteries_supported & (1 << id)) {
2355
+ result = acpi_sb_add(sbs, id);
2356
+ if (result)
2357
+ goto end;
2358
+ }
2359
+ }
2360
+ }
2361
+
2362
+ sbs->handle = device->handle;
2363
+ printk(KERN_ALERT PREFIX "SBS: HANDLE %p\n", sbs->handle);
2364
+
2365
+ printk(KERN_INFO PREFIX "SBS: name %s, class %s, bid %s\n",
2366
+ acpi_device_name(device),
2367
+ acpi_device_class(device), acpi_device_bid(device));
2368
+
2369
+ end:
2370
+ if (result) {
2371
+ remove_result = acpi_sbs_remove(device, 0);
2372
+ }
2373
+ return_VALUE(result);
2374
+}
2375
+
2376
+int acpi_sbs_remove(struct acpi_device *device, int type)
2377
+{
2378
+ struct acpi_sbs *sbs = (struct acpi_sbs *)acpi_driver_data(device);
2379
+ u8 id;
2380
+
2381
+ ACPI_FUNCTION_TRACE("acpi_sbs_remove");
2382
+
2383
+ if (!device || !sbs)
2384
+ return_VALUE(-EINVAL);
2385
+
2386
+ if (sbs->sb) {
2387
+ for (id = 0; id <= 3; id++) {
2388
+ acpi_sb_remove(sbs, id);
2389
+ }
2390
+ kfree(sbs->sb);
2391
+ }
2392
+
2393
+ if (sbs->sbsm) {
2394
+ acpi_sbsm_remove(sbs);
2395
+ kfree(sbs->sbsm);
2396
+ }
2397
+
2398
+ if (sbs->sbc) {
2399
+ acpi_sbc_remove(sbs);
2400
+ kfree(sbs->sbc);
2401
+ }
2402
+
2403
+ acpi_sbs_generic_remove_fs(&acpi_device_dir(device), acpi_sbs_dir);
2404
+
2405
+ kfree(sbs);
2406
+
2407
+ return_VALUE(0);
2408
+}
2409
+
2410
+static int __init acpi_sbs_init(void)
2411
+{
2412
+ int result = 0;
2413
+
2414
+ ACPI_FUNCTION_TRACE("acpi_sbs_init");
2415
+
2416
+ if (capacity_mode > 2)
2417
+ return_VALUE(-EINVAL);
2418
+
2419
+ acpi_sbs_dir = proc_mkdir(ACPI_SBS_CLASS, acpi_root_dir);
2420
+ if (!acpi_sbs_dir)
2421
+ return_VALUE(-ENODEV);
2422
+ acpi_sbs_dir->owner = THIS_MODULE;
2423
+
2424
+ acpi_lbattery_dir = acpi_get_battery_dir();
2425
+ if (!acpi_lbattery_dir) {
2426
+ printk(KERN_ALERT PREFIX "SBS: cannot get acpi battery directory\n");
2427
+ return_VALUE(-ENODEV);
2428
+ }
2429
+
2430
+ acpi_ladapter_dir = acpi_get_ac_dir();
2431
+ if (!acpi_ladapter_dir) {
2432
+ printk(KERN_ALERT PREFIX "SBS: cannot get acpi ac directory\n");
2433
+ return_VALUE(-ENODEV);
2434
+ }
2435
+
2436
+ result = acpi_bus_register_driver(&acpi_sbs_driver);
2437
+ if (result < 0) {
2438
+ remove_proc_entry(ACPI_SBS_CLASS, acpi_root_dir);
2439
+ return_VALUE(-ENODEV);
2440
+ }
2441
+
2442
+ return_VALUE(0);
2443
+}
2444
+
2445
+static void __exit acpi_sbs_exit(void)
2446
+{
2447
+ ACPI_FUNCTION_TRACE("acpi_sbs_exit");
2448
+
2449
+ acpi_bus_unregister_driver(&acpi_sbs_driver);
2450
+
2451
+ remove_proc_entry(ACPI_SBS_CLASS, acpi_root_dir);
2452
+
2453
+ return_VOID;
2454
+}
2455
+
2456
+module_init(acpi_sbs_init);
2457
+module_exit(acpi_sbs_exit);
2458
diff -uNr linux-2.6.16/drivers/acpi/battery.c linux-2.6.16-iMac/drivers/acpi/battery.c
2459
--- linux-2.6.16/drivers/acpi/battery.c 2006-01-03 04:21:10.000000000 +0100
2460
+++ linux-2.6.16-iMac/drivers/acpi/battery.c 2006-03-20 08:01:46.000000000 +0100
2461
@@ -808,5 +808,12 @@
2462
return_VOID;
2463
}
2464
2465
+struct proc_dir_entry *acpi_get_battery_dir(void)
2466
+{
2467
+ return (acpi_battery_dir);
2468
+}
2469
+
2470
+EXPORT_SYMBOL(acpi_get_battery_dir);
2471
+
2472
module_init(acpi_battery_init);
2473
module_exit(acpi_battery_exit);
2474
diff -uNr linux-2.6.16/drivers/acpi/blacklist.c linux-2.6.16-iMac/drivers/acpi/blacklist.c
2475
--- linux-2.6.16/drivers/acpi/blacklist.c 2006-01-03 04:21:10.000000000 +0100
2476
+++ linux-2.6.16-iMac/drivers/acpi/blacklist.c 2006-03-20 08:01:46.000000000 +0100
2477
@@ -32,6 +32,7 @@
2478
#include <linux/acpi.h>
2479
#include <acpi/acpi_bus.h>
2480
#include <linux/dmi.h>
2481
+#include <linux/efi.h>
2482
2483
enum acpi_blacklist_predicates {
2484
all_versions,
2485
@@ -80,6 +81,9 @@
2486
int year;
2487
char *s = dmi_get_system_info(DMI_BIOS_DATE);
2488
2489
+ if (efi_enabled)
2490
+ return 0;
2491
+
2492
if (!s)
2493
return 0;
2494
if (!*s)
2495
diff -uNr linux-2.6.16/drivers/acpi/ec.c linux-2.6.16-iMac/drivers/acpi/ec.c
2496
--- linux-2.6.16/drivers/acpi/ec.c 2006-03-21 23:01:18.000000000 +0100
2497
+++ linux-2.6.16-iMac/drivers/acpi/ec.c 2006-03-21 23:10:14.000000000 +0100
2498
@@ -991,7 +991,6 @@
2499
int result = 0;
2500
acpi_status status = AE_OK;
2501
union acpi_ec *ec = NULL;
2502
- unsigned long uid;
2503
2504
ACPI_FUNCTION_TRACE("acpi_ec_add");
2505
2506
@@ -1014,10 +1013,9 @@
2507
acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
2508
&ec->common.global_lock);
2509
2510
- /* If our UID matches the UID for the ECDT-enumerated EC,
2511
- we now have the *real* EC info, so kill the makeshift one. */
2512
- acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
2513
- if (ec_ecdt && ec_ecdt->common.uid == uid) {
2514
+ /* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
2515
+ http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
2516
+ if (ec_ecdt) {
2517
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
2518
ACPI_ADR_SPACE_EC,
2519
&acpi_ec_space_handler);
2520
@@ -1062,7 +1060,6 @@
2521
int result = 0;
2522
acpi_status status = AE_OK;
2523
union acpi_ec *ec = NULL;
2524
- unsigned long uid;
2525
2526
ACPI_FUNCTION_TRACE("acpi_ec_add");
2527
2528
@@ -1088,10 +1085,9 @@
2529
acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
2530
&ec->common.global_lock);
2531
2532
- /* If our UID matches the UID for the ECDT-enumerated EC,
2533
- we now have the *real* EC info, so kill the makeshift one. */
2534
- acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
2535
- if (ec_ecdt && ec_ecdt->common.uid == uid) {
2536
+ /* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
2537
+ http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
2538
+ if (ec_ecdt) {
2539
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
2540
ACPI_ADR_SPACE_EC,
2541
&acpi_ec_space_handler);
2542
diff -uNr linux-2.6.16/drivers/acpi/ec.h linux-2.6.16-iMac/drivers/acpi/ec.h
2543
--- linux-2.6.16/drivers/acpi/ec.h 1970-01-01 01:00:00.000000000 +0100
2544
+++ linux-2.6.16-iMac/drivers/acpi/ec.h 2006-03-20 08:01:46.000000000 +0100
2545
@@ -0,0 +1,70 @@
2546
+/*
2547
+ * ec.h - ACPI Embedded Controller Driver ($Revision: 1.2 $)
2548
+ *
2549
+ * Copyright (C) 2004 Luming Yu <[email protected]>
2550
+ * Copyright (C) 2001, 2002 Andy Grover <[email protected]>
2551
+ * Copyright (C) 2001, 2002 Paul Diefenbaugh <[email protected]>
2552
+ *
2553
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2554
+ *
2555
+ * This program is free software; you can redistribute it and/or modify
2556
+ * it under the terms of the GNU General Public License as published by
2557
+ * the Free Software Foundation; either version 2 of the License, or (at
2558
+ * your option) any later version.
2559
+ *
2560
+ * This program is distributed in the hope that it will be useful, but
2561
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
2562
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2563
+ * General Public License for more details.
2564
+ *
2565
+ * You should have received a copy of the GNU General Public License along
2566
+ * with this program; if not, write to the Free Software Foundation, Inc.,
2567
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
2568
+ *
2569
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2570
+ */
2571
+
2572
+union acpi_ec {
2573
+ struct {
2574
+ u32 mode;
2575
+ acpi_handle handle;
2576
+ unsigned long uid;
2577
+ unsigned long gpe_bit;
2578
+ struct acpi_generic_address status_addr;
2579
+ struct acpi_generic_address command_addr;
2580
+ struct acpi_generic_address data_addr;
2581
+ unsigned long global_lock;
2582
+ } common;
2583
+
2584
+ struct {
2585
+ u32 mode;
2586
+ acpi_handle handle;
2587
+ unsigned long uid;
2588
+ unsigned long gpe_bit;
2589
+ struct acpi_generic_address status_addr;
2590
+ struct acpi_generic_address command_addr;
2591
+ struct acpi_generic_address data_addr;
2592
+ unsigned long global_lock;
2593
+ unsigned int expect_event;
2594
+ atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
2595
+ atomic_t pending_gpe;
2596
+ struct semaphore sem;
2597
+ wait_queue_head_t wait;
2598
+ } burst;
2599
+
2600
+ struct {
2601
+ u32 mode;
2602
+ acpi_handle handle;
2603
+ unsigned long uid;
2604
+ unsigned long gpe_bit;
2605
+ struct acpi_generic_address status_addr;
2606
+ struct acpi_generic_address command_addr;
2607
+ struct acpi_generic_address data_addr;
2608
+ unsigned long global_lock;
2609
+ struct semaphore sem;
2610
+ spinlock_t lock;
2611
+ } polling;
2612
+};
2613
+
2614
+extern int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data);
2615
+extern int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data);
2616
diff -uNr linux-2.6.16/drivers/acpi/i2c_acpi_ec.c linux-2.6.16-iMac/drivers/acpi/i2c_acpi_ec.c
2617
--- linux-2.6.16/drivers/acpi/i2c_acpi_ec.c 1970-01-01 01:00:00.000000000 +0100
2618
+++ linux-2.6.16-iMac/drivers/acpi/i2c_acpi_ec.c 2006-03-21 16:51:20.000000000 +0100
2619
@@ -0,0 +1,423 @@
2620
+/*
2621
+ * SMBus driver for ACPI Embedded Controller ($Revision: 1.2 $)
2622
+ *
2623
+ * Copyright (c) 2002, 2005 Ducrot Bruno
2624
+ * Copyright (c) 2005 Rich Townsend (tiny hacks & tweaks)
2625
+ *
2626
+ * This program is free software; you can redistribute it and/or modify
2627
+ * it under the terms of the GNU General Public License as published by
2628
+ * the Free Software Foundation version 2.
2629
+ */
2630
+
2631
+#include <linux/version.h>
2632
+#include <linux/module.h>
2633
+#include <linux/slab.h>
2634
+#include <linux/kernel.h>
2635
+#include <linux/stddef.h>
2636
+#include <linux/sched.h>
2637
+#include <linux/init.h>
2638
+#include <linux/i2c.h>
2639
+#include <linux/delay.h>
2640
+#include <linux/acpi.h>
2641
+
2642
+#include "i2c_acpi_ec.h"
2643
+
2644
+//#define xudelay(t)
2645
+#define xudelay(t) udelay(t)
2646
+
2647
+//#define xmsleep(t)
2648
+#define xmsleep(t) msleep(t)
2649
+
2650
+#define ACPI_EC_HC_COMPONENT 0x00080000
2651
+#define ACPI_EC_HC_CLASS "ec_hc_smbus"
2652
+#define ACPI_EC_HC_HID "ACPI0001"
2653
+#define ACPI_EC_HC_DRIVER_NAME "ACPI EC HC smbus driver"
2654
+#define ACPI_EC_HC_DEVICE_NAME "EC HC smbus"
2655
+
2656
+#define _COMPONENT ACPI_EC_HC_COMPONENT
2657
+
2658
+ACPI_MODULE_NAME("acpi_smbus")
2659
+
2660
+static int acpi_ec_hc_add(struct acpi_device *device);
2661
+static int acpi_ec_hc_remove(struct acpi_device *device, int type);
2662
+
2663
+static struct acpi_driver acpi_ec_hc_driver = {
2664
+ .name = ACPI_EC_HC_DRIVER_NAME,
2665
+ .class = ACPI_EC_HC_CLASS,
2666
+ .ids = ACPI_EC_HC_HID,
2667
+ .ops = {
2668
+ .add = acpi_ec_hc_add,
2669
+ .remove = acpi_ec_hc_remove,
2670
+ },
2671
+};
2672
+
2673
+/* Various bit mask for EC_SC (R) */
2674
+#define OBF 0x01
2675
+#define IBF 0x02
2676
+#define CMD 0x08
2677
+#define BURST 0x10
2678
+#define SCI_EVT 0x20
2679
+#define SMI_EVT 0x40
2680
+
2681
+/* Commands for EC_SC (W) */
2682
+#define RD_EC 0x80
2683
+#define WR_EC 0x81
2684
+#define BE_EC 0x82
2685
+#define BD_EC 0x83
2686
+#define QR_EC 0x84
2687
+
2688
+/*
2689
+ * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
2690
+ */
2691
+
2692
+#define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */
2693
+#define ACPI_EC_SMB_STS 0x01 /* status */
2694
+#define ACPI_EC_SMB_ADDR 0x02 /* address */
2695
+#define ACPI_EC_SMB_CMD 0x03 /* command */
2696
+#define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */
2697
+#define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */
2698
+#define ACPI_EC_SMB_ALRM_A 0x25 /* alarm address */
2699
+#define ACPI_EC_SMB_ALRM_D 0x26 /* 2 bytes alarm data */
2700
+
2701
+#define ACPI_EC_SMB_STS_DONE 0x80
2702
+#define ACPI_EC_SMB_STS_ALRM 0x40
2703
+#define ACPI_EC_SMB_STS_RES 0x20
2704
+#define ACPI_EC_SMB_STS_STATUS 0x1f
2705
+
2706
+#define ACPI_EC_SMB_STATUS_OK 0x00
2707
+#define ACPI_EC_SMB_STATUS_FAIL 0x07
2708
+#define ACPI_EC_SMB_STATUS_DNAK 0x10
2709
+#define ACPI_EC_SMB_STATUS_DERR 0x11
2710
+#define ACPI_EC_SMB_STATUS_CMD_DENY 0x12
2711
+#define ACPI_EC_SMB_STATUS_UNKNOWN 0x13
2712
+#define ACPI_EC_SMB_STATUS_ACC_DENY 0x17
2713
+#define ACPI_EC_SMB_STATUS_TIMEOUT 0x18
2714
+#define ACPI_EC_SMB_STATUS_NOTSUP 0x19
2715
+#define ACPI_EC_SMB_STATUS_BUSY 0x1A
2716
+#define ACPI_EC_SMB_STATUS_PEC 0x1F
2717
+
2718
+#define ACPI_EC_SMB_PRTCL_WRITE 0x00
2719
+#define ACPI_EC_SMB_PRTCL_READ 0x01
2720
+#define ACPI_EC_SMB_PRTCL_QUICK 0x02
2721
+#define ACPI_EC_SMB_PRTCL_BYTE 0x04
2722
+#define ACPI_EC_SMB_PRTCL_BYTE_DATA 0x06
2723
+#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08
2724
+#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a
2725
+#define ACPI_EC_SMB_PRTCL_PROC_CALL 0x0c
2726
+#define ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL 0x0d
2727
+#define ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
2728
+#define ACPI_EC_SMB_PRTCL_PEC 0x80
2729
+
2730
+/* Length of pre/post transaction sleep (msec) */
2731
+#define ACPI_EC_SMB_TRANSACTION_SLEEP 1
2732
+
2733
+static int
2734
+acpi_ec_smb_read(struct acpi_ec_smbus *smbus, u8 address, u8 * data)
2735
+{
2736
+ //u32 val;
2737
+ int err;
2738
+
2739
+ ACPI_FUNCTION_TRACE("acpi_ec_smb_read");
2740
+
2741
+ //err = acpi_ec_read(smbus->ec, smbus->base + address, &val);
2742
+ /*
2743
+ err = ec_read(smbus->base + address, &val);
2744
+ if (!err)
2745
+ *data = val;
2746
+ */
2747
+ err = ec_read(smbus->base + address, data);
2748
+
2749
+ xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
2750
+
2751
+ return err;
2752
+}
2753
+
2754
+static int
2755
+acpi_ec_smb_write(struct acpi_ec_smbus *smbus, u8 address, u8 data)
2756
+{
2757
+ int err;
2758
+
2759
+ ACPI_FUNCTION_TRACE("acpi_ec_smb_write");
2760
+
2761
+ //err = acpi_ec_write(smbus->ec, smbus->base + address, data);
2762
+ err = ec_write(smbus->base + address, data);
2763
+
2764
+ xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP);
2765
+
2766
+ return err;
2767
+}
2768
+
2769
+static s32
2770
+acpi_ec_smb_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
2771
+ char read_write, u8 command, int size,
2772
+ union i2c_smbus_data *data)
2773
+{
2774
+ struct acpi_ec_smbus *smbus = adap->algo_data;
2775
+ unsigned char protocol, len = 0, pec, temp[2] = { 0, 0 };
2776
+ int i;
2777
+
2778
+ ACPI_FUNCTION_TRACE("acpi_ec_smb_access");
2779
+
2780
+ if (read_write == I2C_SMBUS_READ) {
2781
+ protocol = ACPI_EC_SMB_PRTCL_READ;
2782
+ } else {
2783
+ protocol = ACPI_EC_SMB_PRTCL_WRITE;
2784
+ }
2785
+ pec = (flags & I2C_CLIENT_PEC) ? ACPI_EC_SMB_PRTCL_PEC : 0;
2786
+
2787
+ switch (size) {
2788
+
2789
+ case I2C_SMBUS_QUICK:
2790
+ protocol |= ACPI_EC_SMB_PRTCL_QUICK;
2791
+ read_write = I2C_SMBUS_WRITE;
2792
+ break;
2793
+
2794
+ case I2C_SMBUS_BYTE:
2795
+ if (read_write == I2C_SMBUS_WRITE)
2796
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
2797
+ protocol |= ACPI_EC_SMB_PRTCL_BYTE;
2798
+ break;
2799
+
2800
+ case I2C_SMBUS_BYTE_DATA:
2801
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
2802
+ if (read_write == I2C_SMBUS_WRITE)
2803
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte);
2804
+ protocol |= ACPI_EC_SMB_PRTCL_BYTE_DATA;
2805
+ break;
2806
+
2807
+ case I2C_SMBUS_WORD_DATA:
2808
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
2809
+ if (read_write == I2C_SMBUS_WRITE) {
2810
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
2811
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1,
2812
+ data->word >> 8);
2813
+ }
2814
+ protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA | pec;
2815
+ break;
2816
+
2817
+ case I2C_SMBUS_BLOCK_DATA:
2818
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
2819
+ if (read_write == I2C_SMBUS_WRITE) {
2820
+ len = min_t(u8, data->block[0], 32);
2821
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
2822
+ for (i = 0; i < len; i++)
2823
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
2824
+ data->block[i + 1]);
2825
+ }
2826
+ protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA | pec;
2827
+ break;
2828
+
2829
+ case I2C_SMBUS_I2C_BLOCK_DATA:
2830
+ len = min_t(u8, data->block[0], 32);
2831
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
2832
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
2833
+ if (read_write == I2C_SMBUS_WRITE)
2834
+ for (i = 0; i < len; i++)
2835
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
2836
+ data->block[i + 1]);
2837
+ protocol |= ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA;
2838
+ break;
2839
+
2840
+ case I2C_SMBUS_PROC_CALL:
2841
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
2842
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word);
2843
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, data->word >> 8);
2844
+ protocol = ACPI_EC_SMB_PRTCL_PROC_CALL | pec;
2845
+ read_write = I2C_SMBUS_READ;
2846
+ break;
2847
+
2848
+ case I2C_SMBUS_BLOCK_PROC_CALL:
2849
+ protocol |= pec;
2850
+ len = min_t(u8, data->block[0], 31);
2851
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command);
2852
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len);
2853
+ for (i = 0; i < len; i++)
2854
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i,
2855
+ data->block[i + 1]);
2856
+ protocol = ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL | pec;
2857
+ read_write = I2C_SMBUS_READ;
2858
+ break;
2859
+
2860
+ default:
2861
+ printk(KERN_WARNING PREFIX "EC SMBus adapter: "
2862
+ "Unsupported transaction %d\n", size);
2863
+ return -1;
2864
+ }
2865
+
2866
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_ADDR, addr << 1);
2867
+ acpi_ec_smb_write(smbus, ACPI_EC_SMB_PRTCL, protocol);
2868
+
2869
+ acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
2870
+
2871
+ if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
2872
+ xudelay(500);
2873
+ acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
2874
+ }
2875
+ if (~temp[0] & ACPI_EC_SMB_STS_DONE) {
2876
+ xmsleep(10);
2877
+ acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0);
2878
+ }
2879
+ if ((~temp[0] & ACPI_EC_SMB_STS_DONE)
2880
+ || (temp[0] & ACPI_EC_SMB_STS_STATUS))
2881
+ return -1;
2882
+
2883
+ if (read_write == I2C_SMBUS_WRITE)
2884
+ return 0;
2885
+
2886
+ switch (size) {
2887
+
2888
+ case I2C_SMBUS_BYTE:
2889
+ case I2C_SMBUS_BYTE_DATA:
2890
+ acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, &data->byte);
2891
+ break;
2892
+
2893
+ case I2C_SMBUS_WORD_DATA:
2894
+ case I2C_SMBUS_PROC_CALL:
2895
+ acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, temp + 0);
2896
+ acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + 1, temp + 1);
2897
+ data->word = (temp[1] << 8) | temp[0];
2898
+ break;
2899
+
2900
+ case I2C_SMBUS_BLOCK_DATA:
2901
+ case I2C_SMBUS_BLOCK_PROC_CALL:
2902
+ len = 0;
2903
+ acpi_ec_smb_read(smbus, ACPI_EC_SMB_BCNT, &len);
2904
+ len = min_t(u8, len, 32);
2905
+ case I2C_SMBUS_I2C_BLOCK_DATA:
2906
+ for (i = 0; i < len; i++)
2907
+ acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + i,
2908
+ data->block + i + 1);
2909
+ data->block[0] = len;
2910
+ break;
2911
+ }
2912
+
2913
+ return 0;
2914
+}
2915
+
2916
+static u32 acpi_ec_smb_func(struct i2c_adapter *adapter)
2917
+{
2918
+ ACPI_FUNCTION_TRACE("acpi_ec_smb_func");
2919
+
2920
+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
2921
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
2922
+ I2C_FUNC_SMBUS_BLOCK_DATA |
2923
+ I2C_FUNC_SMBUS_PROC_CALL |
2924
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
2925
+ I2C_FUNC_SMBUS_I2C_BLOCK |
2926
+ I2C_FUNC_SMBUS_HWPEC_CALC;
2927
+}
2928
+
2929
+static struct i2c_algorithm acpi_ec_smbus_algorithm = {
2930
+ .smbus_xfer = acpi_ec_smb_access,
2931
+ .functionality = acpi_ec_smb_func,
2932
+};
2933
+
2934
+static int acpi_ec_hc_add(struct acpi_device *device)
2935
+{
2936
+ int status;
2937
+ unsigned long val;
2938
+ struct acpi_ec_hc *ec_hc;
2939
+ struct acpi_ec_smbus *smbus;
2940
+
2941
+ ACPI_FUNCTION_TRACE("acpi_ec_hc_add");
2942
+
2943
+ if (!device)
2944
+ return_VALUE(-EINVAL);
2945
+
2946
+ ec_hc = kmalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL);
2947
+ if (!ec_hc)
2948
+ return_VALUE(-ENOMEM);
2949
+ memset(ec_hc, 0, sizeof(struct acpi_ec_hc));
2950
+
2951
+ smbus = kmalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL);
2952
+ if (!smbus) {
2953
+ kfree(ec_hc);
2954
+ return_VALUE(-ENOMEM);
2955
+ }
2956
+ memset(smbus, 0, sizeof(struct acpi_ec_smbus));
2957
+
2958
+ ec_hc->handle = device->handle;
2959
+ strcpy(acpi_device_name(device), ACPI_EC_HC_DEVICE_NAME);
2960
+ strcpy(acpi_device_class(device), ACPI_EC_HC_CLASS);
2961
+ acpi_driver_data(device) = ec_hc;
2962
+
2963
+ status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val);
2964
+ if (ACPI_FAILURE(status)) {
2965
+ printk(KERN_WARNING PREFIX "Error obtaining _EC\n");
2966
+ kfree(ec_hc->smbus);
2967
+ kfree(smbus);
2968
+ return_VALUE(-EIO);
2969
+ }
2970
+
2971
+ smbus->ec = acpi_driver_data(device->parent);
2972
+ smbus->base = (val & 0xff00ull) >> 8;
2973
+ smbus->alert = val & 0xffull;
2974
+
2975
+ printk(KERN_DEBUG "base: 0x%.x alert: 0x%.2x\n", smbus->base, smbus->alert);
2976
+
2977
+ smbus->adapter.owner = THIS_MODULE;
2978
+ smbus->adapter.algo = &acpi_ec_smbus_algorithm;
2979
+ smbus->adapter.algo_data = smbus;
2980
+
2981
+ if (i2c_add_adapter(&smbus->adapter)) {
2982
+ printk(KERN_WARNING PREFIX "EC SMBus adapter: "
2983
+ "Failed to register adapter\n");
2984
+ kfree(smbus);
2985
+ kfree(ec_hc);
2986
+ return_VALUE(-EIO);
2987
+ }
2988
+
2989
+ ec_hc->smbus = smbus;
2990
+
2991
+ printk(KERN_INFO PREFIX "EC SMBus adapter: name %s, class %s, bid %s\n",
2992
+ acpi_device_name(device),
2993
+ acpi_device_class(device), acpi_device_bid(device)
2994
+ );
2995
+
2996
+ return_VALUE(AE_OK);
2997
+}
2998
+
2999
+static int acpi_ec_hc_remove(struct acpi_device *device, int type)
3000
+{
3001
+ struct acpi_ec_hc *ec_hc;
3002
+
3003
+ ACPI_FUNCTION_TRACE("acpi_ec_hc_remove");
3004
+
3005
+ if (!device)
3006
+ return_VALUE(-EINVAL);
3007
+
3008
+ ec_hc = acpi_driver_data(device);
3009
+
3010
+ i2c_del_adapter(&ec_hc->smbus->adapter);
3011
+ kfree(ec_hc->smbus);
3012
+ kfree(ec_hc);
3013
+
3014
+ return_VALUE(AE_OK);
3015
+}
3016
+
3017
+static int __init acpi_ec_hc_init(void)
3018
+{
3019
+ ACPI_FUNCTION_TRACE("acpi_ec_hc_init");
3020
+ return acpi_bus_register_driver(&acpi_ec_hc_driver);
3021
+}
3022
+
3023
+static void __exit acpi_ec_hc_exit(void)
3024
+{
3025
+ ACPI_FUNCTION_TRACE("acpi_ec_hc_exit");
3026
+ acpi_bus_unregister_driver(&acpi_ec_hc_driver);
3027
+}
3028
+
3029
+struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device)
3030
+{
3031
+ ACPI_FUNCTION_TRACE("acpi_get_ec_hc");
3032
+ return ((struct acpi_ec_hc *)acpi_driver_data(device->parent));
3033
+}
3034
+
3035
+EXPORT_SYMBOL(acpi_get_ec_hc);
3036
+
3037
+module_init(acpi_ec_hc_init);
3038
+module_exit(acpi_ec_hc_exit);
3039
+
3040
+MODULE_LICENSE("GPL");
3041
+MODULE_AUTHOR("Ducrot Bruno");
3042
+MODULE_DESCRIPTION("ACPI EC SMBus driver");
3043
diff -uNr linux-2.6.16/drivers/acpi/i2c_acpi_ec.h linux-2.6.16-iMac/drivers/acpi/i2c_acpi_ec.h
3044
--- linux-2.6.16/drivers/acpi/i2c_acpi_ec.h 1970-01-01 01:00:00.000000000 +0100
3045
+++ linux-2.6.16-iMac/drivers/acpi/i2c_acpi_ec.h 2006-03-20 08:01:46.000000000 +0100
3046
@@ -0,0 +1,25 @@
3047
+/*
3048
+ * SMBus driver for ACPI Embedded Controller ($Revision: 1.2 $)
3049
+ *
3050
+ * Copyright (c) 2002, 2005 Ducrot Bruno
3051
+ *
3052
+ * This program is free software; you can redistribute it and/or modify
3053
+ * it under the terms of the GNU General Public License as published by
3054
+ * the Free Software Foundation version 2.
3055
+ */
3056
+
3057
+#include "ec.h"
3058
+
3059
+struct acpi_ec_smbus {
3060
+ struct i2c_adapter adapter;
3061
+ union acpi_ec *ec;
3062
+ int base;
3063
+ int alert;
3064
+};
3065
+
3066
+struct acpi_ec_hc {
3067
+ acpi_handle handle;
3068
+ struct acpi_ec_smbus *smbus;
3069
+};
3070
+
3071
+struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device);
3072
diff -uNr linux-2.6.16/drivers/acpi/osl.c linux-2.6.16-iMac/drivers/acpi/osl.c
3073
--- linux-2.6.16/drivers/acpi/osl.c 2006-03-21 23:01:18.000000000 +0100
3074
+++ linux-2.6.16-iMac/drivers/acpi/osl.c 2006-03-20 08:01:46.000000000 +0100
3075
@@ -208,6 +208,10 @@
3076
3077
void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
3078
{
3079
+ /* Don't unmap memory which was not mapped by acpi_os_map_memory */
3080
+ if (efi_enabled &&
3081
+ (efi_mem_attributes(virt_to_phys(virt)) & EFI_MEMORY_WB))
3082
+ return;
3083
iounmap(virt);
3084
}
3085
EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
3086
diff -uNr linux-2.6.16/drivers/firmware/efivars.c linux-2.6.16-iMac/drivers/firmware/efivars.c
3087
--- linux-2.6.16/drivers/firmware/efivars.c 2006-03-21 23:01:18.000000000 +0100
3088
+++ linux-2.6.16-iMac/drivers/firmware/efivars.c 2006-03-20 10:37:27.000000000 +0100
3089
@@ -110,7 +110,7 @@
3090
struct efi_variable {
3091
efi_char16_t VariableName[1024/sizeof(efi_char16_t)];
3092
efi_guid_t VendorGuid;
3093
- unsigned long DataSize;
3094
+ u64 DataSize;
3095
__u8 Data[1024];
3096
efi_status_t Status;
3097
__u32 Attributes;
3098
diff -uNr linux-2.6.16/drivers/macintosh/Kconfig linux-2.6.16-iMac/drivers/macintosh/Kconfig
3099
--- linux-2.6.16/drivers/macintosh/Kconfig 2006-03-21 23:01:18.000000000 +0100
3100
+++ linux-2.6.16-iMac/drivers/macintosh/Kconfig 2006-03-26 07:07:21.000000000 +0200
3101
@@ -1,6 +1,6 @@
3102
3103
menu "Macintosh device drivers"
3104
- depends on PPC || MAC
3105
+ depends on PPC || MAC || X86
3106
3107
config ADB
3108
bool "Apple Desktop Bus (ADB) support"
3109
@@ -135,7 +135,7 @@
3110
3111
config MAC_EMUMOUSEBTN
3112
bool "Support for mouse button 2+3 emulation"
3113
- depends on INPUT_ADBHID
3114
+# depends on INPUT_ADBHID
3115
help
3116
This provides generic support for emulating the 2nd and 3rd mouse
3117
button with keypresses. If you say Y here, the emulation is still
3118
diff -uNr linux-2.6.16/drivers/pci/msi.c linux-2.6.16-iMac/drivers/pci/msi.c
3119
--- linux-2.6.16/drivers/pci/msi.c 2006-03-21 23:01:19.000000000 +0100
3120
+++ linux-2.6.16-iMac/drivers/pci/msi.c 2006-03-20 08:01:46.000000000 +0100
3121
@@ -15,6 +15,7 @@
3122
#include <linux/smp_lock.h>
3123
#include <linux/pci.h>
3124
#include <linux/proc_fs.h>
3125
+#include <linux/dmi.h>
3126
3127
#include <asm/errno.h>
3128
#include <asm/io.h>
3129
@@ -40,6 +41,27 @@
3130
u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
3131
#endif
3132
3133
+#ifdef CONFIG_X86
3134
+
3135
+static int __init apple_msi_disable(struct dmi_system_id *d)
3136
+{
3137
+ if (!pci_msi_quirk) {
3138
+ printk(KERN_INFO "Apple machine detected. MSI disabled\n");
3139
+ pci_msi_quirk = 1;
3140
+ }
3141
+ return 0;
3142
+}
3143
+
3144
+static struct dmi_system_id __initdata msi_dmi_table[] = {
3145
+ {
3146
+ apple_msi_disable, "Apple",
3147
+ { DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), },
3148
+ },
3149
+ { }
3150
+};
3151
+
3152
+#endif
3153
+
3154
static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags)
3155
{
3156
memset(p, 0, NR_IRQS * sizeof(struct msi_desc));
3157
@@ -362,6 +384,10 @@
3158
if (!status)
3159
return status;
3160
3161
+#ifdef CONFIG_X86
3162
+ dmi_check_system(msi_dmi_table);
3163
+#endif
3164
+
3165
if (pci_msi_quirk) {
3166
pci_msi_enable = 0;
3167
printk(KERN_WARNING "PCI: MSI quirk detected. MSI disabled.\n");
3168
diff -uNr linux-2.6.16/drivers/scsi/ata_piix.c linux-2.6.16-iMac/drivers/scsi/ata_piix.c
3169
--- linux-2.6.16/drivers/scsi/ata_piix.c 2006-03-21 23:01:19.000000000 +0100
3170
+++ linux-2.6.16-iMac/drivers/scsi/ata_piix.c 2006-03-20 08:01:46.000000000 +0100
3171
@@ -95,6 +95,8 @@
3172
#define DRV_NAME "ata_piix"
3173
#define DRV_VERSION "1.05"
3174
3175
+#define ATA_ENABLE_PATA 1
3176
+
3177
enum {
3178
PIIX_IOCFG = 0x54, /* IDE I/O configuration register */
3179
ICH5_PMR = 0x90, /* port mapping register */
3180
@@ -141,6 +143,7 @@
3181
{ 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata },
3182
{ 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
3183
{ 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
3184
+ { 0x8086, 0x27df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
3185
#endif
3186
3187
/* NOTE: The following PCI ids must be kept in sync with the
3188
diff -uNr linux-2.6.16/drivers/usb/input/hid-core.c linux-2.6.16-iMac/drivers/usb/input/hid-core.c
3189
--- linux-2.6.16/drivers/usb/input/hid-core.c 2006-03-21 23:01:19.000000000 +0100
3190
+++ linux-2.6.16-iMac/drivers/usb/input/hid-core.c 2006-03-20 12:44:24.000000000 +0100
3191
@@ -1602,6 +1602,8 @@
3192
{ USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
3193
{ USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN },
3194
{ USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
3195
+ { USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN },
3196
+ { USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN },
3197
{ USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
3198
{ USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
3199
3200
diff -uNr linux-2.6.16/drivers/usb/storage/usb.c linux-2.6.16-iMac/drivers/usb/storage/usb.c
3201
--- linux-2.6.16/drivers/usb/storage/usb.c 2006-03-21 23:01:19.000000000 +0100
3202
+++ linux-2.6.16-iMac/drivers/usb/storage/usb.c 2006-03-20 08:01:46.000000000 +0100
3203
@@ -103,7 +103,7 @@
3204
MODULE_DESCRIPTION("USB Mass Storage driver for Linux");
3205
MODULE_LICENSE("GPL");
3206
3207
-static unsigned int delay_use = 5;
3208
+static unsigned int delay_use = 0;
3209
module_param(delay_use, uint, S_IRUGO | S_IWUSR);
3210
MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
3211
3212
diff -uNr linux-2.6.16/drivers/video/Kconfig linux-2.6.16-iMac/drivers/video/Kconfig
3213
--- linux-2.6.16/drivers/video/Kconfig 2006-03-21 23:01:19.000000000 +0100
3214
+++ linux-2.6.16-iMac/drivers/video/Kconfig 2006-03-20 08:01:46.000000000 +0100
3215
@@ -465,6 +465,15 @@
3216
You will get a boot time penguin logo at no additional cost. Please
3217
read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
3218
3219
+config FB_IMAC
3220
+ bool "Intel Based Macs FB"
3221
+ depends on (FB = y) && X86
3222
+ select FB_CFB_FILLRECT
3223
+ select FB_CFB_COPYAREA
3224
+ select FB_CFB_IMAGEBLIT
3225
+ help
3226
+ This is the frame buffer device driver for the Inel Based Mac's
3227
+
3228
config VIDEO_SELECT
3229
bool
3230
depends on FB_VESA
3231
diff -uNr linux-2.6.16/drivers/video/Makefile linux-2.6.16-iMac/drivers/video/Makefile
3232
--- linux-2.6.16/drivers/video/Makefile 2006-01-03 04:21:10.000000000 +0100
3233
+++ linux-2.6.16-iMac/drivers/video/Makefile 2006-03-20 08:01:46.000000000 +0100
3234
@@ -97,6 +97,7 @@
3235
3236
# Platform or fallback drivers go here
3237
obj-$(CONFIG_FB_VESA) += vesafb.o
3238
+obj-$(CONFIG_FB_IMAC) += imacfb.o
3239
obj-$(CONFIG_FB_VGA16) += vga16fb.o vgastate.o
3240
obj-$(CONFIG_FB_OF) += offb.o
3241
3242
diff -uNr linux-2.6.16/drivers/video/imacfb.c linux-2.6.16-iMac/drivers/video/imacfb.c
3243
--- linux-2.6.16/drivers/video/imacfb.c 1970-01-01 01:00:00.000000000 +0100
3244
+++ linux-2.6.16-iMac/drivers/video/imacfb.c 2006-03-20 08:01:46.000000000 +0100
3245
@@ -0,0 +1,425 @@
3246
+/*
3247
+ * framebuffer driver for Intel Based Mac's
3248
+ *
3249
+ * (c) 2006 Edgar Hucek <[email protected]>
3250
+ * Original imac driver written by Gerd Knorr <[email protected]>
3251
+ *
3252
+ */
3253
+
3254
+#include <linux/module.h>
3255
+#include <linux/kernel.h>
3256
+#include <linux/errno.h>
3257
+#include <linux/string.h>
3258
+#include <linux/mm.h>
3259
+#include <linux/tty.h>
3260
+#include <linux/slab.h>
3261
+#include <linux/delay.h>
3262
+#include <linux/fb.h>
3263
+#include <linux/ioport.h>
3264
+#include <linux/init.h>
3265
+#include <linux/platform_device.h>
3266
+
3267
+#include <video/vga.h>
3268
+#include <asm/io.h>
3269
+#include <asm/mtrr.h>
3270
+
3271
+#define dac_reg (0x3c8)
3272
+#define dac_val (0x3c9)
3273
+
3274
+typedef enum _MAC_TAPE {
3275
+ M_I17,
3276
+ M_I20,
3277
+ M_MINI,
3278
+ M_NEW
3279
+} MAC_TAPE;
3280
+
3281
+/* --------------------------------------------------------------------- */
3282
+
3283
+static struct fb_var_screeninfo imacfb_defined __initdata = {
3284
+ .activate = FB_ACTIVATE_NOW,
3285
+ .height = -1,
3286
+ .width = -1,
3287
+ .right_margin = 32,
3288
+ .upper_margin = 16,
3289
+ .lower_margin = 4,
3290
+ .vsync_len = 4,
3291
+ .vmode = FB_VMODE_NONINTERLACED,
3292
+};
3293
+
3294
+static struct fb_fix_screeninfo imacfb_fix __initdata = {
3295
+ .id = "IMAC VGA",
3296
+ .type = FB_TYPE_PACKED_PIXELS,
3297
+ .accel = FB_ACCEL_NONE,
3298
+};
3299
+
3300
+static int inverse = 0;
3301
+static int mtrr = 0; /* disable mtrr */
3302
+static int vram_remap __initdata = 0; /* Set amount of memory to be used */
3303
+static int vram_total __initdata = 0; /* Set total amount of memory */
3304
+static int depth;
3305
+static int model = M_NEW;
3306
+static int manual_height = 0;
3307
+static int manual_width = 0;
3308
+
3309
+/* --------------------------------------------------------------------- */
3310
+
3311
+static int imacfb_setcolreg(unsigned regno, unsigned red, unsigned green,
3312
+ unsigned blue, unsigned transp,
3313
+ struct fb_info *info)
3314
+{
3315
+ /*
3316
+ * Set a single color register. The values supplied are
3317
+ * already rounded down to the hardware's capabilities
3318
+ * (according to the entries in the `var' structure). Return
3319
+ * != 0 for invalid regno.
3320
+ */
3321
+
3322
+ if (regno >= info->cmap.len)
3323
+ return 1;
3324
+
3325
+ if (regno < 16 && info->var.bits_per_pixel != 8) {
3326
+ switch (info->var.bits_per_pixel) {
3327
+ case 16:
3328
+ if (info->var.red.offset == 10) {
3329
+ /* 1:5:5:5 */
3330
+ ((u32*) (info->pseudo_palette))[regno] =
3331
+ ((red & 0xf800) >> 1) |
3332
+ ((green & 0xf800) >> 6) |
3333
+ ((blue & 0xf800) >> 11);
3334
+ } else {
3335
+ /* 0:5:6:5 */
3336
+ ((u32*) (info->pseudo_palette))[regno] =
3337
+ ((red & 0xf800) ) |
3338
+ ((green & 0xfc00) >> 5) |
3339
+ ((blue & 0xf800) >> 11);
3340
+ }
3341
+ break;
3342
+ case 24:
3343
+ case 32:
3344
+ red >>= 8;
3345
+ green >>= 8;
3346
+ blue >>= 8;
3347
+ ((u32 *)(info->pseudo_palette))[regno] =
3348
+ (red << info->var.red.offset) |
3349
+ (green << info->var.green.offset) |
3350
+ (blue << info->var.blue.offset);
3351
+ break;
3352
+ }
3353
+ }
3354
+
3355
+ return 0;
3356
+}
3357
+
3358
+static struct fb_ops imacfb_ops = {
3359
+ .owner = THIS_MODULE,
3360
+ .fb_setcolreg = imacfb_setcolreg,
3361
+ .fb_fillrect = cfb_fillrect,
3362
+ .fb_copyarea = cfb_copyarea,
3363
+ .fb_imageblit = cfb_imageblit,
3364
+};
3365
+
3366
+static int __init imacfb_setup(char *options)
3367
+{
3368
+ char *this_opt;
3369
+
3370
+ if (!options || !*options)
3371
+ return 0;
3372
+
3373
+ while ((this_opt = strsep(&options, ",")) != NULL) {
3374
+ if (!*this_opt) continue;
3375
+
3376
+ if (! strcmp(this_opt, "inverse"))
3377
+ inverse=1;
3378
+ else if (! strncmp(this_opt, "mtrr:", 5))
3379
+ mtrr = simple_strtoul(this_opt+5, NULL, 0);
3380
+ else if (! strcmp(this_opt, "nomtrr"))
3381
+ mtrr=0;
3382
+ else if (! strncmp(this_opt, "vtotal:", 7))
3383
+ vram_total = simple_strtoul(this_opt+7, NULL, 0);
3384
+ else if (! strncmp(this_opt, "vremap:", 7))
3385
+ vram_remap = simple_strtoul(this_opt+7, NULL, 0);
3386
+ else if (! strcmp(this_opt, "i17"))
3387
+ model = M_I17;
3388
+ else if (! strcmp(this_opt, "i20"))
3389
+ model = M_I20;
3390
+ else if (! strcmp(this_opt, "mini"))
3391
+ model = M_MINI;
3392
+ else if (! strncmp(this_opt, "height:", 7))
3393
+ manual_height = simple_strtoul(this_opt+7, NULL, 0);
3394
+ else if (! strncmp(this_opt, "width:", 6))
3395
+ manual_width = simple_strtoul(this_opt+6, NULL, 0);
3396
+ }
3397
+ return 0;
3398
+}
3399
+
3400
+#define DEFAULT_FB_MEM 1024*1024*16
3401
+
3402
+static int __init imacfb_probe(struct platform_device *dev)
3403
+{
3404
+ struct fb_info *info;
3405
+ int err;
3406
+ unsigned int size_vmode;
3407
+ unsigned int size_remap;
3408
+ unsigned int size_total;
3409
+
3410
+ screen_info.lfb_base = 0x80010000;
3411
+ screen_info.lfb_depth = 32;
3412
+ screen_info.lfb_size = DEFAULT_FB_MEM / 0x10000;
3413
+ screen_info.pages=1;
3414
+ screen_info.blue_size = 8;
3415
+ screen_info.blue_pos = 0;
3416
+ screen_info.green_size = 8;
3417
+ screen_info.green_pos = 8;
3418
+ screen_info.red_size = 8;
3419
+ screen_info.red_pos = 16;
3420
+ screen_info.rsvd_size = 8;
3421
+ screen_info.rsvd_pos = 24;
3422
+
3423
+ switch(model) {
3424
+ case M_I17:
3425
+ screen_info.lfb_width = 1440;
3426
+ screen_info.lfb_height = 900;
3427
+ screen_info.lfb_linelength = 1472 * 4;
3428
+ break;
3429
+ case M_NEW:
3430
+ case M_I20:
3431
+ screen_info.lfb_width = 1680;
3432
+ screen_info.lfb_height = 1050;
3433
+ screen_info.lfb_linelength = 1728 * 4;
3434
+ break;
3435
+ case M_MINI:
3436
+ screen_info.lfb_width = 1024;
3437
+ screen_info.lfb_height = 768;
3438
+ screen_info.lfb_linelength = 2048 * 4;
3439
+ break;
3440
+ }
3441
+
3442
+ /* if the user wants to manually specify height/width,
3443
+ we will override the defaults */
3444
+ /* TODO: eventually get auto-detection working */
3445
+ if(manual_height > 0)
3446
+ screen_info.lfb_height = manual_height;
3447
+ if(manual_width > 0)
3448
+ screen_info.lfb_width = manual_width;
3449
+
3450
+ /*
3451
+ static void *videomemory;
3452
+ static u_long videomemorysize = (64*1024*1024);
3453
+ videomemory = ioremap(0x80000000,videomemorysize);
3454
+ memset(videomemory, 0x99, videomemorysize);
3455
+ */
3456
+
3457
+ imacfb_fix.smem_start = screen_info.lfb_base;
3458
+ imacfb_defined.bits_per_pixel = screen_info.lfb_depth;
3459
+ if (15 == imacfb_defined.bits_per_pixel)
3460
+ imacfb_defined.bits_per_pixel = 16;
3461
+ imacfb_defined.xres = screen_info.lfb_width;
3462
+ imacfb_defined.yres = screen_info.lfb_height;
3463
+ imacfb_fix.line_length = screen_info.lfb_linelength;
3464
+ imacfb_fix.visual = (imacfb_defined.bits_per_pixel == 8) ?
3465
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
3466
+
3467
+ /* size_vmode -- that is the amount of memory needed for the
3468
+ * used video mode, i.e. the minimum amount of
3469
+ * memory we need. */
3470
+ size_vmode = imacfb_defined.yres * imacfb_fix.line_length;
3471
+
3472
+ /* size_total -- all video memory we have. Used for mtrr
3473
+ * entries, ressource allocation and bounds
3474
+ * checking. */
3475
+ size_total = screen_info.lfb_size * 65536;
3476
+ if (vram_total)
3477
+ size_total = vram_total * 1024 * 1024;
3478
+ if (size_total < size_vmode)
3479
+ size_total = size_vmode;
3480
+
3481
+ /* size_remap -- the amount of video memory we are going to
3482
+ * use for imacfb. With modern cards it is no
3483
+ * option to simply use size_total as that
3484
+ * wastes plenty of kernel address space. */
3485
+ size_remap = size_vmode * 2;
3486
+ if (vram_remap)
3487
+ size_remap = vram_remap * 1024 * 1024;
3488
+ if (size_remap < size_vmode)
3489
+ size_remap = size_vmode;
3490
+ if (size_remap > size_total)
3491
+ size_remap = size_total;
3492
+ imacfb_fix.smem_len = size_remap;
3493
+
3494
+#ifndef __i386__
3495
+ screen_info.imacpm_seg = 0;
3496
+#endif
3497
+
3498
+ if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) {
3499
+ printk(KERN_WARNING
3500
+ "imacfb: cannot reserve video memory at 0x%lx\n",
3501
+ imacfb_fix.smem_start);
3502
+ /* We cannot make this fatal. Sometimes this comes from magic
3503
+ spaces our resource handlers simply don't know about */
3504
+ }
3505
+
3506
+ info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
3507
+ if (!info) {
3508
+ release_mem_region(imacfb_fix.smem_start, size_total);
3509
+ return -ENOMEM;
3510
+ }
3511
+ info->pseudo_palette = info->par;
3512
+ info->par = NULL;
3513
+
3514
+ info->screen_base = ioremap(imacfb_fix.smem_start, imacfb_fix.smem_len);
3515
+ if (!info->screen_base) {
3516
+ printk(KERN_ERR
3517
+ "imacfb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
3518
+ imacfb_fix.smem_len, imacfb_fix.smem_start);
3519
+ err = -EIO;
3520
+ goto err;
3521
+ }
3522
+
3523
+ printk(KERN_INFO "imacfb: framebuffer at 0x%lx, mapped to 0x%p, "
3524
+ "using %dk, total %dk\n",
3525
+ imacfb_fix.smem_start, info->screen_base,
3526
+ size_remap/1024, size_total/1024);
3527
+ printk(KERN_INFO "imacfb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
3528
+ imacfb_defined.xres, imacfb_defined.yres, imacfb_defined.bits_per_pixel, imacfb_fix.line_length, screen_info.pages);
3529
+
3530
+ imacfb_defined.xres_virtual = imacfb_defined.xres;
3531
+ imacfb_defined.yres_virtual = imacfb_fix.smem_len / imacfb_fix.line_length;
3532
+ printk(KERN_INFO "imacfb: scrolling: redraw\n");
3533
+ imacfb_defined.yres_virtual = imacfb_defined.yres;
3534
+
3535
+ /* some dummy values for timing to make fbset happy */
3536
+ imacfb_defined.pixclock = 10000000 / imacfb_defined.xres * 1000 / imacfb_defined.yres;
3537
+ imacfb_defined.left_margin = (imacfb_defined.xres / 8) & 0xf8;
3538
+ imacfb_defined.hsync_len = (imacfb_defined.xres / 8) & 0xf8;
3539
+
3540
+ imacfb_defined.red.offset = screen_info.red_pos;
3541
+ imacfb_defined.red.length = screen_info.red_size;
3542
+ imacfb_defined.green.offset = screen_info.green_pos;
3543
+ imacfb_defined.green.length = screen_info.green_size;
3544
+ imacfb_defined.blue.offset = screen_info.blue_pos;
3545
+ imacfb_defined.blue.length = screen_info.blue_size;
3546
+ imacfb_defined.transp.offset = screen_info.rsvd_pos;
3547
+ imacfb_defined.transp.length = screen_info.rsvd_size;
3548
+
3549
+ if (imacfb_defined.bits_per_pixel <= 8) {
3550
+ depth = imacfb_defined.green.length;
3551
+ imacfb_defined.red.length =
3552
+ imacfb_defined.green.length =
3553
+ imacfb_defined.blue.length =
3554
+ imacfb_defined.bits_per_pixel;
3555
+ }
3556
+
3557
+ printk(KERN_INFO "imacfb: %s: "
3558
+ "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
3559
+ (imacfb_defined.bits_per_pixel > 8) ?
3560
+ "Truecolor" : "Pseudocolor",
3561
+ screen_info.rsvd_size,
3562
+ screen_info.red_size,
3563
+ screen_info.green_size,
3564
+ screen_info.blue_size,
3565
+ screen_info.rsvd_pos,
3566
+ screen_info.red_pos,
3567
+ screen_info.green_pos,
3568
+ screen_info.blue_pos);
3569
+
3570
+ imacfb_fix.ypanstep = 0;
3571
+ imacfb_fix.ywrapstep = 0;
3572
+
3573
+ /* request failure does not faze us, as vgacon probably has this
3574
+ * region already (FIXME) */
3575
+ request_region(0x3c0, 32, "imacfb");
3576
+
3577
+#ifdef CONFIG_MTRR
3578
+ if (mtrr) {
3579
+ unsigned int temp_size = size_total;
3580
+ unsigned int type = 0;
3581
+
3582
+ switch (mtrr) {
3583
+ case 1:
3584
+ type = MTRR_TYPE_UNCACHABLE;
3585
+ break;
3586
+ case 2:
3587
+ type = MTRR_TYPE_WRBACK;
3588
+ break;
3589
+ case 3:
3590
+ type = MTRR_TYPE_WRCOMB;
3591
+ break;
3592
+ case 4:
3593
+ type = MTRR_TYPE_WRTHROUGH;
3594
+ break;
3595
+ default:
3596
+ type = 0;
3597
+ break;
3598
+ }
3599
+
3600
+ if (type) {
3601
+ int rc;
3602
+
3603
+ /* Find the largest power-of-two */
3604
+ while (temp_size & (temp_size - 1))
3605
+ temp_size &= (temp_size - 1);
3606
+
3607
+ /* Try and find a power of two to add */
3608
+ do {
3609
+ rc = mtrr_add(imacfb_fix.smem_start, temp_size,
3610
+ type, 1);
3611
+ temp_size >>= 1;
3612
+ } while (temp_size >= PAGE_SIZE && rc == -EINVAL);
3613
+ }
3614
+ }
3615
+#endif
3616
+
3617
+ info->fbops = &imacfb_ops;
3618
+ info->var = imacfb_defined;
3619
+ info->fix = imacfb_fix;
3620
+ info->flags = FBINFO_FLAG_DEFAULT;
3621
+
3622
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
3623
+ err = -ENOMEM;
3624
+ goto err;
3625
+ }
3626
+ if (register_framebuffer(info)<0) {
3627
+ err = -EINVAL;
3628
+ fb_dealloc_cmap(&info->cmap);
3629
+ goto err;
3630
+ }
3631
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
3632
+ info->node, info->fix.id);
3633
+ return 0;
3634
+err:
3635
+ framebuffer_release(info);
3636
+ release_mem_region(imacfb_fix.smem_start, size_total);
3637
+ return err;
3638
+}
3639
+
3640
+static struct platform_driver imacfb_driver = {
3641
+ .probe = imacfb_probe,
3642
+ .driver = {
3643
+ .name = "imacfb",
3644
+ },
3645
+};
3646
+
3647
+static struct platform_device imacfb_device = {
3648
+ .name = "imacfb",
3649
+};
3650
+
3651
+static int __init imacfb_init(void)
3652
+{
3653
+ int ret;
3654
+ char *option = NULL;
3655
+
3656
+ /* ignore error return of fb_get_options */
3657
+ fb_get_options("imacfb", &option);
3658
+ imacfb_setup(option);
3659
+ ret = platform_driver_register(&imacfb_driver);
3660
+
3661
+ if (!ret) {
3662
+ ret = platform_device_register(&imacfb_device);
3663
+ if (ret)
3664
+ platform_driver_unregister(&imacfb_driver);
3665
+ }
3666
+ return ret;
3667
+}
3668
+module_init(imacfb_init);
3669
+
3670
+MODULE_LICENSE("GPL");
3671
diff -uNr linux-2.6.16/include/linux/efi.h linux-2.6.16-iMac/include/linux/efi.h
3672
--- linux-2.6.16/include/linux/efi.h 2006-01-03 04:21:10.000000000 +0100
3673
+++ linux-2.6.16-iMac/include/linux/efi.h 2006-03-20 10:38:02.000000000 +0100
3674
@@ -163,7 +163,7 @@
3675
efi_time_t *tm);
3676
typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm);
3677
typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
3678
- unsigned long *data_size, void *data);
3679
+ u64 *data_size, void *data);
3680
typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name,
3681
efi_guid_t *vendor);
3682
typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor,
3683
diff -uNr linux-2.6.16/sound/pci/hda/patch_sigmatel.c linux-2.6.16-iMac/sound/pci/hda/patch_sigmatel.c
3684
--- linux-2.6.16/sound/pci/hda/patch_sigmatel.c 2006-03-21 23:01:21.000000000 +0100
3685
+++ linux-2.6.16-iMac/sound/pci/hda/patch_sigmatel.c 2006-03-20 08:01:46.000000000 +0100
3686
@@ -314,6 +314,9 @@
3687
{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
3688
.pci_subdevice = 0x0417,
3689
.config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */
3690
+ { .pci_subvendor = 0x8384,
3691
+ .pci_subdevice = 0x7680,
3692
+ .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */
3693
{} /* terminator */
3694
};
3695
3696