diff options
Diffstat (limited to 'drivers')
212 files changed, 17285 insertions, 6210 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 6a4da417c16b..606f8733a776 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
30 | #include <linux/pm.h> | 30 | #include <linux/pm.h> |
31 | #include <linux/pm_legacy.h> | ||
31 | #include <linux/device.h> | 32 | #include <linux/device.h> |
32 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
33 | #ifdef CONFIG_X86 | 34 | #ifdef CONFIG_X86 |
@@ -754,7 +755,7 @@ static int __init acpi_init(void) | |||
754 | result = acpi_bus_init(); | 755 | result = acpi_bus_init(); |
755 | 756 | ||
756 | if (!result) { | 757 | if (!result) { |
757 | #ifdef CONFIG_PM | 758 | #ifdef CONFIG_PM_LEGACY |
758 | if (!PM_IS_ACTIVE()) | 759 | if (!PM_IS_ACTIVE()) |
759 | pm_active = 1; | 760 | pm_active = 1; |
760 | else { | 761 | else { |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 573b6a97bb1f..70d8a6ec0920 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -514,8 +514,6 @@ static int acpi_processor_set_power_policy(struct acpi_processor *pr) | |||
514 | 514 | ||
515 | static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) | 515 | static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) |
516 | { | 516 | { |
517 | int i; | ||
518 | |||
519 | ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_fadt"); | 517 | ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_fadt"); |
520 | 518 | ||
521 | if (!pr) | 519 | if (!pr) |
@@ -524,8 +522,7 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) | |||
524 | if (!pr->pblk) | 522 | if (!pr->pblk) |
525 | return_VALUE(-ENODEV); | 523 | return_VALUE(-ENODEV); |
526 | 524 | ||
527 | for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) | 525 | memset(pr->power.states, 0, sizeof(pr->power.states)); |
528 | memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); | ||
529 | 526 | ||
530 | /* if info is obtained from pblk/fadt, type equals state */ | 527 | /* if info is obtained from pblk/fadt, type equals state */ |
531 | pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; | 528 | pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; |
@@ -555,13 +552,9 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) | |||
555 | 552 | ||
556 | static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr) | 553 | static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr) |
557 | { | 554 | { |
558 | int i; | ||
559 | |||
560 | ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1"); | 555 | ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1"); |
561 | 556 | ||
562 | for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) | 557 | memset(pr->power.states, 0, sizeof(pr->power.states)); |
563 | memset(&(pr->power.states[i]), 0, | ||
564 | sizeof(struct acpi_processor_cx)); | ||
565 | 558 | ||
566 | /* if info is obtained from pblk/fadt, type equals state */ | 559 | /* if info is obtained from pblk/fadt, type equals state */ |
567 | pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; | 560 | pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; |
@@ -873,7 +866,8 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr) | |||
873 | for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { | 866 | for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { |
874 | if (pr->power.states[i].valid) { | 867 | if (pr->power.states[i].valid) { |
875 | pr->power.count = i; | 868 | pr->power.count = i; |
876 | pr->flags.power = 1; | 869 | if (pr->power.states[i].type >= ACPI_STATE_C2) |
870 | pr->flags.power = 1; | ||
877 | } | 871 | } |
878 | } | 872 | } |
879 | 873 | ||
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 98f6c02d6790..59dacb6552c0 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -526,18 +526,23 @@ request_firmware_work_func(void *arg) | |||
526 | { | 526 | { |
527 | struct firmware_work *fw_work = arg; | 527 | struct firmware_work *fw_work = arg; |
528 | const struct firmware *fw; | 528 | const struct firmware *fw; |
529 | int ret; | ||
529 | if (!arg) { | 530 | if (!arg) { |
530 | WARN_ON(1); | 531 | WARN_ON(1); |
531 | return 0; | 532 | return 0; |
532 | } | 533 | } |
533 | daemonize("%s/%s", "firmware", fw_work->name); | 534 | daemonize("%s/%s", "firmware", fw_work->name); |
534 | _request_firmware(&fw, fw_work->name, fw_work->device, | 535 | ret = _request_firmware(&fw, fw_work->name, fw_work->device, |
535 | fw_work->hotplug); | 536 | fw_work->hotplug); |
536 | fw_work->cont(fw, fw_work->context); | 537 | if (ret < 0) |
537 | release_firmware(fw); | 538 | fw_work->cont(NULL, fw_work->context); |
539 | else { | ||
540 | fw_work->cont(fw, fw_work->context); | ||
541 | release_firmware(fw); | ||
542 | } | ||
538 | module_put(fw_work->module); | 543 | module_put(fw_work->module); |
539 | kfree(fw_work); | 544 | kfree(fw_work); |
540 | return 0; | 545 | return ret; |
541 | } | 546 | } |
542 | 547 | ||
543 | /** | 548 | /** |
@@ -586,6 +591,8 @@ request_firmware_nowait( | |||
586 | 591 | ||
587 | if (ret < 0) { | 592 | if (ret < 0) { |
588 | fw_work->cont(NULL, fw_work->context); | 593 | fw_work->cont(NULL, fw_work->context); |
594 | module_put(fw_work->module); | ||
595 | kfree(fw_work); | ||
589 | return ret; | 596 | return ret; |
590 | } | 597 | } |
591 | return 0; | 598 | return 0; |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 3226aa11c6ef..2942d32280a5 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -255,7 +255,7 @@ scsi_cmd_stack_free(int ctlr) | |||
255 | #define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ | 255 | #define DEVICETYPE(n) (n<0 || n>MAX_SCSI_DEVICE_CODE) ? \ |
256 | "Unknown" : scsi_device_types[n] | 256 | "Unknown" : scsi_device_types[n] |
257 | 257 | ||
258 | #if 1 | 258 | #if 0 |
259 | static int xmargin=8; | 259 | static int xmargin=8; |
260 | static int amargin=60; | 260 | static int amargin=60; |
261 | 261 | ||
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 59e5982a5db3..c0233efabeba 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -1188,7 +1188,7 @@ static void pkt_count_states(struct pktcdvd_device *pd, int *states) | |||
1188 | struct packet_data *pkt; | 1188 | struct packet_data *pkt; |
1189 | int i; | 1189 | int i; |
1190 | 1190 | ||
1191 | for (i = 0; i <= PACKET_NUM_STATES; i++) | 1191 | for (i = 0; i < PACKET_NUM_STATES; i++) |
1192 | states[i] = 0; | 1192 | states[i] = 0; |
1193 | 1193 | ||
1194 | spin_lock(&pd->cdrw.active_list_lock); | 1194 | spin_lock(&pd->cdrw.active_list_lock); |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index fdf4370db994..970f70d498f4 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -735,7 +735,7 @@ config SGI_IP27_RTC | |||
735 | 735 | ||
736 | config GEN_RTC | 736 | config GEN_RTC |
737 | tristate "Generic /dev/rtc emulation" | 737 | tristate "Generic /dev/rtc emulation" |
738 | depends on RTC!=y && !IA64 && !ARM && !PPC64 && !M32R && !SPARC32 && !SPARC64 | 738 | depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC32 && !SPARC64 |
739 | ---help--- | 739 | ---help--- |
740 | If you say Y here and create a character special file /dev/rtc with | 740 | If you say Y here and create a character special file /dev/rtc with |
741 | major number 10 and minor number 135 using mknod ("man mknod"), you | 741 | major number 10 and minor number 135 using mknod ("man mknod"), you |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 78ce98a69f37..76589782adcb 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -57,9 +57,8 @@ static int nr_garts; | |||
57 | static struct pci_dev * hammers[MAX_HAMMER_GARTS]; | 57 | static struct pci_dev * hammers[MAX_HAMMER_GARTS]; |
58 | 58 | ||
59 | static struct resource *aperture_resource; | 59 | static struct resource *aperture_resource; |
60 | static int __initdata agp_try_unsupported; | 60 | static int __initdata agp_try_unsupported = 1; |
61 | 61 | ||
62 | static int gart_iterator; | ||
63 | #define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++) | 62 | #define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++) |
64 | 63 | ||
65 | static void flush_amd64_tlb(struct pci_dev *dev) | 64 | static void flush_amd64_tlb(struct pci_dev *dev) |
@@ -73,6 +72,7 @@ static void flush_amd64_tlb(struct pci_dev *dev) | |||
73 | 72 | ||
74 | static void amd64_tlbflush(struct agp_memory *temp) | 73 | static void amd64_tlbflush(struct agp_memory *temp) |
75 | { | 74 | { |
75 | int gart_iterator; | ||
76 | for_each_nb() | 76 | for_each_nb() |
77 | flush_amd64_tlb(hammers[gart_iterator]); | 77 | flush_amd64_tlb(hammers[gart_iterator]); |
78 | } | 78 | } |
@@ -222,6 +222,7 @@ static struct aper_size_info_32 amd_8151_sizes[7] = | |||
222 | static int amd_8151_configure(void) | 222 | static int amd_8151_configure(void) |
223 | { | 223 | { |
224 | unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real); | 224 | unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real); |
225 | int gart_iterator; | ||
225 | 226 | ||
226 | /* Configure AGP regs in each x86-64 host bridge. */ | 227 | /* Configure AGP regs in each x86-64 host bridge. */ |
227 | for_each_nb() { | 228 | for_each_nb() { |
@@ -235,7 +236,7 @@ static int amd_8151_configure(void) | |||
235 | static void amd64_cleanup(void) | 236 | static void amd64_cleanup(void) |
236 | { | 237 | { |
237 | u32 tmp; | 238 | u32 tmp; |
238 | 239 | int gart_iterator; | |
239 | for_each_nb() { | 240 | for_each_nb() { |
240 | /* disable gart translation */ | 241 | /* disable gart translation */ |
241 | pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp); | 242 | pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp); |
@@ -697,6 +698,16 @@ static struct pci_device_id agp_amd64_pci_table[] = { | |||
697 | .subvendor = PCI_ANY_ID, | 698 | .subvendor = PCI_ANY_ID, |
698 | .subdevice = PCI_ANY_ID, | 699 | .subdevice = PCI_ANY_ID, |
699 | }, | 700 | }, |
701 | /* ALI/ULI M1695 */ | ||
702 | { | ||
703 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
704 | .class_mask = ~0, | ||
705 | .vendor = PCI_VENDOR_ID_AL, | ||
706 | .device = 0x1689, | ||
707 | .subvendor = PCI_ANY_ID, | ||
708 | .subdevice = PCI_ANY_ID, | ||
709 | }, | ||
710 | |||
700 | { } | 711 | { } |
701 | }; | 712 | }; |
702 | 713 | ||
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index c8255312b8c1..50947e38501a 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c | |||
@@ -557,6 +557,10 @@ static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = { | |||
557 | .device_id = PCI_DEVICE_ID_APPLE_U3H_AGP, | 557 | .device_id = PCI_DEVICE_ID_APPLE_U3H_AGP, |
558 | .chipset_name = "U3H", | 558 | .chipset_name = "U3H", |
559 | }, | 559 | }, |
560 | { | ||
561 | .device_id = PCI_DEVICE_ID_APPLE_IPID2_AGP, | ||
562 | .chipset_name = "UniNorth/Intrepid2", | ||
563 | }, | ||
560 | }; | 564 | }; |
561 | 565 | ||
562 | static int __devinit agp_uninorth_probe(struct pci_dev *pdev, | 566 | static int __devinit agp_uninorth_probe(struct pci_dev *pdev, |
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 6c4b3f986d0c..f3c3aaf4560e 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c | |||
@@ -99,7 +99,9 @@ struct smm_regs { | |||
99 | 99 | ||
100 | static inline char *i8k_get_dmi_data(int field) | 100 | static inline char *i8k_get_dmi_data(int field) |
101 | { | 101 | { |
102 | return dmi_get_system_info(field) ? : "N/A"; | 102 | char *dmi_data = dmi_get_system_info(field); |
103 | |||
104 | return dmi_data && *dmi_data ? dmi_data : "?"; | ||
103 | } | 105 | } |
104 | 106 | ||
105 | /* | 107 | /* |
@@ -396,7 +398,7 @@ static int i8k_proc_show(struct seq_file *seq, void *offset) | |||
396 | return seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n", | 398 | return seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n", |
397 | I8K_PROC_FMT, | 399 | I8K_PROC_FMT, |
398 | bios_version, | 400 | bios_version, |
399 | dmi_get_system_info(DMI_PRODUCT_SERIAL) ? : "N/A", | 401 | i8k_get_dmi_data(DMI_PRODUCT_SERIAL), |
400 | cpu_temp, | 402 | cpu_temp, |
401 | left_fan, right_fan, left_speed, right_speed, | 403 | left_fan, right_fan, left_speed, right_speed, |
402 | ac_power, fn_key); | 404 | ac_power, fn_key); |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index d16bd4b5c117..6b302a930e5f 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -48,7 +48,7 @@ | |||
48 | 48 | ||
49 | #define PFX "IPMI message handler: " | 49 | #define PFX "IPMI message handler: " |
50 | 50 | ||
51 | #define IPMI_DRIVER_VERSION "36.0" | 51 | #define IPMI_DRIVER_VERSION "38.0" |
52 | 52 | ||
53 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); | 53 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); |
54 | static int ipmi_init_msghandler(void); | 54 | static int ipmi_init_msghandler(void); |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index ea89dca3dbb5..01a1f6badb53 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -2203,7 +2203,7 @@ static void setup_xaction_handlers(struct smi_info *smi_info) | |||
2203 | 2203 | ||
2204 | static inline void wait_for_timer_and_thread(struct smi_info *smi_info) | 2204 | static inline void wait_for_timer_and_thread(struct smi_info *smi_info) |
2205 | { | 2205 | { |
2206 | if (smi_info->thread != ERR_PTR(-ENOMEM)) | 2206 | if (smi_info->thread != NULL && smi_info->thread != ERR_PTR(-ENOMEM)) |
2207 | kthread_stop(smi_info->thread); | 2207 | kthread_stop(smi_info->thread); |
2208 | del_timer_sync(&smi_info->si_timer); | 2208 | del_timer_sync(&smi_info->si_timer); |
2209 | } | 2209 | } |
diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig index d22bfdc13563..27c1179ee527 100644 --- a/drivers/char/pcmcia/Kconfig +++ b/drivers/char/pcmcia/Kconfig | |||
@@ -18,5 +18,29 @@ config SYNCLINK_CS | |||
18 | The module will be called synclinkmp. If you want to do that, say M | 18 | The module will be called synclinkmp. If you want to do that, say M |
19 | here. | 19 | here. |
20 | 20 | ||
21 | config CARDMAN_4000 | ||
22 | tristate "Omnikey Cardman 4000 support" | ||
23 | depends on PCMCIA | ||
24 | help | ||
25 | Enable support for the Omnikey Cardman 4000 PCMCIA Smartcard | ||
26 | reader. | ||
27 | |||
28 | This kernel driver requires additional userspace support, either | ||
29 | by the vendor-provided PC/SC ifd_handler (http://www.omnikey.com/), | ||
30 | or via the cm4000 backend of OpenCT (http://www.opensc.com/). | ||
31 | |||
32 | config CARDMAN_4040 | ||
33 | tristate "Omnikey CardMan 4040 support" | ||
34 | depends on PCMCIA | ||
35 | help | ||
36 | Enable support for the Omnikey CardMan 4040 PCMCIA Smartcard | ||
37 | reader. | ||
38 | |||
39 | This card is basically a USB CCID device connected to a FIFO | ||
40 | in I/O space. To use the kernel driver, you will need either the | ||
41 | PC/SC ifdhandler provided from the Omnikey homepage | ||
42 | (http://www.omnikey.com/), or a current development version of OpenCT | ||
43 | (http://www.opensc.org/). | ||
44 | |||
21 | endmenu | 45 | endmenu |
22 | 46 | ||
diff --git a/drivers/char/pcmcia/Makefile b/drivers/char/pcmcia/Makefile index 1fcd4c591958..0aae20985d57 100644 --- a/drivers/char/pcmcia/Makefile +++ b/drivers/char/pcmcia/Makefile | |||
@@ -5,3 +5,5 @@ | |||
5 | # | 5 | # |
6 | 6 | ||
7 | obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o | 7 | obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o |
8 | obj-$(CONFIG_CARDMAN_4000) += cm4000_cs.o | ||
9 | obj-$(CONFIG_CARDMAN_4040) += cm4040_cs.o | ||
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c new file mode 100644 index 000000000000..ef011ef5dc46 --- /dev/null +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -0,0 +1,2078 @@ | |||
1 | /* | ||
2 | * A driver for the PCMCIA Smartcard Reader "Omnikey CardMan Mobile 4000" | ||
3 | * | ||
4 | * cm4000_cs.c support.linux@omnikey.com | ||
5 | * | ||
6 | * Tue Oct 23 11:32:43 GMT 2001 herp - cleaned up header files | ||
7 | * Sun Jan 20 10:11:15 MET 2002 herp - added modversion header files | ||
8 | * Thu Nov 14 16:34:11 GMT 2002 mh - added PPS functionality | ||
9 | * Tue Nov 19 16:36:27 GMT 2002 mh - added SUSPEND/RESUME functionailty | ||
10 | * Wed Jul 28 12:55:01 CEST 2004 mh - kernel 2.6 adjustments | ||
11 | * | ||
12 | * current version: 2.4.0gm4 | ||
13 | * | ||
14 | * (C) 2000,2001,2002,2003,2004 Omnikey AG | ||
15 | * | ||
16 | * (C) 2005 Harald Welte <laforge@gnumonks.org> | ||
17 | * - Adhere to Kernel CodingStyle | ||
18 | * - Port to 2.6.13 "new" style PCMCIA | ||
19 | * - Check for copy_{from,to}_user return values | ||
20 | * - Use nonseekable_open() | ||
21 | * | ||
22 | * All rights reserved. Licensed under dual BSD/GPL license. | ||
23 | */ | ||
24 | |||
25 | /* #define PCMCIA_DEBUG 6 */ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/fs.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <asm/uaccess.h> | ||
34 | #include <asm/io.h> | ||
35 | |||
36 | #include <pcmcia/cs_types.h> | ||
37 | #include <pcmcia/cs.h> | ||
38 | #include <pcmcia/cistpl.h> | ||
39 | #include <pcmcia/cisreg.h> | ||
40 | #include <pcmcia/ciscode.h> | ||
41 | #include <pcmcia/ds.h> | ||
42 | |||
43 | #include <linux/cm4000_cs.h> | ||
44 | |||
45 | /* #define ATR_CSUM */ | ||
46 | |||
47 | #ifdef PCMCIA_DEBUG | ||
48 | #define reader_to_dev(x) (&handle_to_dev(x->link.handle)) | ||
49 | static int pc_debug = PCMCIA_DEBUG; | ||
50 | module_param(pc_debug, int, 0600); | ||
51 | #define DEBUGP(n, rdr, x, args...) do { \ | ||
52 | if (pc_debug >= (n)) \ | ||
53 | dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x, \ | ||
54 | __FUNCTION__ , ## args); \ | ||
55 | } while (0) | ||
56 | #else | ||
57 | #define DEBUGP(n, rdr, x, args...) | ||
58 | #endif | ||
59 | static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte"; | ||
60 | |||
61 | #define T_1SEC (HZ) | ||
62 | #define T_10MSEC msecs_to_jiffies(10) | ||
63 | #define T_20MSEC msecs_to_jiffies(20) | ||
64 | #define T_40MSEC msecs_to_jiffies(40) | ||
65 | #define T_50MSEC msecs_to_jiffies(50) | ||
66 | #define T_100MSEC msecs_to_jiffies(100) | ||
67 | #define T_500MSEC msecs_to_jiffies(500) | ||
68 | |||
69 | static void cm4000_detach(dev_link_t *link); | ||
70 | static void cm4000_release(dev_link_t *link); | ||
71 | |||
72 | static int major; /* major number we get from the kernel */ | ||
73 | |||
74 | /* note: the first state has to have number 0 always */ | ||
75 | |||
76 | #define M_FETCH_ATR 0 | ||
77 | #define M_TIMEOUT_WAIT 1 | ||
78 | #define M_READ_ATR_LEN 2 | ||
79 | #define M_READ_ATR 3 | ||
80 | #define M_ATR_PRESENT 4 | ||
81 | #define M_BAD_CARD 5 | ||
82 | #define M_CARDOFF 6 | ||
83 | |||
84 | #define LOCK_IO 0 | ||
85 | #define LOCK_MONITOR 1 | ||
86 | |||
87 | #define IS_AUTOPPS_ACT 6 | ||
88 | #define IS_PROCBYTE_PRESENT 7 | ||
89 | #define IS_INVREV 8 | ||
90 | #define IS_ANY_T0 9 | ||
91 | #define IS_ANY_T1 10 | ||
92 | #define IS_ATR_PRESENT 11 | ||
93 | #define IS_ATR_VALID 12 | ||
94 | #define IS_CMM_ABSENT 13 | ||
95 | #define IS_BAD_LENGTH 14 | ||
96 | #define IS_BAD_CSUM 15 | ||
97 | #define IS_BAD_CARD 16 | ||
98 | |||
99 | #define REG_FLAGS0(x) (x + 0) | ||
100 | #define REG_FLAGS1(x) (x + 1) | ||
101 | #define REG_NUM_BYTES(x) (x + 2) | ||
102 | #define REG_BUF_ADDR(x) (x + 3) | ||
103 | #define REG_BUF_DATA(x) (x + 4) | ||
104 | #define REG_NUM_SEND(x) (x + 5) | ||
105 | #define REG_BAUDRATE(x) (x + 6) | ||
106 | #define REG_STOPBITS(x) (x + 7) | ||
107 | |||
108 | struct cm4000_dev { | ||
109 | dev_link_t link; /* pcmcia link */ | ||
110 | dev_node_t node; /* OS node (major,minor) */ | ||
111 | |||
112 | unsigned char atr[MAX_ATR]; | ||
113 | unsigned char rbuf[512]; | ||
114 | unsigned char sbuf[512]; | ||
115 | |||
116 | wait_queue_head_t devq; /* when removing cardman must not be | ||
117 | zeroed! */ | ||
118 | |||
119 | wait_queue_head_t ioq; /* if IO is locked, wait on this Q */ | ||
120 | wait_queue_head_t atrq; /* wait for ATR valid */ | ||
121 | wait_queue_head_t readq; /* used by write to wake blk.read */ | ||
122 | |||
123 | /* warning: do not move this fields. | ||
124 | * initialising to zero depends on it - see ZERO_DEV below. */ | ||
125 | unsigned char atr_csum; | ||
126 | unsigned char atr_len_retry; | ||
127 | unsigned short atr_len; | ||
128 | unsigned short rlen; /* bytes avail. after write */ | ||
129 | unsigned short rpos; /* latest read pos. write zeroes */ | ||
130 | unsigned char procbyte; /* T=0 procedure byte */ | ||
131 | unsigned char mstate; /* state of card monitor */ | ||
132 | unsigned char cwarn; /* slow down warning */ | ||
133 | unsigned char flags0; /* cardman IO-flags 0 */ | ||
134 | unsigned char flags1; /* cardman IO-flags 1 */ | ||
135 | unsigned int mdelay; /* variable monitor speeds, in jiffies */ | ||
136 | |||
137 | unsigned int baudv; /* baud value for speed */ | ||
138 | unsigned char ta1; | ||
139 | unsigned char proto; /* T=0, T=1, ... */ | ||
140 | unsigned long flags; /* lock+flags (MONITOR,IO,ATR) * for concurrent | ||
141 | access */ | ||
142 | |||
143 | unsigned char pts[4]; | ||
144 | |||
145 | struct timer_list timer; /* used to keep monitor running */ | ||
146 | int monitor_running; | ||
147 | }; | ||
148 | |||
149 | #define ZERO_DEV(dev) \ | ||
150 | memset(&dev->atr_csum,0, \ | ||
151 | sizeof(struct cm4000_dev) - \ | ||
152 | /*link*/ sizeof(dev_link_t) - \ | ||
153 | /*node*/ sizeof(dev_node_t) - \ | ||
154 | /*atr*/ MAX_ATR*sizeof(char) - \ | ||
155 | /*rbuf*/ 512*sizeof(char) - \ | ||
156 | /*sbuf*/ 512*sizeof(char) - \ | ||
157 | /*queue*/ 4*sizeof(wait_queue_head_t)) | ||
158 | |||
159 | static dev_info_t dev_info = MODULE_NAME; | ||
160 | static dev_link_t *dev_table[CM4000_MAX_DEV]; | ||
161 | |||
162 | /* This table doesn't use spaces after the comma between fields and thus | ||
163 | * violates CodingStyle. However, I don't really think wrapping it around will | ||
164 | * make it any clearer to read -HW */ | ||
165 | static unsigned char fi_di_table[10][14] = { | ||
166 | /*FI 00 01 02 03 04 05 06 07 08 09 10 11 12 13 */ | ||
167 | /*DI */ | ||
168 | /* 0 */ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, | ||
169 | /* 1 */ {0x01,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x91,0x11,0x11,0x11,0x11}, | ||
170 | /* 2 */ {0x02,0x12,0x22,0x32,0x11,0x11,0x11,0x11,0x11,0x92,0xA2,0xB2,0x11,0x11}, | ||
171 | /* 3 */ {0x03,0x13,0x23,0x33,0x43,0x53,0x63,0x11,0x11,0x93,0xA3,0xB3,0xC3,0xD3}, | ||
172 | /* 4 */ {0x04,0x14,0x24,0x34,0x44,0x54,0x64,0x11,0x11,0x94,0xA4,0xB4,0xC4,0xD4}, | ||
173 | /* 5 */ {0x00,0x15,0x25,0x35,0x45,0x55,0x65,0x11,0x11,0x95,0xA5,0xB5,0xC5,0xD5}, | ||
174 | /* 6 */ {0x06,0x16,0x26,0x36,0x46,0x56,0x66,0x11,0x11,0x96,0xA6,0xB6,0xC6,0xD6}, | ||
175 | /* 7 */ {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, | ||
176 | /* 8 */ {0x08,0x11,0x28,0x38,0x48,0x58,0x68,0x11,0x11,0x98,0xA8,0xB8,0xC8,0xD8}, | ||
177 | /* 9 */ {0x09,0x19,0x29,0x39,0x49,0x59,0x69,0x11,0x11,0x99,0xA9,0xB9,0xC9,0xD9} | ||
178 | }; | ||
179 | |||
180 | #ifndef PCMCIA_DEBUG | ||
181 | #define xoutb outb | ||
182 | #define xinb inb | ||
183 | #else | ||
184 | static inline void xoutb(unsigned char val, unsigned short port) | ||
185 | { | ||
186 | if (pc_debug >= 7) | ||
187 | printk(KERN_DEBUG "outb(val=%.2x,port=%.4x)\n", val, port); | ||
188 | outb(val, port); | ||
189 | } | ||
190 | static inline unsigned char xinb(unsigned short port) | ||
191 | { | ||
192 | unsigned char val; | ||
193 | |||
194 | val = inb(port); | ||
195 | if (pc_debug >= 7) | ||
196 | printk(KERN_DEBUG "%.2x=inb(%.4x)\n", val, port); | ||
197 | |||
198 | return val; | ||
199 | } | ||
200 | #endif | ||
201 | |||
202 | #define b_0000 15 | ||
203 | #define b_0001 14 | ||
204 | #define b_0010 13 | ||
205 | #define b_0011 12 | ||
206 | #define b_0100 11 | ||
207 | #define b_0101 10 | ||
208 | #define b_0110 9 | ||
209 | #define b_0111 8 | ||
210 | #define b_1000 7 | ||
211 | #define b_1001 6 | ||
212 | #define b_1010 5 | ||
213 | #define b_1011 4 | ||
214 | #define b_1100 3 | ||
215 | #define b_1101 2 | ||
216 | #define b_1110 1 | ||
217 | #define b_1111 0 | ||
218 | |||
219 | static unsigned char irtab[16] = { | ||
220 | b_0000, b_1000, b_0100, b_1100, | ||
221 | b_0010, b_1010, b_0110, b_1110, | ||
222 | b_0001, b_1001, b_0101, b_1101, | ||
223 | b_0011, b_1011, b_0111, b_1111 | ||
224 | }; | ||
225 | |||
226 | static void str_invert_revert(unsigned char *b, int len) | ||
227 | { | ||
228 | int i; | ||
229 | |||
230 | for (i = 0; i < len; i++) | ||
231 | b[i] = (irtab[b[i] & 0x0f] << 4) | irtab[b[i] >> 4]; | ||
232 | } | ||
233 | |||
234 | static unsigned char invert_revert(unsigned char ch) | ||
235 | { | ||
236 | return (irtab[ch & 0x0f] << 4) | irtab[ch >> 4]; | ||
237 | } | ||
238 | |||
239 | #define ATRLENCK(dev,pos) \ | ||
240 | if (pos>=dev->atr_len || pos>=MAX_ATR) \ | ||
241 | goto return_0; | ||
242 | |||
243 | static unsigned int calc_baudv(unsigned char fidi) | ||
244 | { | ||
245 | unsigned int wcrcf, wbrcf, fi_rfu, di_rfu; | ||
246 | |||
247 | fi_rfu = 372; | ||
248 | di_rfu = 1; | ||
249 | |||
250 | /* FI */ | ||
251 | switch ((fidi >> 4) & 0x0F) { | ||
252 | case 0x00: | ||
253 | wcrcf = 372; | ||
254 | break; | ||
255 | case 0x01: | ||
256 | wcrcf = 372; | ||
257 | break; | ||
258 | case 0x02: | ||
259 | wcrcf = 558; | ||
260 | break; | ||
261 | case 0x03: | ||
262 | wcrcf = 744; | ||
263 | break; | ||
264 | case 0x04: | ||
265 | wcrcf = 1116; | ||
266 | break; | ||
267 | case 0x05: | ||
268 | wcrcf = 1488; | ||
269 | break; | ||
270 | case 0x06: | ||
271 | wcrcf = 1860; | ||
272 | break; | ||
273 | case 0x07: | ||
274 | wcrcf = fi_rfu; | ||
275 | break; | ||
276 | case 0x08: | ||
277 | wcrcf = fi_rfu; | ||
278 | break; | ||
279 | case 0x09: | ||
280 | wcrcf = 512; | ||
281 | break; | ||
282 | case 0x0A: | ||
283 | wcrcf = 768; | ||
284 | break; | ||
285 | case 0x0B: | ||
286 | wcrcf = 1024; | ||
287 | break; | ||
288 | case 0x0C: | ||
289 | wcrcf = 1536; | ||
290 | break; | ||
291 | case 0x0D: | ||
292 | wcrcf = 2048; | ||
293 | break; | ||
294 | default: | ||
295 | wcrcf = fi_rfu; | ||
296 | break; | ||
297 | } | ||
298 | |||
299 | /* DI */ | ||
300 | switch (fidi & 0x0F) { | ||
301 | case 0x00: | ||
302 | wbrcf = di_rfu; | ||
303 | break; | ||
304 | case 0x01: | ||
305 | wbrcf = 1; | ||
306 | break; | ||
307 | case 0x02: | ||
308 | wbrcf = 2; | ||
309 | break; | ||
310 | case 0x03: | ||
311 | wbrcf = 4; | ||
312 | break; | ||
313 | case 0x04: | ||
314 | wbrcf = 8; | ||
315 | break; | ||
316 | case 0x05: | ||
317 | wbrcf = 16; | ||
318 | break; | ||
319 | case 0x06: | ||
320 | wbrcf = 32; | ||
321 | break; | ||
322 | case 0x07: | ||
323 | wbrcf = di_rfu; | ||
324 | break; | ||
325 | case 0x08: | ||
326 | wbrcf = 12; | ||
327 | break; | ||
328 | case 0x09: | ||
329 | wbrcf = 20; | ||
330 | break; | ||
331 | default: | ||
332 | wbrcf = di_rfu; | ||
333 | break; | ||
334 | } | ||
335 | |||
336 | return (wcrcf / wbrcf); | ||
337 | } | ||
338 | |||
339 | static unsigned short io_read_num_rec_bytes(ioaddr_t iobase, unsigned short *s) | ||
340 | { | ||
341 | unsigned short tmp; | ||
342 | |||
343 | tmp = *s = 0; | ||
344 | do { | ||
345 | *s = tmp; | ||
346 | tmp = inb(REG_NUM_BYTES(iobase)) | | ||
347 | (inb(REG_FLAGS0(iobase)) & 4 ? 0x100 : 0); | ||
348 | } while (tmp != *s); | ||
349 | |||
350 | return *s; | ||
351 | } | ||
352 | |||
353 | static int parse_atr(struct cm4000_dev *dev) | ||
354 | { | ||
355 | unsigned char any_t1, any_t0; | ||
356 | unsigned char ch, ifno; | ||
357 | int ix, done; | ||
358 | |||
359 | DEBUGP(3, dev, "-> parse_atr: dev->atr_len = %i\n", dev->atr_len); | ||
360 | |||
361 | if (dev->atr_len < 3) { | ||
362 | DEBUGP(5, dev, "parse_atr: atr_len < 3\n"); | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | if (dev->atr[0] == 0x3f) | ||
367 | set_bit(IS_INVREV, &dev->flags); | ||
368 | else | ||
369 | clear_bit(IS_INVREV, &dev->flags); | ||
370 | ix = 1; | ||
371 | ifno = 1; | ||
372 | ch = dev->atr[1]; | ||
373 | dev->proto = 0; /* XXX PROTO */ | ||
374 | any_t1 = any_t0 = done = 0; | ||
375 | dev->ta1 = 0x11; /* defaults to 9600 baud */ | ||
376 | do { | ||
377 | if (ifno == 1 && (ch & 0x10)) { | ||
378 | /* read first interface byte and TA1 is present */ | ||
379 | dev->ta1 = dev->atr[2]; | ||
380 | DEBUGP(5, dev, "Card says FiDi is 0x%.2x\n", dev->ta1); | ||
381 | ifno++; | ||
382 | } else if ((ifno == 2) && (ch & 0x10)) { /* TA(2) */ | ||
383 | dev->ta1 = 0x11; | ||
384 | ifno++; | ||
385 | } | ||
386 | |||
387 | DEBUGP(5, dev, "Yi=%.2x\n", ch & 0xf0); | ||
388 | ix += ((ch & 0x10) >> 4) /* no of int.face chars */ | ||
389 | +((ch & 0x20) >> 5) | ||
390 | + ((ch & 0x40) >> 6) | ||
391 | + ((ch & 0x80) >> 7); | ||
392 | /* ATRLENCK(dev,ix); */ | ||
393 | if (ch & 0x80) { /* TDi */ | ||
394 | ch = dev->atr[ix]; | ||
395 | if ((ch & 0x0f)) { | ||
396 | any_t1 = 1; | ||
397 | DEBUGP(5, dev, "card is capable of T=1\n"); | ||
398 | } else { | ||
399 | any_t0 = 1; | ||
400 | DEBUGP(5, dev, "card is capable of T=0\n"); | ||
401 | } | ||
402 | } else | ||
403 | done = 1; | ||
404 | } while (!done); | ||
405 | |||
406 | DEBUGP(5, dev, "ix=%d noHist=%d any_t1=%d\n", | ||
407 | ix, dev->atr[1] & 15, any_t1); | ||
408 | if (ix + 1 + (dev->atr[1] & 0x0f) + any_t1 != dev->atr_len) { | ||
409 | DEBUGP(5, dev, "length error\n"); | ||
410 | return 0; | ||
411 | } | ||
412 | if (any_t0) | ||
413 | set_bit(IS_ANY_T0, &dev->flags); | ||
414 | |||
415 | if (any_t1) { /* compute csum */ | ||
416 | dev->atr_csum = 0; | ||
417 | #ifdef ATR_CSUM | ||
418 | for (i = 1; i < dev->atr_len; i++) | ||
419 | dev->atr_csum ^= dev->atr[i]; | ||
420 | if (dev->atr_csum) { | ||
421 | set_bit(IS_BAD_CSUM, &dev->flags); | ||
422 | DEBUGP(5, dev, "bad checksum\n"); | ||
423 | goto return_0; | ||
424 | } | ||
425 | #endif | ||
426 | if (any_t0 == 0) | ||
427 | dev->proto = 1; /* XXX PROTO */ | ||
428 | set_bit(IS_ANY_T1, &dev->flags); | ||
429 | } | ||
430 | |||
431 | return 1; | ||
432 | } | ||
433 | |||
434 | struct card_fixup { | ||
435 | char atr[12]; | ||
436 | u_int8_t atr_len; | ||
437 | u_int8_t stopbits; | ||
438 | }; | ||
439 | |||
440 | static struct card_fixup card_fixups[] = { | ||
441 | { /* ACOS */ | ||
442 | .atr = { 0x3b, 0xb3, 0x11, 0x00, 0x00, 0x41, 0x01 }, | ||
443 | .atr_len = 7, | ||
444 | .stopbits = 0x03, | ||
445 | }, | ||
446 | { /* Motorola */ | ||
447 | .atr = {0x3b, 0x76, 0x13, 0x00, 0x00, 0x80, 0x62, 0x07, | ||
448 | 0x41, 0x81, 0x81 }, | ||
449 | .atr_len = 11, | ||
450 | .stopbits = 0x04, | ||
451 | }, | ||
452 | }; | ||
453 | |||
454 | static void set_cardparameter(struct cm4000_dev *dev) | ||
455 | { | ||
456 | int i; | ||
457 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
458 | u_int8_t stopbits = 0x02; /* ISO default */ | ||
459 | |||
460 | DEBUGP(3, dev, "-> set_cardparameter\n"); | ||
461 | |||
462 | dev->flags1 = dev->flags1 | (((dev->baudv - 1) & 0x0100) >> 8); | ||
463 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
464 | DEBUGP(5, dev, "flags1 = 0x%02x\n", dev->flags1); | ||
465 | |||
466 | /* set baudrate */ | ||
467 | xoutb((unsigned char)((dev->baudv - 1) & 0xFF), REG_BAUDRATE(iobase)); | ||
468 | |||
469 | DEBUGP(5, dev, "baudv = %i -> write 0x%02x\n", dev->baudv, | ||
470 | ((dev->baudv - 1) & 0xFF)); | ||
471 | |||
472 | /* set stopbits */ | ||
473 | for (i = 0; i < ARRAY_SIZE(card_fixups); i++) { | ||
474 | if (!memcmp(dev->atr, card_fixups[i].atr, | ||
475 | card_fixups[i].atr_len)) | ||
476 | stopbits = card_fixups[i].stopbits; | ||
477 | } | ||
478 | xoutb(stopbits, REG_STOPBITS(iobase)); | ||
479 | |||
480 | DEBUGP(3, dev, "<- set_cardparameter\n"); | ||
481 | } | ||
482 | |||
483 | static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) | ||
484 | { | ||
485 | |||
486 | unsigned long tmp, i; | ||
487 | unsigned short num_bytes_read; | ||
488 | unsigned char pts_reply[4]; | ||
489 | ssize_t rc; | ||
490 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
491 | |||
492 | rc = 0; | ||
493 | |||
494 | DEBUGP(3, dev, "-> set_protocol\n"); | ||
495 | DEBUGP(5, dev, "ptsreq->Protocol = 0x%.8x, ptsreq->Flags=0x%.8x, " | ||
496 | "ptsreq->pts1=0x%.2x, ptsreq->pts2=0x%.2x, " | ||
497 | "ptsreq->pts3=0x%.2x\n", (unsigned int)ptsreq->protocol, | ||
498 | (unsigned int)ptsreq->flags, ptsreq->pts1, ptsreq->pts2, | ||
499 | ptsreq->pts3); | ||
500 | |||
501 | /* Fill PTS structure */ | ||
502 | dev->pts[0] = 0xff; | ||
503 | dev->pts[1] = 0x00; | ||
504 | tmp = ptsreq->protocol; | ||
505 | while ((tmp = (tmp >> 1)) > 0) | ||
506 | dev->pts[1]++; | ||
507 | dev->proto = dev->pts[1]; /* Set new protocol */ | ||
508 | dev->pts[1] = (0x01 << 4) | (dev->pts[1]); | ||
509 | |||
510 | /* Correct Fi/Di according to CM4000 Fi/Di table */ | ||
511 | DEBUGP(5, dev, "Ta(1) from ATR is 0x%.2x\n", dev->ta1); | ||
512 | /* set Fi/Di according to ATR TA(1) */ | ||
513 | dev->pts[2] = fi_di_table[dev->ta1 & 0x0F][(dev->ta1 >> 4) & 0x0F]; | ||
514 | |||
515 | /* Calculate PCK character */ | ||
516 | dev->pts[3] = dev->pts[0] ^ dev->pts[1] ^ dev->pts[2]; | ||
517 | |||
518 | DEBUGP(5, dev, "pts0=%.2x, pts1=%.2x, pts2=%.2x, pts3=%.2x\n", | ||
519 | dev->pts[0], dev->pts[1], dev->pts[2], dev->pts[3]); | ||
520 | |||
521 | /* check card convention */ | ||
522 | if (test_bit(IS_INVREV, &dev->flags)) | ||
523 | str_invert_revert(dev->pts, 4); | ||
524 | |||
525 | /* reset SM */ | ||
526 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
527 | |||
528 | /* Enable access to the message buffer */ | ||
529 | DEBUGP(5, dev, "Enable access to the messages buffer\n"); | ||
530 | dev->flags1 = 0x20 /* T_Active */ | ||
531 | | (test_bit(IS_INVREV, &dev->flags) ? 0x02 : 0x00) /* inv parity */ | ||
532 | | ((dev->baudv >> 8) & 0x01); /* MSB-baud */ | ||
533 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
534 | |||
535 | DEBUGP(5, dev, "Enable message buffer -> flags1 = 0x%.2x\n", | ||
536 | dev->flags1); | ||
537 | |||
538 | /* write challenge to the buffer */ | ||
539 | DEBUGP(5, dev, "Write challenge to buffer: "); | ||
540 | for (i = 0; i < 4; i++) { | ||
541 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
542 | xoutb(dev->pts[i], REG_BUF_DATA(iobase)); /* buf data */ | ||
543 | #ifdef PCMCIA_DEBUG | ||
544 | if (pc_debug >= 5) | ||
545 | printk("0x%.2x ", dev->pts[i]); | ||
546 | } | ||
547 | if (pc_debug >= 5) | ||
548 | printk("\n"); | ||
549 | #else | ||
550 | } | ||
551 | #endif | ||
552 | |||
553 | /* set number of bytes to write */ | ||
554 | DEBUGP(5, dev, "Set number of bytes to write\n"); | ||
555 | xoutb(0x04, REG_NUM_SEND(iobase)); | ||
556 | |||
557 | /* Trigger CARDMAN CONTROLLER */ | ||
558 | xoutb(0x50, REG_FLAGS0(iobase)); | ||
559 | |||
560 | /* Monitor progress */ | ||
561 | /* wait for xmit done */ | ||
562 | DEBUGP(5, dev, "Waiting for NumRecBytes getting valid\n"); | ||
563 | |||
564 | for (i = 0; i < 100; i++) { | ||
565 | if (inb(REG_FLAGS0(iobase)) & 0x08) { | ||
566 | DEBUGP(5, dev, "NumRecBytes is valid\n"); | ||
567 | break; | ||
568 | } | ||
569 | mdelay(10); | ||
570 | } | ||
571 | if (i == 100) { | ||
572 | DEBUGP(5, dev, "Timeout waiting for NumRecBytes getting " | ||
573 | "valid\n"); | ||
574 | rc = -EIO; | ||
575 | goto exit_setprotocol; | ||
576 | } | ||
577 | |||
578 | DEBUGP(5, dev, "Reading NumRecBytes\n"); | ||
579 | for (i = 0; i < 100; i++) { | ||
580 | io_read_num_rec_bytes(iobase, &num_bytes_read); | ||
581 | if (num_bytes_read >= 4) { | ||
582 | DEBUGP(2, dev, "NumRecBytes = %i\n", num_bytes_read); | ||
583 | break; | ||
584 | } | ||
585 | mdelay(10); | ||
586 | } | ||
587 | |||
588 | /* check whether it is a short PTS reply? */ | ||
589 | if (num_bytes_read == 3) | ||
590 | i = 0; | ||
591 | |||
592 | if (i == 100) { | ||
593 | DEBUGP(5, dev, "Timeout reading num_bytes_read\n"); | ||
594 | rc = -EIO; | ||
595 | goto exit_setprotocol; | ||
596 | } | ||
597 | |||
598 | DEBUGP(5, dev, "Reset the CARDMAN CONTROLLER\n"); | ||
599 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
600 | |||
601 | /* Read PPS reply */ | ||
602 | DEBUGP(5, dev, "Read PPS reply\n"); | ||
603 | for (i = 0; i < num_bytes_read; i++) { | ||
604 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
605 | pts_reply[i] = inb(REG_BUF_DATA(iobase)); | ||
606 | } | ||
607 | |||
608 | #ifdef PCMCIA_DEBUG | ||
609 | DEBUGP(2, dev, "PTSreply: "); | ||
610 | for (i = 0; i < num_bytes_read; i++) { | ||
611 | if (pc_debug >= 5) | ||
612 | printk("0x%.2x ", pts_reply[i]); | ||
613 | } | ||
614 | printk("\n"); | ||
615 | #endif /* PCMCIA_DEBUG */ | ||
616 | |||
617 | DEBUGP(5, dev, "Clear Tactive in Flags1\n"); | ||
618 | xoutb(0x20, REG_FLAGS1(iobase)); | ||
619 | |||
620 | /* Compare ptsreq and ptsreply */ | ||
621 | if ((dev->pts[0] == pts_reply[0]) && | ||
622 | (dev->pts[1] == pts_reply[1]) && | ||
623 | (dev->pts[2] == pts_reply[2]) && (dev->pts[3] == pts_reply[3])) { | ||
624 | /* setcardparameter according to PPS */ | ||
625 | dev->baudv = calc_baudv(dev->pts[2]); | ||
626 | set_cardparameter(dev); | ||
627 | } else if ((dev->pts[0] == pts_reply[0]) && | ||
628 | ((dev->pts[1] & 0xef) == pts_reply[1]) && | ||
629 | ((pts_reply[0] ^ pts_reply[1]) == pts_reply[2])) { | ||
630 | /* short PTS reply, set card parameter to default values */ | ||
631 | dev->baudv = calc_baudv(0x11); | ||
632 | set_cardparameter(dev); | ||
633 | } else | ||
634 | rc = -EIO; | ||
635 | |||
636 | exit_setprotocol: | ||
637 | DEBUGP(3, dev, "<- set_protocol\n"); | ||
638 | return rc; | ||
639 | } | ||
640 | |||
641 | static int io_detect_cm4000(ioaddr_t iobase, struct cm4000_dev *dev) | ||
642 | { | ||
643 | |||
644 | /* note: statemachine is assumed to be reset */ | ||
645 | if (inb(REG_FLAGS0(iobase)) & 8) { | ||
646 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
647 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
648 | return 0; /* detect CMM = 1 -> failure */ | ||
649 | } | ||
650 | /* xoutb(0x40, REG_FLAGS1(iobase)); detectCMM */ | ||
651 | xoutb(dev->flags1 | 0x40, REG_FLAGS1(iobase)); | ||
652 | if ((inb(REG_FLAGS0(iobase)) & 8) == 0) { | ||
653 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
654 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
655 | return 0; /* detect CMM=0 -> failure */ | ||
656 | } | ||
657 | /* clear detectCMM again by restoring original flags1 */ | ||
658 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
659 | return 1; | ||
660 | } | ||
661 | |||
662 | static void terminate_monitor(struct cm4000_dev *dev) | ||
663 | { | ||
664 | |||
665 | /* tell the monitor to stop and wait until | ||
666 | * it terminates. | ||
667 | */ | ||
668 | DEBUGP(3, dev, "-> terminate_monitor\n"); | ||
669 | wait_event_interruptible(dev->devq, | ||
670 | test_and_set_bit(LOCK_MONITOR, | ||
671 | (void *)&dev->flags)); | ||
672 | |||
673 | /* now, LOCK_MONITOR has been set. | ||
674 | * allow a last cycle in the monitor. | ||
675 | * the monitor will indicate that it has | ||
676 | * finished by clearing this bit. | ||
677 | */ | ||
678 | DEBUGP(5, dev, "Now allow last cycle of monitor!\n"); | ||
679 | while (test_bit(LOCK_MONITOR, (void *)&dev->flags)) | ||
680 | msleep(25); | ||
681 | |||
682 | DEBUGP(5, dev, "Delete timer\n"); | ||
683 | del_timer_sync(&dev->timer); | ||
684 | #ifdef PCMCIA_DEBUG | ||
685 | dev->monitor_running = 0; | ||
686 | #endif | ||
687 | |||
688 | DEBUGP(3, dev, "<- terminate_monitor\n"); | ||
689 | } | ||
690 | |||
691 | /* | ||
692 | * monitor the card every 50msec. as a side-effect, retrieve the | ||
693 | * atr once a card is inserted. another side-effect of retrieving the | ||
694 | * atr is that the card will be powered on, so there is no need to | ||
695 | * power on the card explictely from the application: the driver | ||
696 | * is already doing that for you. | ||
697 | */ | ||
698 | |||
699 | static void monitor_card(unsigned long p) | ||
700 | { | ||
701 | struct cm4000_dev *dev = (struct cm4000_dev *) p; | ||
702 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
703 | unsigned short s; | ||
704 | struct ptsreq ptsreq; | ||
705 | int i, atrc; | ||
706 | |||
707 | DEBUGP(7, dev, "-> monitor_card\n"); | ||
708 | |||
709 | /* if someone has set the lock for us: we're done! */ | ||
710 | if (test_and_set_bit(LOCK_MONITOR, &dev->flags)) { | ||
711 | DEBUGP(4, dev, "About to stop monitor\n"); | ||
712 | /* no */ | ||
713 | dev->rlen = | ||
714 | dev->rpos = | ||
715 | dev->atr_csum = dev->atr_len_retry = dev->cwarn = 0; | ||
716 | dev->mstate = M_FETCH_ATR; | ||
717 | clear_bit(LOCK_MONITOR, &dev->flags); | ||
718 | /* close et al. are sleeping on devq, so wake it */ | ||
719 | wake_up_interruptible(&dev->devq); | ||
720 | DEBUGP(2, dev, "<- monitor_card (we are done now)\n"); | ||
721 | return; | ||
722 | } | ||
723 | |||
724 | /* try to lock io: if it is already locked, just add another timer */ | ||
725 | if (test_and_set_bit(LOCK_IO, (void *)&dev->flags)) { | ||
726 | DEBUGP(4, dev, "Couldn't get IO lock\n"); | ||
727 | goto return_with_timer; | ||
728 | } | ||
729 | |||
730 | /* is a card/a reader inserted at all ? */ | ||
731 | dev->flags0 = xinb(REG_FLAGS0(iobase)); | ||
732 | DEBUGP(7, dev, "dev->flags0 = 0x%2x\n", dev->flags0); | ||
733 | DEBUGP(7, dev, "smartcard present: %s\n", | ||
734 | dev->flags0 & 1 ? "yes" : "no"); | ||
735 | DEBUGP(7, dev, "cardman present: %s\n", | ||
736 | dev->flags0 == 0xff ? "no" : "yes"); | ||
737 | |||
738 | if ((dev->flags0 & 1) == 0 /* no smartcard inserted */ | ||
739 | || dev->flags0 == 0xff) { /* no cardman inserted */ | ||
740 | /* no */ | ||
741 | dev->rlen = | ||
742 | dev->rpos = | ||
743 | dev->atr_csum = dev->atr_len_retry = dev->cwarn = 0; | ||
744 | dev->mstate = M_FETCH_ATR; | ||
745 | |||
746 | dev->flags &= 0x000000ff; /* only keep IO and MONITOR locks */ | ||
747 | |||
748 | if (dev->flags0 == 0xff) { | ||
749 | DEBUGP(4, dev, "set IS_CMM_ABSENT bit\n"); | ||
750 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
751 | } else if (test_bit(IS_CMM_ABSENT, &dev->flags)) { | ||
752 | DEBUGP(4, dev, "clear IS_CMM_ABSENT bit " | ||
753 | "(card is removed)\n"); | ||
754 | clear_bit(IS_CMM_ABSENT, &dev->flags); | ||
755 | } | ||
756 | |||
757 | goto release_io; | ||
758 | } else if ((dev->flags0 & 1) && test_bit(IS_CMM_ABSENT, &dev->flags)) { | ||
759 | /* cardman and card present but cardman was absent before | ||
760 | * (after suspend with inserted card) */ | ||
761 | DEBUGP(4, dev, "clear IS_CMM_ABSENT bit (card is inserted)\n"); | ||
762 | clear_bit(IS_CMM_ABSENT, &dev->flags); | ||
763 | } | ||
764 | |||
765 | if (test_bit(IS_ATR_VALID, &dev->flags) == 1) { | ||
766 | DEBUGP(7, dev, "believe ATR is already valid (do nothing)\n"); | ||
767 | goto release_io; | ||
768 | } | ||
769 | |||
770 | switch (dev->mstate) { | ||
771 | unsigned char flags0; | ||
772 | case M_CARDOFF: | ||
773 | DEBUGP(4, dev, "M_CARDOFF\n"); | ||
774 | flags0 = inb(REG_FLAGS0(iobase)); | ||
775 | if (flags0 & 0x02) { | ||
776 | /* wait until Flags0 indicate power is off */ | ||
777 | dev->mdelay = T_10MSEC; | ||
778 | } else { | ||
779 | /* Flags0 indicate power off and no card inserted now; | ||
780 | * Reset CARDMAN CONTROLLER */ | ||
781 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
782 | |||
783 | /* prepare for fetching ATR again: after card off ATR | ||
784 | * is read again automatically */ | ||
785 | dev->rlen = | ||
786 | dev->rpos = | ||
787 | dev->atr_csum = | ||
788 | dev->atr_len_retry = dev->cwarn = 0; | ||
789 | dev->mstate = M_FETCH_ATR; | ||
790 | |||
791 | /* minimal gap between CARDOFF and read ATR is 50msec */ | ||
792 | dev->mdelay = T_50MSEC; | ||
793 | } | ||
794 | break; | ||
795 | case M_FETCH_ATR: | ||
796 | DEBUGP(4, dev, "M_FETCH_ATR\n"); | ||
797 | xoutb(0x80, REG_FLAGS0(iobase)); | ||
798 | DEBUGP(4, dev, "Reset BAUDV to 9600\n"); | ||
799 | dev->baudv = 0x173; /* 9600 */ | ||
800 | xoutb(0x02, REG_STOPBITS(iobase)); /* stopbits=2 */ | ||
801 | xoutb(0x73, REG_BAUDRATE(iobase)); /* baud value */ | ||
802 | xoutb(0x21, REG_FLAGS1(iobase)); /* T_Active=1, baud | ||
803 | value */ | ||
804 | /* warm start vs. power on: */ | ||
805 | xoutb(dev->flags0 & 2 ? 0x46 : 0x44, REG_FLAGS0(iobase)); | ||
806 | dev->mdelay = T_40MSEC; | ||
807 | dev->mstate = M_TIMEOUT_WAIT; | ||
808 | break; | ||
809 | case M_TIMEOUT_WAIT: | ||
810 | DEBUGP(4, dev, "M_TIMEOUT_WAIT\n"); | ||
811 | /* numRecBytes */ | ||
812 | io_read_num_rec_bytes(iobase, &dev->atr_len); | ||
813 | dev->mdelay = T_10MSEC; | ||
814 | dev->mstate = M_READ_ATR_LEN; | ||
815 | break; | ||
816 | case M_READ_ATR_LEN: | ||
817 | DEBUGP(4, dev, "M_READ_ATR_LEN\n"); | ||
818 | /* infinite loop possible, since there is no timeout */ | ||
819 | |||
820 | #define MAX_ATR_LEN_RETRY 100 | ||
821 | |||
822 | if (dev->atr_len == io_read_num_rec_bytes(iobase, &s)) { | ||
823 | if (dev->atr_len_retry++ >= MAX_ATR_LEN_RETRY) { /* + XX msec */ | ||
824 | dev->mdelay = T_10MSEC; | ||
825 | dev->mstate = M_READ_ATR; | ||
826 | } | ||
827 | } else { | ||
828 | dev->atr_len = s; | ||
829 | dev->atr_len_retry = 0; /* set new timeout */ | ||
830 | } | ||
831 | |||
832 | DEBUGP(4, dev, "Current ATR_LEN = %i\n", dev->atr_len); | ||
833 | break; | ||
834 | case M_READ_ATR: | ||
835 | DEBUGP(4, dev, "M_READ_ATR\n"); | ||
836 | xoutb(0x80, REG_FLAGS0(iobase)); /* reset SM */ | ||
837 | for (i = 0; i < dev->atr_len; i++) { | ||
838 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
839 | dev->atr[i] = inb(REG_BUF_DATA(iobase)); | ||
840 | } | ||
841 | /* Deactivate T_Active flags */ | ||
842 | DEBUGP(4, dev, "Deactivate T_Active flags\n"); | ||
843 | dev->flags1 = 0x01; | ||
844 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
845 | |||
846 | /* atr is present (which doesnt mean it's valid) */ | ||
847 | set_bit(IS_ATR_PRESENT, &dev->flags); | ||
848 | if (dev->atr[0] == 0x03) | ||
849 | str_invert_revert(dev->atr, dev->atr_len); | ||
850 | atrc = parse_atr(dev); | ||
851 | if (atrc == 0) { /* atr invalid */ | ||
852 | dev->mdelay = 0; | ||
853 | dev->mstate = M_BAD_CARD; | ||
854 | } else { | ||
855 | dev->mdelay = T_50MSEC; | ||
856 | dev->mstate = M_ATR_PRESENT; | ||
857 | set_bit(IS_ATR_VALID, &dev->flags); | ||
858 | } | ||
859 | |||
860 | if (test_bit(IS_ATR_VALID, &dev->flags) == 1) { | ||
861 | DEBUGP(4, dev, "monitor_card: ATR valid\n"); | ||
862 | /* if ta1 == 0x11, no PPS necessary (default values) */ | ||
863 | /* do not do PPS with multi protocol cards */ | ||
864 | if ((test_bit(IS_AUTOPPS_ACT, &dev->flags) == 0) && | ||
865 | (dev->ta1 != 0x11) && | ||
866 | !(test_bit(IS_ANY_T0, &dev->flags) && | ||
867 | test_bit(IS_ANY_T1, &dev->flags))) { | ||
868 | DEBUGP(4, dev, "Perform AUTOPPS\n"); | ||
869 | set_bit(IS_AUTOPPS_ACT, &dev->flags); | ||
870 | ptsreq.protocol = ptsreq.protocol = | ||
871 | (0x01 << dev->proto); | ||
872 | ptsreq.flags = 0x01; | ||
873 | ptsreq.pts1 = 0x00; | ||
874 | ptsreq.pts2 = 0x00; | ||
875 | ptsreq.pts3 = 0x00; | ||
876 | if (set_protocol(dev, &ptsreq) == 0) { | ||
877 | DEBUGP(4, dev, "AUTOPPS ret SUCC\n"); | ||
878 | clear_bit(IS_AUTOPPS_ACT, &dev->flags); | ||
879 | wake_up_interruptible(&dev->atrq); | ||
880 | } else { | ||
881 | DEBUGP(4, dev, "AUTOPPS failed: " | ||
882 | "repower using defaults\n"); | ||
883 | /* prepare for repowering */ | ||
884 | clear_bit(IS_ATR_PRESENT, &dev->flags); | ||
885 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
886 | dev->rlen = | ||
887 | dev->rpos = | ||
888 | dev->atr_csum = | ||
889 | dev->atr_len_retry = dev->cwarn = 0; | ||
890 | dev->mstate = M_FETCH_ATR; | ||
891 | |||
892 | dev->mdelay = T_50MSEC; | ||
893 | } | ||
894 | } else { | ||
895 | /* for cards which use slightly different | ||
896 | * params (extra guard time) */ | ||
897 | set_cardparameter(dev); | ||
898 | if (test_bit(IS_AUTOPPS_ACT, &dev->flags) == 1) | ||
899 | DEBUGP(4, dev, "AUTOPPS already active " | ||
900 | "2nd try:use default values\n"); | ||
901 | if (dev->ta1 == 0x11) | ||
902 | DEBUGP(4, dev, "No AUTOPPS necessary " | ||
903 | "TA(1)==0x11\n"); | ||
904 | if (test_bit(IS_ANY_T0, &dev->flags) | ||
905 | && test_bit(IS_ANY_T1, &dev->flags)) | ||
906 | DEBUGP(4, dev, "Do NOT perform AUTOPPS " | ||
907 | "with multiprotocol cards\n"); | ||
908 | clear_bit(IS_AUTOPPS_ACT, &dev->flags); | ||
909 | wake_up_interruptible(&dev->atrq); | ||
910 | } | ||
911 | } else { | ||
912 | DEBUGP(4, dev, "ATR invalid\n"); | ||
913 | wake_up_interruptible(&dev->atrq); | ||
914 | } | ||
915 | break; | ||
916 | case M_BAD_CARD: | ||
917 | DEBUGP(4, dev, "M_BAD_CARD\n"); | ||
918 | /* slow down warning, but prompt immediately after insertion */ | ||
919 | if (dev->cwarn == 0 || dev->cwarn == 10) { | ||
920 | set_bit(IS_BAD_CARD, &dev->flags); | ||
921 | printk(KERN_WARNING MODULE_NAME ": device %s: ", | ||
922 | dev->node.dev_name); | ||
923 | if (test_bit(IS_BAD_CSUM, &dev->flags)) { | ||
924 | DEBUGP(4, dev, "ATR checksum (0x%.2x, should " | ||
925 | "be zero) failed\n", dev->atr_csum); | ||
926 | } | ||
927 | #ifdef PCMCIA_DEBUG | ||
928 | else if (test_bit(IS_BAD_LENGTH, &dev->flags)) { | ||
929 | DEBUGP(4, dev, "ATR length error\n"); | ||
930 | } else { | ||
931 | DEBUGP(4, dev, "card damaged or wrong way " | ||
932 | "inserted\n"); | ||
933 | } | ||
934 | #endif | ||
935 | dev->cwarn = 0; | ||
936 | wake_up_interruptible(&dev->atrq); /* wake open */ | ||
937 | } | ||
938 | dev->cwarn++; | ||
939 | dev->mdelay = T_100MSEC; | ||
940 | dev->mstate = M_FETCH_ATR; | ||
941 | break; | ||
942 | default: | ||
943 | DEBUGP(7, dev, "Unknown action\n"); | ||
944 | break; /* nothing */ | ||
945 | } | ||
946 | |||
947 | release_io: | ||
948 | DEBUGP(7, dev, "release_io\n"); | ||
949 | clear_bit(LOCK_IO, &dev->flags); | ||
950 | wake_up_interruptible(&dev->ioq); /* whoever needs IO */ | ||
951 | |||
952 | return_with_timer: | ||
953 | DEBUGP(7, dev, "<- monitor_card (returns with timer)\n"); | ||
954 | dev->timer.expires = jiffies + dev->mdelay; | ||
955 | add_timer(&dev->timer); | ||
956 | clear_bit(LOCK_MONITOR, &dev->flags); | ||
957 | } | ||
958 | |||
959 | /* Interface to userland (file_operations) */ | ||
960 | |||
961 | static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, | ||
962 | loff_t *ppos) | ||
963 | { | ||
964 | struct cm4000_dev *dev = filp->private_data; | ||
965 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
966 | ssize_t rc; | ||
967 | int i, j, k; | ||
968 | |||
969 | DEBUGP(2, dev, "-> cmm_read(%s,%d)\n", current->comm, current->pid); | ||
970 | |||
971 | if (count == 0) /* according to manpage */ | ||
972 | return 0; | ||
973 | |||
974 | if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */ | ||
975 | test_bit(IS_CMM_ABSENT, &dev->flags)) | ||
976 | return -ENODEV; | ||
977 | |||
978 | if (test_bit(IS_BAD_CSUM, &dev->flags)) | ||
979 | return -EIO; | ||
980 | |||
981 | /* also see the note about this in cmm_write */ | ||
982 | if (wait_event_interruptible | ||
983 | (dev->atrq, | ||
984 | ((filp->f_flags & O_NONBLOCK) | ||
985 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) != 0)))) { | ||
986 | if (filp->f_flags & O_NONBLOCK) | ||
987 | return -EAGAIN; | ||
988 | return -ERESTARTSYS; | ||
989 | } | ||
990 | |||
991 | if (test_bit(IS_ATR_VALID, &dev->flags) == 0) | ||
992 | return -EIO; | ||
993 | |||
994 | /* this one implements blocking IO */ | ||
995 | if (wait_event_interruptible | ||
996 | (dev->readq, | ||
997 | ((filp->f_flags & O_NONBLOCK) || (dev->rpos < dev->rlen)))) { | ||
998 | if (filp->f_flags & O_NONBLOCK) | ||
999 | return -EAGAIN; | ||
1000 | return -ERESTARTSYS; | ||
1001 | } | ||
1002 | |||
1003 | /* lock io */ | ||
1004 | if (wait_event_interruptible | ||
1005 | (dev->ioq, | ||
1006 | ((filp->f_flags & O_NONBLOCK) | ||
1007 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) == 0)))) { | ||
1008 | if (filp->f_flags & O_NONBLOCK) | ||
1009 | return -EAGAIN; | ||
1010 | return -ERESTARTSYS; | ||
1011 | } | ||
1012 | |||
1013 | rc = 0; | ||
1014 | dev->flags0 = inb(REG_FLAGS0(iobase)); | ||
1015 | if ((dev->flags0 & 1) == 0 /* no smartcard inserted */ | ||
1016 | || dev->flags0 == 0xff) { /* no cardman inserted */ | ||
1017 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1018 | if (dev->flags0 & 1) { | ||
1019 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
1020 | rc = -ENODEV; | ||
1021 | } | ||
1022 | rc = -EIO; | ||
1023 | goto release_io; | ||
1024 | } | ||
1025 | |||
1026 | DEBUGP(4, dev, "begin read answer\n"); | ||
1027 | j = min(count, (size_t)(dev->rlen - dev->rpos)); | ||
1028 | k = dev->rpos; | ||
1029 | if (k + j > 255) | ||
1030 | j = 256 - k; | ||
1031 | DEBUGP(4, dev, "read1 j=%d\n", j); | ||
1032 | for (i = 0; i < j; i++) { | ||
1033 | xoutb(k++, REG_BUF_ADDR(iobase)); | ||
1034 | dev->rbuf[i] = xinb(REG_BUF_DATA(iobase)); | ||
1035 | } | ||
1036 | j = min(count, (size_t)(dev->rlen - dev->rpos)); | ||
1037 | if (k + j > 255) { | ||
1038 | DEBUGP(4, dev, "read2 j=%d\n", j); | ||
1039 | dev->flags1 |= 0x10; /* MSB buf addr set */ | ||
1040 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1041 | for (; i < j; i++) { | ||
1042 | xoutb(k++, REG_BUF_ADDR(iobase)); | ||
1043 | dev->rbuf[i] = xinb(REG_BUF_DATA(iobase)); | ||
1044 | } | ||
1045 | } | ||
1046 | |||
1047 | if (dev->proto == 0 && count > dev->rlen - dev->rpos) { | ||
1048 | DEBUGP(4, dev, "T=0 and count > buffer\n"); | ||
1049 | dev->rbuf[i] = dev->rbuf[i - 1]; | ||
1050 | dev->rbuf[i - 1] = dev->procbyte; | ||
1051 | j++; | ||
1052 | } | ||
1053 | count = j; | ||
1054 | |||
1055 | dev->rpos = dev->rlen + 1; | ||
1056 | |||
1057 | /* Clear T1Active */ | ||
1058 | DEBUGP(4, dev, "Clear T1Active\n"); | ||
1059 | dev->flags1 &= 0xdf; | ||
1060 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1061 | |||
1062 | xoutb(0, REG_FLAGS1(iobase)); /* clear detectCMM */ | ||
1063 | /* last check before exit */ | ||
1064 | if (!io_detect_cm4000(iobase, dev)) | ||
1065 | count = -ENODEV; | ||
1066 | |||
1067 | if (test_bit(IS_INVREV, &dev->flags) && count > 0) | ||
1068 | str_invert_revert(dev->rbuf, count); | ||
1069 | |||
1070 | if (copy_to_user(buf, dev->rbuf, count)) | ||
1071 | return -EFAULT; | ||
1072 | |||
1073 | release_io: | ||
1074 | clear_bit(LOCK_IO, &dev->flags); | ||
1075 | wake_up_interruptible(&dev->ioq); | ||
1076 | |||
1077 | DEBUGP(2, dev, "<- cmm_read returns: rc = %Zi\n", | ||
1078 | (rc < 0 ? rc : count)); | ||
1079 | return rc < 0 ? rc : count; | ||
1080 | } | ||
1081 | |||
1082 | static ssize_t cmm_write(struct file *filp, const char __user *buf, | ||
1083 | size_t count, loff_t *ppos) | ||
1084 | { | ||
1085 | struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data; | ||
1086 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
1087 | unsigned short s; | ||
1088 | unsigned char tmp; | ||
1089 | unsigned char infolen; | ||
1090 | unsigned char sendT0; | ||
1091 | unsigned short nsend; | ||
1092 | unsigned short nr; | ||
1093 | ssize_t rc; | ||
1094 | int i; | ||
1095 | |||
1096 | DEBUGP(2, dev, "-> cmm_write(%s,%d)\n", current->comm, current->pid); | ||
1097 | |||
1098 | if (count == 0) /* according to manpage */ | ||
1099 | return 0; | ||
1100 | |||
1101 | if (dev->proto == 0 && count < 4) { | ||
1102 | /* T0 must have at least 4 bytes */ | ||
1103 | DEBUGP(4, dev, "T0 short write\n"); | ||
1104 | return -EIO; | ||
1105 | } | ||
1106 | |||
1107 | nr = count & 0x1ff; /* max bytes to write */ | ||
1108 | |||
1109 | sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0; | ||
1110 | |||
1111 | if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */ | ||
1112 | test_bit(IS_CMM_ABSENT, &dev->flags)) | ||
1113 | return -ENODEV; | ||
1114 | |||
1115 | if (test_bit(IS_BAD_CSUM, &dev->flags)) { | ||
1116 | DEBUGP(4, dev, "bad csum\n"); | ||
1117 | return -EIO; | ||
1118 | } | ||
1119 | |||
1120 | /* | ||
1121 | * wait for atr to become valid. | ||
1122 | * note: it is important to lock this code. if we dont, the monitor | ||
1123 | * could be run between test_bit and the the call the sleep on the | ||
1124 | * atr-queue. if *then* the monitor detects atr valid, it will wake up | ||
1125 | * any process on the atr-queue, *but* since we have been interrupted, | ||
1126 | * we do not yet sleep on this queue. this would result in a missed | ||
1127 | * wake_up and the calling process would sleep forever (until | ||
1128 | * interrupted). also, do *not* restore_flags before sleep_on, because | ||
1129 | * this could result in the same situation! | ||
1130 | */ | ||
1131 | if (wait_event_interruptible | ||
1132 | (dev->atrq, | ||
1133 | ((filp->f_flags & O_NONBLOCK) | ||
1134 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) != 0)))) { | ||
1135 | if (filp->f_flags & O_NONBLOCK) | ||
1136 | return -EAGAIN; | ||
1137 | return -ERESTARTSYS; | ||
1138 | } | ||
1139 | |||
1140 | if (test_bit(IS_ATR_VALID, &dev->flags) == 0) { /* invalid atr */ | ||
1141 | DEBUGP(4, dev, "invalid ATR\n"); | ||
1142 | return -EIO; | ||
1143 | } | ||
1144 | |||
1145 | /* lock io */ | ||
1146 | if (wait_event_interruptible | ||
1147 | (dev->ioq, | ||
1148 | ((filp->f_flags & O_NONBLOCK) | ||
1149 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) == 0)))) { | ||
1150 | if (filp->f_flags & O_NONBLOCK) | ||
1151 | return -EAGAIN; | ||
1152 | return -ERESTARTSYS; | ||
1153 | } | ||
1154 | |||
1155 | if (copy_from_user(dev->sbuf, buf, ((count > 512) ? 512 : count))) | ||
1156 | return -EFAULT; | ||
1157 | |||
1158 | rc = 0; | ||
1159 | dev->flags0 = inb(REG_FLAGS0(iobase)); | ||
1160 | if ((dev->flags0 & 1) == 0 /* no smartcard inserted */ | ||
1161 | || dev->flags0 == 0xff) { /* no cardman inserted */ | ||
1162 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1163 | if (dev->flags0 & 1) { | ||
1164 | set_bit(IS_CMM_ABSENT, &dev->flags); | ||
1165 | rc = -ENODEV; | ||
1166 | } else { | ||
1167 | DEBUGP(4, dev, "IO error\n"); | ||
1168 | rc = -EIO; | ||
1169 | } | ||
1170 | goto release_io; | ||
1171 | } | ||
1172 | |||
1173 | xoutb(0x80, REG_FLAGS0(iobase)); /* reset SM */ | ||
1174 | |||
1175 | if (!io_detect_cm4000(iobase, dev)) { | ||
1176 | rc = -ENODEV; | ||
1177 | goto release_io; | ||
1178 | } | ||
1179 | |||
1180 | /* reflect T=0 send/read mode in flags1 */ | ||
1181 | dev->flags1 |= (sendT0); | ||
1182 | |||
1183 | set_cardparameter(dev); | ||
1184 | |||
1185 | /* dummy read, reset flag procedure received */ | ||
1186 | tmp = inb(REG_FLAGS1(iobase)); | ||
1187 | |||
1188 | dev->flags1 = 0x20 /* T_Active */ | ||
1189 | | (sendT0) | ||
1190 | | (test_bit(IS_INVREV, &dev->flags) ? 2 : 0)/* inverse parity */ | ||
1191 | | (((dev->baudv - 1) & 0x0100) >> 8); /* MSB-Baud */ | ||
1192 | DEBUGP(1, dev, "set dev->flags1 = 0x%.2x\n", dev->flags1); | ||
1193 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1194 | |||
1195 | /* xmit data */ | ||
1196 | DEBUGP(4, dev, "Xmit data\n"); | ||
1197 | for (i = 0; i < nr; i++) { | ||
1198 | if (i >= 256) { | ||
1199 | dev->flags1 = 0x20 /* T_Active */ | ||
1200 | | (sendT0) /* SendT0 */ | ||
1201 | /* inverse parity: */ | ||
1202 | | (test_bit(IS_INVREV, &dev->flags) ? 2 : 0) | ||
1203 | | (((dev->baudv - 1) & 0x0100) >> 8) /* MSB-Baud */ | ||
1204 | | 0x10; /* set address high */ | ||
1205 | DEBUGP(4, dev, "dev->flags = 0x%.2x - set address " | ||
1206 | "high\n", dev->flags1); | ||
1207 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1208 | } | ||
1209 | if (test_bit(IS_INVREV, &dev->flags)) { | ||
1210 | DEBUGP(4, dev, "Apply inverse convention for 0x%.2x " | ||
1211 | "-> 0x%.2x\n", (unsigned char)dev->sbuf[i], | ||
1212 | invert_revert(dev->sbuf[i])); | ||
1213 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
1214 | xoutb(invert_revert(dev->sbuf[i]), | ||
1215 | REG_BUF_DATA(iobase)); | ||
1216 | } else { | ||
1217 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
1218 | xoutb(dev->sbuf[i], REG_BUF_DATA(iobase)); | ||
1219 | } | ||
1220 | } | ||
1221 | DEBUGP(4, dev, "Xmit done\n"); | ||
1222 | |||
1223 | if (dev->proto == 0) { | ||
1224 | /* T=0 proto: 0 byte reply */ | ||
1225 | if (nr == 4) { | ||
1226 | DEBUGP(4, dev, "T=0 assumes 0 byte reply\n"); | ||
1227 | xoutb(i, REG_BUF_ADDR(iobase)); | ||
1228 | if (test_bit(IS_INVREV, &dev->flags)) | ||
1229 | xoutb(0xff, REG_BUF_DATA(iobase)); | ||
1230 | else | ||
1231 | xoutb(0x00, REG_BUF_DATA(iobase)); | ||
1232 | } | ||
1233 | |||
1234 | /* numSendBytes */ | ||
1235 | if (sendT0) | ||
1236 | nsend = nr; | ||
1237 | else { | ||
1238 | if (nr == 4) | ||
1239 | nsend = 5; | ||
1240 | else { | ||
1241 | nsend = 5 + (unsigned char)dev->sbuf[4]; | ||
1242 | if (dev->sbuf[4] == 0) | ||
1243 | nsend += 0x100; | ||
1244 | } | ||
1245 | } | ||
1246 | } else | ||
1247 | nsend = nr; | ||
1248 | |||
1249 | /* T0: output procedure byte */ | ||
1250 | if (test_bit(IS_INVREV, &dev->flags)) { | ||
1251 | DEBUGP(4, dev, "T=0 set Procedure byte (inverse-reverse) " | ||
1252 | "0x%.2x\n", invert_revert(dev->sbuf[1])); | ||
1253 | xoutb(invert_revert(dev->sbuf[1]), REG_NUM_BYTES(iobase)); | ||
1254 | } else { | ||
1255 | DEBUGP(4, dev, "T=0 set Procedure byte 0x%.2x\n", dev->sbuf[1]); | ||
1256 | xoutb(dev->sbuf[1], REG_NUM_BYTES(iobase)); | ||
1257 | } | ||
1258 | |||
1259 | DEBUGP(1, dev, "set NumSendBytes = 0x%.2x\n", | ||
1260 | (unsigned char)(nsend & 0xff)); | ||
1261 | xoutb((unsigned char)(nsend & 0xff), REG_NUM_SEND(iobase)); | ||
1262 | |||
1263 | DEBUGP(1, dev, "Trigger CARDMAN CONTROLLER (0x%.2x)\n", | ||
1264 | 0x40 /* SM_Active */ | ||
1265 | | (dev->flags0 & 2 ? 0 : 4) /* power on if needed */ | ||
1266 | |(dev->proto ? 0x10 : 0x08) /* T=1/T=0 */ | ||
1267 | |(nsend & 0x100) >> 8 /* MSB numSendBytes */ ); | ||
1268 | xoutb(0x40 /* SM_Active */ | ||
1269 | | (dev->flags0 & 2 ? 0 : 4) /* power on if needed */ | ||
1270 | |(dev->proto ? 0x10 : 0x08) /* T=1/T=0 */ | ||
1271 | |(nsend & 0x100) >> 8, /* MSB numSendBytes */ | ||
1272 | REG_FLAGS0(iobase)); | ||
1273 | |||
1274 | /* wait for xmit done */ | ||
1275 | if (dev->proto == 1) { | ||
1276 | DEBUGP(4, dev, "Wait for xmit done\n"); | ||
1277 | for (i = 0; i < 1000; i++) { | ||
1278 | if (inb(REG_FLAGS0(iobase)) & 0x08) | ||
1279 | break; | ||
1280 | msleep_interruptible(10); | ||
1281 | } | ||
1282 | if (i == 1000) { | ||
1283 | DEBUGP(4, dev, "timeout waiting for xmit done\n"); | ||
1284 | rc = -EIO; | ||
1285 | goto release_io; | ||
1286 | } | ||
1287 | } | ||
1288 | |||
1289 | /* T=1: wait for infoLen */ | ||
1290 | |||
1291 | infolen = 0; | ||
1292 | if (dev->proto) { | ||
1293 | /* wait until infoLen is valid */ | ||
1294 | for (i = 0; i < 6000; i++) { /* max waiting time of 1 min */ | ||
1295 | io_read_num_rec_bytes(iobase, &s); | ||
1296 | if (s >= 3) { | ||
1297 | infolen = inb(REG_FLAGS1(iobase)); | ||
1298 | DEBUGP(4, dev, "infolen=%d\n", infolen); | ||
1299 | break; | ||
1300 | } | ||
1301 | msleep_interruptible(10); | ||
1302 | } | ||
1303 | if (i == 6000) { | ||
1304 | DEBUGP(4, dev, "timeout waiting for infoLen\n"); | ||
1305 | rc = -EIO; | ||
1306 | goto release_io; | ||
1307 | } | ||
1308 | } else | ||
1309 | clear_bit(IS_PROCBYTE_PRESENT, &dev->flags); | ||
1310 | |||
1311 | /* numRecBytes | bit9 of numRecytes */ | ||
1312 | io_read_num_rec_bytes(iobase, &dev->rlen); | ||
1313 | for (i = 0; i < 600; i++) { /* max waiting time of 2 sec */ | ||
1314 | if (dev->proto) { | ||
1315 | if (dev->rlen >= infolen + 4) | ||
1316 | break; | ||
1317 | } | ||
1318 | msleep_interruptible(10); | ||
1319 | /* numRecBytes | bit9 of numRecytes */ | ||
1320 | io_read_num_rec_bytes(iobase, &s); | ||
1321 | if (s > dev->rlen) { | ||
1322 | DEBUGP(1, dev, "NumRecBytes inc (reset timeout)\n"); | ||
1323 | i = 0; /* reset timeout */ | ||
1324 | dev->rlen = s; | ||
1325 | } | ||
1326 | /* T=0: we are done when numRecBytes doesn't | ||
1327 | * increment any more and NoProcedureByte | ||
1328 | * is set and numRecBytes == bytes sent + 6 | ||
1329 | * (header bytes + data + 1 for sw2) | ||
1330 | * except when the card replies an error | ||
1331 | * which means, no data will be sent back. | ||
1332 | */ | ||
1333 | else if (dev->proto == 0) { | ||
1334 | if ((inb(REG_BUF_ADDR(iobase)) & 0x80)) { | ||
1335 | /* no procedure byte received since last read */ | ||
1336 | DEBUGP(1, dev, "NoProcedure byte set\n"); | ||
1337 | /* i=0; */ | ||
1338 | } else { | ||
1339 | /* procedure byte received since last read */ | ||
1340 | DEBUGP(1, dev, "NoProcedure byte unset " | ||
1341 | "(reset timeout)\n"); | ||
1342 | dev->procbyte = inb(REG_FLAGS1(iobase)); | ||
1343 | DEBUGP(1, dev, "Read procedure byte 0x%.2x\n", | ||
1344 | dev->procbyte); | ||
1345 | i = 0; /* resettimeout */ | ||
1346 | } | ||
1347 | if (inb(REG_FLAGS0(iobase)) & 0x08) { | ||
1348 | DEBUGP(1, dev, "T0Done flag (read reply)\n"); | ||
1349 | break; | ||
1350 | } | ||
1351 | } | ||
1352 | if (dev->proto) | ||
1353 | infolen = inb(REG_FLAGS1(iobase)); | ||
1354 | } | ||
1355 | if (i == 600) { | ||
1356 | DEBUGP(1, dev, "timeout waiting for numRecBytes\n"); | ||
1357 | rc = -EIO; | ||
1358 | goto release_io; | ||
1359 | } else { | ||
1360 | if (dev->proto == 0) { | ||
1361 | DEBUGP(1, dev, "Wait for T0Done bit to be set\n"); | ||
1362 | for (i = 0; i < 1000; i++) { | ||
1363 | if (inb(REG_FLAGS0(iobase)) & 0x08) | ||
1364 | break; | ||
1365 | msleep_interruptible(10); | ||
1366 | } | ||
1367 | if (i == 1000) { | ||
1368 | DEBUGP(1, dev, "timeout waiting for T0Done\n"); | ||
1369 | rc = -EIO; | ||
1370 | goto release_io; | ||
1371 | } | ||
1372 | |||
1373 | dev->procbyte = inb(REG_FLAGS1(iobase)); | ||
1374 | DEBUGP(4, dev, "Read procedure byte 0x%.2x\n", | ||
1375 | dev->procbyte); | ||
1376 | |||
1377 | io_read_num_rec_bytes(iobase, &dev->rlen); | ||
1378 | DEBUGP(4, dev, "Read NumRecBytes = %i\n", dev->rlen); | ||
1379 | |||
1380 | } | ||
1381 | } | ||
1382 | /* T=1: read offset=zero, T=0: read offset=after challenge */ | ||
1383 | dev->rpos = dev->proto ? 0 : nr == 4 ? 5 : nr > dev->rlen ? 5 : nr; | ||
1384 | DEBUGP(4, dev, "dev->rlen = %i, dev->rpos = %i, nr = %i\n", | ||
1385 | dev->rlen, dev->rpos, nr); | ||
1386 | |||
1387 | release_io: | ||
1388 | DEBUGP(4, dev, "Reset SM\n"); | ||
1389 | xoutb(0x80, REG_FLAGS0(iobase)); /* reset SM */ | ||
1390 | |||
1391 | if (rc < 0) { | ||
1392 | DEBUGP(4, dev, "Write failed but clear T_Active\n"); | ||
1393 | dev->flags1 &= 0xdf; | ||
1394 | xoutb(dev->flags1, REG_FLAGS1(iobase)); | ||
1395 | } | ||
1396 | |||
1397 | clear_bit(LOCK_IO, &dev->flags); | ||
1398 | wake_up_interruptible(&dev->ioq); | ||
1399 | wake_up_interruptible(&dev->readq); /* tell read we have data */ | ||
1400 | |||
1401 | /* ITSEC E2: clear write buffer */ | ||
1402 | memset((char *)dev->sbuf, 0, 512); | ||
1403 | |||
1404 | /* return error or actually written bytes */ | ||
1405 | DEBUGP(2, dev, "<- cmm_write\n"); | ||
1406 | return rc < 0 ? rc : nr; | ||
1407 | } | ||
1408 | |||
1409 | static void start_monitor(struct cm4000_dev *dev) | ||
1410 | { | ||
1411 | DEBUGP(3, dev, "-> start_monitor\n"); | ||
1412 | if (!dev->monitor_running) { | ||
1413 | DEBUGP(5, dev, "create, init and add timer\n"); | ||
1414 | init_timer(&dev->timer); | ||
1415 | dev->monitor_running = 1; | ||
1416 | dev->timer.expires = jiffies; | ||
1417 | dev->timer.data = (unsigned long) dev; | ||
1418 | dev->timer.function = monitor_card; | ||
1419 | add_timer(&dev->timer); | ||
1420 | } else | ||
1421 | DEBUGP(5, dev, "monitor already running\n"); | ||
1422 | DEBUGP(3, dev, "<- start_monitor\n"); | ||
1423 | } | ||
1424 | |||
1425 | static void stop_monitor(struct cm4000_dev *dev) | ||
1426 | { | ||
1427 | DEBUGP(3, dev, "-> stop_monitor\n"); | ||
1428 | if (dev->monitor_running) { | ||
1429 | DEBUGP(5, dev, "stopping monitor\n"); | ||
1430 | terminate_monitor(dev); | ||
1431 | /* reset monitor SM */ | ||
1432 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1433 | clear_bit(IS_ATR_PRESENT, &dev->flags); | ||
1434 | } else | ||
1435 | DEBUGP(5, dev, "monitor already stopped\n"); | ||
1436 | DEBUGP(3, dev, "<- stop_monitor\n"); | ||
1437 | } | ||
1438 | |||
1439 | static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | ||
1440 | unsigned long arg) | ||
1441 | { | ||
1442 | struct cm4000_dev *dev = filp->private_data; | ||
1443 | ioaddr_t iobase = dev->link.io.BasePort1; | ||
1444 | dev_link_t *link; | ||
1445 | int size; | ||
1446 | int rc; | ||
1447 | #ifdef PCMCIA_DEBUG | ||
1448 | char *ioctl_names[CM_IOC_MAXNR + 1] = { | ||
1449 | [_IOC_NR(CM_IOCGSTATUS)] "CM_IOCGSTATUS", | ||
1450 | [_IOC_NR(CM_IOCGATR)] "CM_IOCGATR", | ||
1451 | [_IOC_NR(CM_IOCARDOFF)] "CM_IOCARDOFF", | ||
1452 | [_IOC_NR(CM_IOCSPTS)] "CM_IOCSPTS", | ||
1453 | [_IOC_NR(CM_IOSDBGLVL)] "CM4000_DBGLVL", | ||
1454 | }; | ||
1455 | #endif | ||
1456 | DEBUGP(3, dev, "cmm_ioctl(device=%d.%d) %s\n", imajor(inode), | ||
1457 | iminor(inode), ioctl_names[_IOC_NR(cmd)]); | ||
1458 | |||
1459 | link = dev_table[iminor(inode)]; | ||
1460 | if (!(DEV_OK(link))) { | ||
1461 | DEBUGP(4, dev, "DEV_OK false\n"); | ||
1462 | return -ENODEV; | ||
1463 | } | ||
1464 | |||
1465 | if (test_bit(IS_CMM_ABSENT, &dev->flags)) { | ||
1466 | DEBUGP(4, dev, "CMM_ABSENT flag set\n"); | ||
1467 | return -ENODEV; | ||
1468 | } | ||
1469 | |||
1470 | if (_IOC_TYPE(cmd) != CM_IOC_MAGIC) { | ||
1471 | DEBUGP(4, dev, "ioctype mismatch\n"); | ||
1472 | return -EINVAL; | ||
1473 | } | ||
1474 | if (_IOC_NR(cmd) > CM_IOC_MAXNR) { | ||
1475 | DEBUGP(4, dev, "iocnr mismatch\n"); | ||
1476 | return -EINVAL; | ||
1477 | } | ||
1478 | size = _IOC_SIZE(cmd); | ||
1479 | rc = 0; | ||
1480 | DEBUGP(4, dev, "iocdir=%.4x iocr=%.4x iocw=%.4x iocsize=%d cmd=%.4x\n", | ||
1481 | _IOC_DIR(cmd), _IOC_READ, _IOC_WRITE, size, cmd); | ||
1482 | |||
1483 | if (_IOC_DIR(cmd) & _IOC_READ) { | ||
1484 | if (!access_ok(VERIFY_WRITE, (void *)arg, size)) | ||
1485 | return -EFAULT; | ||
1486 | } | ||
1487 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | ||
1488 | if (!access_ok(VERIFY_READ, (void *)arg, size)) | ||
1489 | return -EFAULT; | ||
1490 | } | ||
1491 | |||
1492 | switch (cmd) { | ||
1493 | case CM_IOCGSTATUS: | ||
1494 | DEBUGP(4, dev, " ... in CM_IOCGSTATUS\n"); | ||
1495 | { | ||
1496 | int status; | ||
1497 | |||
1498 | /* clear other bits, but leave inserted & powered as | ||
1499 | * they are */ | ||
1500 | status = dev->flags0 & 3; | ||
1501 | if (test_bit(IS_ATR_PRESENT, &dev->flags)) | ||
1502 | status |= CM_ATR_PRESENT; | ||
1503 | if (test_bit(IS_ATR_VALID, &dev->flags)) | ||
1504 | status |= CM_ATR_VALID; | ||
1505 | if (test_bit(IS_CMM_ABSENT, &dev->flags)) | ||
1506 | status |= CM_NO_READER; | ||
1507 | if (test_bit(IS_BAD_CARD, &dev->flags)) | ||
1508 | status |= CM_BAD_CARD; | ||
1509 | if (copy_to_user((int *)arg, &status, sizeof(int))) | ||
1510 | return -EFAULT; | ||
1511 | } | ||
1512 | return 0; | ||
1513 | case CM_IOCGATR: | ||
1514 | DEBUGP(4, dev, "... in CM_IOCGATR\n"); | ||
1515 | { | ||
1516 | struct atreq *atreq = (struct atreq *) arg; | ||
1517 | int tmp; | ||
1518 | /* allow nonblocking io and being interrupted */ | ||
1519 | if (wait_event_interruptible | ||
1520 | (dev->atrq, | ||
1521 | ((filp->f_flags & O_NONBLOCK) | ||
1522 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) | ||
1523 | != 0)))) { | ||
1524 | if (filp->f_flags & O_NONBLOCK) | ||
1525 | return -EAGAIN; | ||
1526 | return -ERESTARTSYS; | ||
1527 | } | ||
1528 | |||
1529 | if (test_bit(IS_ATR_VALID, &dev->flags) == 0) { | ||
1530 | tmp = -1; | ||
1531 | if (copy_to_user(&(atreq->atr_len), &tmp, | ||
1532 | sizeof(int))) | ||
1533 | return -EFAULT; | ||
1534 | } else { | ||
1535 | if (copy_to_user(atreq->atr, dev->atr, | ||
1536 | dev->atr_len)) | ||
1537 | return -EFAULT; | ||
1538 | |||
1539 | tmp = dev->atr_len; | ||
1540 | if (copy_to_user(&(atreq->atr_len), &tmp, sizeof(int))) | ||
1541 | return -EFAULT; | ||
1542 | } | ||
1543 | return 0; | ||
1544 | } | ||
1545 | case CM_IOCARDOFF: | ||
1546 | |||
1547 | #ifdef PCMCIA_DEBUG | ||
1548 | DEBUGP(4, dev, "... in CM_IOCARDOFF\n"); | ||
1549 | if (dev->flags0 & 0x01) { | ||
1550 | DEBUGP(4, dev, " Card inserted\n"); | ||
1551 | } else { | ||
1552 | DEBUGP(2, dev, " No card inserted\n"); | ||
1553 | } | ||
1554 | if (dev->flags0 & 0x02) { | ||
1555 | DEBUGP(4, dev, " Card powered\n"); | ||
1556 | } else { | ||
1557 | DEBUGP(2, dev, " Card not powered\n"); | ||
1558 | } | ||
1559 | #endif | ||
1560 | |||
1561 | /* is a card inserted and powered? */ | ||
1562 | if ((dev->flags0 & 0x01) && (dev->flags0 & 0x02)) { | ||
1563 | |||
1564 | /* get IO lock */ | ||
1565 | if (wait_event_interruptible | ||
1566 | (dev->ioq, | ||
1567 | ((filp->f_flags & O_NONBLOCK) | ||
1568 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) | ||
1569 | == 0)))) { | ||
1570 | if (filp->f_flags & O_NONBLOCK) | ||
1571 | return -EAGAIN; | ||
1572 | return -ERESTARTSYS; | ||
1573 | } | ||
1574 | /* Set Flags0 = 0x42 */ | ||
1575 | DEBUGP(4, dev, "Set Flags0=0x42 \n"); | ||
1576 | xoutb(0x42, REG_FLAGS0(iobase)); | ||
1577 | clear_bit(IS_ATR_PRESENT, &dev->flags); | ||
1578 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1579 | dev->mstate = M_CARDOFF; | ||
1580 | clear_bit(LOCK_IO, &dev->flags); | ||
1581 | if (wait_event_interruptible | ||
1582 | (dev->atrq, | ||
1583 | ((filp->f_flags & O_NONBLOCK) | ||
1584 | || (test_bit(IS_ATR_VALID, (void *)&dev->flags) != | ||
1585 | 0)))) { | ||
1586 | if (filp->f_flags & O_NONBLOCK) | ||
1587 | return -EAGAIN; | ||
1588 | return -ERESTARTSYS; | ||
1589 | } | ||
1590 | } | ||
1591 | /* release lock */ | ||
1592 | clear_bit(LOCK_IO, &dev->flags); | ||
1593 | wake_up_interruptible(&dev->ioq); | ||
1594 | |||
1595 | return 0; | ||
1596 | case CM_IOCSPTS: | ||
1597 | { | ||
1598 | struct ptsreq krnptsreq; | ||
1599 | |||
1600 | if (copy_from_user(&krnptsreq, (struct ptsreq *) arg, | ||
1601 | sizeof(struct ptsreq))) | ||
1602 | return -EFAULT; | ||
1603 | |||
1604 | rc = 0; | ||
1605 | DEBUGP(4, dev, "... in CM_IOCSPTS\n"); | ||
1606 | /* wait for ATR to get valid */ | ||
1607 | if (wait_event_interruptible | ||
1608 | (dev->atrq, | ||
1609 | ((filp->f_flags & O_NONBLOCK) | ||
1610 | || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) | ||
1611 | != 0)))) { | ||
1612 | if (filp->f_flags & O_NONBLOCK) | ||
1613 | return -EAGAIN; | ||
1614 | return -ERESTARTSYS; | ||
1615 | } | ||
1616 | /* get IO lock */ | ||
1617 | if (wait_event_interruptible | ||
1618 | (dev->ioq, | ||
1619 | ((filp->f_flags & O_NONBLOCK) | ||
1620 | || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) | ||
1621 | == 0)))) { | ||
1622 | if (filp->f_flags & O_NONBLOCK) | ||
1623 | return -EAGAIN; | ||
1624 | return -ERESTARTSYS; | ||
1625 | } | ||
1626 | |||
1627 | if ((rc = set_protocol(dev, &krnptsreq)) != 0) { | ||
1628 | /* auto power_on again */ | ||
1629 | dev->mstate = M_FETCH_ATR; | ||
1630 | clear_bit(IS_ATR_VALID, &dev->flags); | ||
1631 | } | ||
1632 | /* release lock */ | ||
1633 | clear_bit(LOCK_IO, &dev->flags); | ||
1634 | wake_up_interruptible(&dev->ioq); | ||
1635 | |||
1636 | } | ||
1637 | return rc; | ||
1638 | #ifdef PCMCIA_DEBUG | ||
1639 | case CM_IOSDBGLVL: /* set debug log level */ | ||
1640 | { | ||
1641 | int old_pc_debug = 0; | ||
1642 | |||
1643 | old_pc_debug = pc_debug; | ||
1644 | if (copy_from_user(&pc_debug, (int *)arg, sizeof(int))) | ||
1645 | return -EFAULT; | ||
1646 | |||
1647 | if (old_pc_debug != pc_debug) | ||
1648 | DEBUGP(0, dev, "Changed debug log level " | ||
1649 | "to %i\n", pc_debug); | ||
1650 | } | ||
1651 | return rc; | ||
1652 | #endif | ||
1653 | default: | ||
1654 | DEBUGP(4, dev, "... in default (unknown IOCTL code)\n"); | ||
1655 | return -EINVAL; | ||
1656 | } | ||
1657 | } | ||
1658 | |||
1659 | static int cmm_open(struct inode *inode, struct file *filp) | ||
1660 | { | ||
1661 | struct cm4000_dev *dev; | ||
1662 | dev_link_t *link; | ||
1663 | int rc, minor = iminor(inode); | ||
1664 | |||
1665 | if (minor >= CM4000_MAX_DEV) | ||
1666 | return -ENODEV; | ||
1667 | |||
1668 | link = dev_table[minor]; | ||
1669 | if (link == NULL || !(DEV_OK(link))) | ||
1670 | return -ENODEV; | ||
1671 | |||
1672 | if (link->open) | ||
1673 | return -EBUSY; | ||
1674 | |||
1675 | dev = link->priv; | ||
1676 | filp->private_data = dev; | ||
1677 | |||
1678 | DEBUGP(2, dev, "-> cmm_open(device=%d.%d process=%s,%d)\n", | ||
1679 | imajor(inode), minor, current->comm, current->pid); | ||
1680 | |||
1681 | /* init device variables, they may be "polluted" after close | ||
1682 | * or, the device may never have been closed (i.e. open failed) | ||
1683 | */ | ||
1684 | |||
1685 | ZERO_DEV(dev); | ||
1686 | |||
1687 | /* opening will always block since the | ||
1688 | * monitor will be started by open, which | ||
1689 | * means we have to wait for ATR becoming | ||
1690 | * vaild = block until valid (or card | ||
1691 | * inserted) | ||
1692 | */ | ||
1693 | if (filp->f_flags & O_NONBLOCK) | ||
1694 | return -EAGAIN; | ||
1695 | |||
1696 | dev->mdelay = T_50MSEC; | ||
1697 | |||
1698 | /* start monitoring the cardstatus */ | ||
1699 | start_monitor(dev); | ||
1700 | |||
1701 | link->open = 1; /* only one open per device */ | ||
1702 | rc = 0; | ||
1703 | |||
1704 | DEBUGP(2, dev, "<- cmm_open\n"); | ||
1705 | return nonseekable_open(inode, filp); | ||
1706 | } | ||
1707 | |||
1708 | static int cmm_close(struct inode *inode, struct file *filp) | ||
1709 | { | ||
1710 | struct cm4000_dev *dev; | ||
1711 | dev_link_t *link; | ||
1712 | int minor = iminor(inode); | ||
1713 | |||
1714 | if (minor >= CM4000_MAX_DEV) | ||
1715 | return -ENODEV; | ||
1716 | |||
1717 | link = dev_table[minor]; | ||
1718 | if (link == NULL) | ||
1719 | return -ENODEV; | ||
1720 | |||
1721 | dev = link->priv; | ||
1722 | |||
1723 | DEBUGP(2, dev, "-> cmm_close(maj/min=%d.%d)\n", | ||
1724 | imajor(inode), minor); | ||
1725 | |||
1726 | stop_monitor(dev); | ||
1727 | |||
1728 | ZERO_DEV(dev); | ||
1729 | |||
1730 | link->open = 0; /* only one open per device */ | ||
1731 | wake_up(&dev->devq); /* socket removed? */ | ||
1732 | |||
1733 | DEBUGP(2, dev, "cmm_close\n"); | ||
1734 | return 0; | ||
1735 | } | ||
1736 | |||
1737 | static void cmm_cm4000_release(dev_link_t * link) | ||
1738 | { | ||
1739 | struct cm4000_dev *dev = link->priv; | ||
1740 | |||
1741 | /* dont terminate the monitor, rather rely on | ||
1742 | * close doing that for us. | ||
1743 | */ | ||
1744 | DEBUGP(3, dev, "-> cmm_cm4000_release\n"); | ||
1745 | while (link->open) { | ||
1746 | printk(KERN_INFO MODULE_NAME ": delaying release until " | ||
1747 | "process has terminated\n"); | ||
1748 | /* note: don't interrupt us: | ||
1749 | * close the applications which own | ||
1750 | * the devices _first_ ! | ||
1751 | */ | ||
1752 | wait_event(dev->devq, (link->open == 0)); | ||
1753 | } | ||
1754 | /* dev->devq=NULL; this cannot be zeroed earlier */ | ||
1755 | DEBUGP(3, dev, "<- cmm_cm4000_release\n"); | ||
1756 | return; | ||
1757 | } | ||
1758 | |||
1759 | /*==== Interface to PCMCIA Layer =======================================*/ | ||
1760 | |||
1761 | static void cm4000_config(dev_link_t * link, int devno) | ||
1762 | { | ||
1763 | client_handle_t handle = link->handle; | ||
1764 | struct cm4000_dev *dev; | ||
1765 | tuple_t tuple; | ||
1766 | cisparse_t parse; | ||
1767 | config_info_t conf; | ||
1768 | u_char buf[64]; | ||
1769 | int fail_fn, fail_rc; | ||
1770 | int rc; | ||
1771 | |||
1772 | /* read the config-tuples */ | ||
1773 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
1774 | tuple.Attributes = 0; | ||
1775 | tuple.TupleData = buf; | ||
1776 | tuple.TupleDataMax = sizeof(buf); | ||
1777 | tuple.TupleOffset = 0; | ||
1778 | |||
1779 | if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) { | ||
1780 | fail_fn = GetFirstTuple; | ||
1781 | goto cs_failed; | ||
1782 | } | ||
1783 | if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) { | ||
1784 | fail_fn = GetTupleData; | ||
1785 | goto cs_failed; | ||
1786 | } | ||
1787 | if ((fail_rc = | ||
1788 | pcmcia_parse_tuple(handle, &tuple, &parse)) != CS_SUCCESS) { | ||
1789 | fail_fn = ParseTuple; | ||
1790 | goto cs_failed; | ||
1791 | } | ||
1792 | if ((fail_rc = | ||
1793 | pcmcia_get_configuration_info(handle, &conf)) != CS_SUCCESS) { | ||
1794 | fail_fn = GetConfigurationInfo; | ||
1795 | goto cs_failed; | ||
1796 | } | ||
1797 | |||
1798 | link->state |= DEV_CONFIG; | ||
1799 | link->conf.ConfigBase = parse.config.base; | ||
1800 | link->conf.Present = parse.config.rmask[0]; | ||
1801 | link->conf.Vcc = conf.Vcc; | ||
1802 | |||
1803 | link->io.BasePort2 = 0; | ||
1804 | link->io.NumPorts2 = 0; | ||
1805 | link->io.Attributes2 = 0; | ||
1806 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
1807 | for (rc = pcmcia_get_first_tuple(handle, &tuple); | ||
1808 | rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(handle, &tuple)) { | ||
1809 | |||
1810 | rc = pcmcia_get_tuple_data(handle, &tuple); | ||
1811 | if (rc != CS_SUCCESS) | ||
1812 | continue; | ||
1813 | rc = pcmcia_parse_tuple(handle, &tuple, &parse); | ||
1814 | if (rc != CS_SUCCESS) | ||
1815 | continue; | ||
1816 | |||
1817 | link->conf.ConfigIndex = parse.cftable_entry.index; | ||
1818 | |||
1819 | if (!parse.cftable_entry.io.nwin) | ||
1820 | continue; | ||
1821 | |||
1822 | /* Get the IOaddr */ | ||
1823 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; | ||
1824 | link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; | ||
1825 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
1826 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT)) | ||
1827 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
1828 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT)) | ||
1829 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
1830 | link->io.IOAddrLines = parse.cftable_entry.io.flags | ||
1831 | & CISTPL_IO_LINES_MASK; | ||
1832 | |||
1833 | rc = pcmcia_request_io(handle, &link->io); | ||
1834 | if (rc == CS_SUCCESS) | ||
1835 | break; /* we are done */ | ||
1836 | } | ||
1837 | if (rc != CS_SUCCESS) | ||
1838 | goto cs_release; | ||
1839 | |||
1840 | link->conf.IntType = 00000002; | ||
1841 | |||
1842 | if ((fail_rc = | ||
1843 | pcmcia_request_configuration(handle, &link->conf)) != CS_SUCCESS) { | ||
1844 | fail_fn = RequestConfiguration; | ||
1845 | goto cs_release; | ||
1846 | } | ||
1847 | |||
1848 | dev = link->priv; | ||
1849 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); | ||
1850 | dev->node.major = major; | ||
1851 | dev->node.minor = devno; | ||
1852 | dev->node.next = NULL; | ||
1853 | link->dev = &dev->node; | ||
1854 | link->state &= ~DEV_CONFIG_PENDING; | ||
1855 | |||
1856 | return; | ||
1857 | |||
1858 | cs_failed: | ||
1859 | cs_error(handle, fail_fn, fail_rc); | ||
1860 | cs_release: | ||
1861 | cm4000_release(link); | ||
1862 | |||
1863 | link->state &= ~DEV_CONFIG_PENDING; | ||
1864 | } | ||
1865 | |||
1866 | static int cm4000_event(event_t event, int priority, | ||
1867 | event_callback_args_t *args) | ||
1868 | { | ||
1869 | dev_link_t *link; | ||
1870 | struct cm4000_dev *dev; | ||
1871 | int devno; | ||
1872 | |||
1873 | link = args->client_data; | ||
1874 | dev = link->priv; | ||
1875 | |||
1876 | DEBUGP(3, dev, "-> cm4000_event\n"); | ||
1877 | for (devno = 0; devno < CM4000_MAX_DEV; devno++) | ||
1878 | if (dev_table[devno] == link) | ||
1879 | break; | ||
1880 | |||
1881 | if (devno == CM4000_MAX_DEV) | ||
1882 | return CS_BAD_ADAPTER; | ||
1883 | |||
1884 | switch (event) { | ||
1885 | case CS_EVENT_CARD_INSERTION: | ||
1886 | DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n"); | ||
1887 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
1888 | cm4000_config(link, devno); | ||
1889 | break; | ||
1890 | case CS_EVENT_CARD_REMOVAL: | ||
1891 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); | ||
1892 | link->state &= ~DEV_PRESENT; | ||
1893 | stop_monitor(dev); | ||
1894 | break; | ||
1895 | case CS_EVENT_PM_SUSPEND: | ||
1896 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | ||
1897 | "(fall-through to CS_EVENT_RESET_PHYSICAL)\n"); | ||
1898 | link->state |= DEV_SUSPEND; | ||
1899 | /* fall-through */ | ||
1900 | case CS_EVENT_RESET_PHYSICAL: | ||
1901 | DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n"); | ||
1902 | if (link->state & DEV_CONFIG) { | ||
1903 | DEBUGP(5, dev, "ReleaseConfiguration\n"); | ||
1904 | pcmcia_release_configuration(link->handle); | ||
1905 | } | ||
1906 | stop_monitor(dev); | ||
1907 | break; | ||
1908 | case CS_EVENT_PM_RESUME: | ||
1909 | DEBUGP(5, dev, "CS_EVENT_PM_RESUME " | ||
1910 | "(fall-through to CS_EVENT_CARD_RESET)\n"); | ||
1911 | link->state &= ~DEV_SUSPEND; | ||
1912 | /* fall-through */ | ||
1913 | case CS_EVENT_CARD_RESET: | ||
1914 | DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n"); | ||
1915 | if ((link->state & DEV_CONFIG)) { | ||
1916 | DEBUGP(5, dev, "RequestConfiguration\n"); | ||
1917 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1918 | } | ||
1919 | if (link->open) | ||
1920 | start_monitor(dev); | ||
1921 | break; | ||
1922 | default: | ||
1923 | DEBUGP(5, dev, "unknown event %.2x\n", event); | ||
1924 | break; | ||
1925 | } | ||
1926 | DEBUGP(3, dev, "<- cm4000_event\n"); | ||
1927 | return CS_SUCCESS; | ||
1928 | } | ||
1929 | |||
1930 | static void cm4000_release(dev_link_t *link) | ||
1931 | { | ||
1932 | cmm_cm4000_release(link->priv); /* delay release until device closed */ | ||
1933 | pcmcia_release_configuration(link->handle); | ||
1934 | pcmcia_release_io(link->handle, &link->io); | ||
1935 | } | ||
1936 | |||
1937 | static dev_link_t *cm4000_attach(void) | ||
1938 | { | ||
1939 | struct cm4000_dev *dev; | ||
1940 | dev_link_t *link; | ||
1941 | client_reg_t client_reg; | ||
1942 | int i; | ||
1943 | |||
1944 | for (i = 0; i < CM4000_MAX_DEV; i++) | ||
1945 | if (dev_table[i] == NULL) | ||
1946 | break; | ||
1947 | |||
1948 | if (i == CM4000_MAX_DEV) { | ||
1949 | printk(KERN_NOTICE MODULE_NAME ": all devices in use\n"); | ||
1950 | return NULL; | ||
1951 | } | ||
1952 | |||
1953 | /* create a new cm4000_cs device */ | ||
1954 | dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL); | ||
1955 | if (dev == NULL) | ||
1956 | return NULL; | ||
1957 | |||
1958 | link = &dev->link; | ||
1959 | link->priv = dev; | ||
1960 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
1961 | dev_table[i] = link; | ||
1962 | |||
1963 | /* register with card services */ | ||
1964 | client_reg.dev_info = &dev_info; | ||
1965 | client_reg.EventMask = | ||
1966 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
1967 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
1968 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
1969 | client_reg.Version = 0x0210; | ||
1970 | client_reg.event_callback_args.client_data = link; | ||
1971 | |||
1972 | i = pcmcia_register_client(&link->handle, &client_reg); | ||
1973 | if (i) { | ||
1974 | cs_error(link->handle, RegisterClient, i); | ||
1975 | cm4000_detach(link); | ||
1976 | return NULL; | ||
1977 | } | ||
1978 | |||
1979 | init_waitqueue_head(&dev->devq); | ||
1980 | init_waitqueue_head(&dev->ioq); | ||
1981 | init_waitqueue_head(&dev->atrq); | ||
1982 | init_waitqueue_head(&dev->readq); | ||
1983 | |||
1984 | return link; | ||
1985 | } | ||
1986 | |||
1987 | static void cm4000_detach_by_devno(int devno, dev_link_t * link) | ||
1988 | { | ||
1989 | struct cm4000_dev *dev = link->priv; | ||
1990 | |||
1991 | DEBUGP(3, dev, "-> detach_by_devno(devno=%d)\n", devno); | ||
1992 | |||
1993 | if (link->state & DEV_CONFIG) { | ||
1994 | DEBUGP(5, dev, "device still configured (try to release it)\n"); | ||
1995 | cm4000_release(link); | ||
1996 | } | ||
1997 | |||
1998 | if (link->handle) { | ||
1999 | pcmcia_deregister_client(link->handle); | ||
2000 | } | ||
2001 | |||
2002 | dev_table[devno] = NULL; | ||
2003 | kfree(dev); | ||
2004 | return; | ||
2005 | } | ||
2006 | |||
2007 | static void cm4000_detach(dev_link_t * link) | ||
2008 | { | ||
2009 | int i; | ||
2010 | |||
2011 | /* find device */ | ||
2012 | for (i = 0; i < CM4000_MAX_DEV; i++) | ||
2013 | if (dev_table[i] == link) | ||
2014 | break; | ||
2015 | |||
2016 | if (i == CM4000_MAX_DEV) | ||
2017 | return; | ||
2018 | |||
2019 | cm4000_detach_by_devno(i, link); | ||
2020 | return; | ||
2021 | } | ||
2022 | |||
2023 | static struct file_operations cm4000_fops = { | ||
2024 | .owner = THIS_MODULE, | ||
2025 | .read = cmm_read, | ||
2026 | .write = cmm_write, | ||
2027 | .ioctl = cmm_ioctl, | ||
2028 | .open = cmm_open, | ||
2029 | .release= cmm_close, | ||
2030 | }; | ||
2031 | |||
2032 | static struct pcmcia_device_id cm4000_ids[] = { | ||
2033 | PCMCIA_DEVICE_MANF_CARD(0x0223, 0x0002), | ||
2034 | PCMCIA_DEVICE_PROD_ID12("CardMan", "4000", 0x2FB368CA, 0xA2BD8C39), | ||
2035 | PCMCIA_DEVICE_NULL, | ||
2036 | }; | ||
2037 | MODULE_DEVICE_TABLE(pcmcia, cm4000_ids); | ||
2038 | |||
2039 | static struct pcmcia_driver cm4000_driver = { | ||
2040 | .owner = THIS_MODULE, | ||
2041 | .drv = { | ||
2042 | .name = "cm4000_cs", | ||
2043 | }, | ||
2044 | .attach = cm4000_attach, | ||
2045 | .detach = cm4000_detach, | ||
2046 | .event = cm4000_event, | ||
2047 | .id_table = cm4000_ids, | ||
2048 | }; | ||
2049 | |||
2050 | static int __init cmm_init(void) | ||
2051 | { | ||
2052 | printk(KERN_INFO "%s\n", version); | ||
2053 | pcmcia_register_driver(&cm4000_driver); | ||
2054 | major = register_chrdev(0, DEVICE_NAME, &cm4000_fops); | ||
2055 | if (major < 0) { | ||
2056 | printk(KERN_WARNING MODULE_NAME | ||
2057 | ": could not get major number\n"); | ||
2058 | return -1; | ||
2059 | } | ||
2060 | |||
2061 | return 0; | ||
2062 | } | ||
2063 | |||
2064 | static void __exit cmm_exit(void) | ||
2065 | { | ||
2066 | int i; | ||
2067 | |||
2068 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | ||
2069 | pcmcia_unregister_driver(&cm4000_driver); | ||
2070 | for (i = 0; i < CM4000_MAX_DEV; i++) | ||
2071 | if (dev_table[i]) | ||
2072 | cm4000_detach_by_devno(i, dev_table[i]); | ||
2073 | unregister_chrdev(major, DEVICE_NAME); | ||
2074 | }; | ||
2075 | |||
2076 | module_init(cmm_init); | ||
2077 | module_exit(cmm_exit); | ||
2078 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c new file mode 100644 index 000000000000..4c698d908ffa --- /dev/null +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -0,0 +1,841 @@ | |||
1 | /* | ||
2 | * A driver for the Omnikey PCMCIA smartcard reader CardMan 4040 | ||
3 | * | ||
4 | * (c) 2000-2004 Omnikey AG (http://www.omnikey.com/) | ||
5 | * | ||
6 | * (C) 2005 Harald Welte <laforge@gnumonks.org> | ||
7 | * - add support for poll() | ||
8 | * - driver cleanup | ||
9 | * - add waitqueues | ||
10 | * - adhere to linux kernel coding style and policies | ||
11 | * - support 2.6.13 "new style" pcmcia interface | ||
12 | * | ||
13 | * The device basically is a USB CCID compliant device that has been | ||
14 | * attached to an I/O-Mapped FIFO. | ||
15 | * | ||
16 | * All rights reserved, Dual BSD/GPL Licensed. | ||
17 | */ | ||
18 | |||
19 | /* #define PCMCIA_DEBUG 6 */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/poll.h> | ||
28 | #include <linux/wait.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | #include <asm/io.h> | ||
31 | |||
32 | #include <pcmcia/cs_types.h> | ||
33 | #include <pcmcia/cs.h> | ||
34 | #include <pcmcia/cistpl.h> | ||
35 | #include <pcmcia/cisreg.h> | ||
36 | #include <pcmcia/ciscode.h> | ||
37 | #include <pcmcia/ds.h> | ||
38 | |||
39 | #include "cm4040_cs.h" | ||
40 | |||
41 | |||
42 | #ifdef PCMCIA_DEBUG | ||
43 | #define reader_to_dev(x) (&handle_to_dev(x->link.handle)) | ||
44 | static int pc_debug = PCMCIA_DEBUG; | ||
45 | module_param(pc_debug, int, 0600); | ||
46 | #define DEBUGP(n, rdr, x, args...) do { \ | ||
47 | if (pc_debug >= (n)) \ | ||
48 | dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x, \ | ||
49 | __FUNCTION__ , ##args); \ | ||
50 | } while (0) | ||
51 | #else | ||
52 | #define DEBUGP(n, rdr, x, args...) | ||
53 | #endif | ||
54 | |||
55 | static char *version = | ||
56 | "OMNIKEY CardMan 4040 v1.1.0gm4 - All bugs added by Harald Welte"; | ||
57 | |||
58 | #define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*HZ) | ||
59 | #define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*HZ) | ||
60 | #define CCID_DRIVER_MINIMUM_TIMEOUT (3*HZ) | ||
61 | #define READ_WRITE_BUFFER_SIZE 512 | ||
62 | #define POLL_LOOP_COUNT 1000 | ||
63 | |||
64 | /* how often to poll for fifo status change */ | ||
65 | #define POLL_PERIOD msecs_to_jiffies(10) | ||
66 | |||
67 | static void reader_release(dev_link_t *link); | ||
68 | static void reader_detach(dev_link_t *link); | ||
69 | |||
70 | static int major; | ||
71 | |||
72 | #define BS_READABLE 0x01 | ||
73 | #define BS_WRITABLE 0x02 | ||
74 | |||
75 | struct reader_dev { | ||
76 | dev_link_t link; | ||
77 | dev_node_t node; | ||
78 | wait_queue_head_t devq; | ||
79 | wait_queue_head_t poll_wait; | ||
80 | wait_queue_head_t read_wait; | ||
81 | wait_queue_head_t write_wait; | ||
82 | unsigned long buffer_status; | ||
83 | unsigned long timeout; | ||
84 | unsigned char s_buf[READ_WRITE_BUFFER_SIZE]; | ||
85 | unsigned char r_buf[READ_WRITE_BUFFER_SIZE]; | ||
86 | struct timer_list poll_timer; | ||
87 | }; | ||
88 | |||
89 | static dev_info_t dev_info = MODULE_NAME; | ||
90 | static dev_link_t *dev_table[CM_MAX_DEV]; | ||
91 | |||
92 | #ifndef PCMCIA_DEBUG | ||
93 | #define xoutb outb | ||
94 | #define xinb inb | ||
95 | #else | ||
96 | static inline void xoutb(unsigned char val, unsigned short port) | ||
97 | { | ||
98 | if (pc_debug >= 7) | ||
99 | printk(KERN_DEBUG "outb(val=%.2x,port=%.4x)\n", val, port); | ||
100 | outb(val, port); | ||
101 | } | ||
102 | |||
103 | static inline unsigned char xinb(unsigned short port) | ||
104 | { | ||
105 | unsigned char val; | ||
106 | |||
107 | val = inb(port); | ||
108 | if (pc_debug >= 7) | ||
109 | printk(KERN_DEBUG "%.2x=inb(%.4x)\n", val, port); | ||
110 | return val; | ||
111 | } | ||
112 | #endif | ||
113 | |||
114 | /* poll the device fifo status register. not to be confused with | ||
115 | * the poll syscall. */ | ||
116 | static void cm4040_do_poll(unsigned long dummy) | ||
117 | { | ||
118 | struct reader_dev *dev = (struct reader_dev *) dummy; | ||
119 | unsigned int obs = xinb(dev->link.io.BasePort1 | ||
120 | + REG_OFFSET_BUFFER_STATUS); | ||
121 | |||
122 | if ((obs & BSR_BULK_IN_FULL)) { | ||
123 | set_bit(BS_READABLE, &dev->buffer_status); | ||
124 | DEBUGP(4, dev, "waking up read_wait\n"); | ||
125 | wake_up_interruptible(&dev->read_wait); | ||
126 | } else | ||
127 | clear_bit(BS_READABLE, &dev->buffer_status); | ||
128 | |||
129 | if (!(obs & BSR_BULK_OUT_FULL)) { | ||
130 | set_bit(BS_WRITABLE, &dev->buffer_status); | ||
131 | DEBUGP(4, dev, "waking up write_wait\n"); | ||
132 | wake_up_interruptible(&dev->write_wait); | ||
133 | } else | ||
134 | clear_bit(BS_WRITABLE, &dev->buffer_status); | ||
135 | |||
136 | if (dev->buffer_status) | ||
137 | wake_up_interruptible(&dev->poll_wait); | ||
138 | |||
139 | mod_timer(&dev->poll_timer, jiffies + POLL_PERIOD); | ||
140 | } | ||
141 | |||
142 | static void cm4040_stop_poll(struct reader_dev *dev) | ||
143 | { | ||
144 | del_timer_sync(&dev->poll_timer); | ||
145 | } | ||
146 | |||
147 | static int wait_for_bulk_out_ready(struct reader_dev *dev) | ||
148 | { | ||
149 | int i, rc; | ||
150 | int iobase = dev->link.io.BasePort1; | ||
151 | |||
152 | for (i = 0; i < POLL_LOOP_COUNT; i++) { | ||
153 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) | ||
154 | & BSR_BULK_OUT_FULL) == 0) { | ||
155 | DEBUGP(4, dev, "BulkOut empty (i=%d)\n", i); | ||
156 | return 1; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | DEBUGP(4, dev, "wait_event_interruptible_timeout(timeout=%ld\n", | ||
161 | dev->timeout); | ||
162 | rc = wait_event_interruptible_timeout(dev->write_wait, | ||
163 | test_and_clear_bit(BS_WRITABLE, | ||
164 | &dev->buffer_status), | ||
165 | dev->timeout); | ||
166 | |||
167 | if (rc > 0) | ||
168 | DEBUGP(4, dev, "woke up: BulkOut empty\n"); | ||
169 | else if (rc == 0) | ||
170 | DEBUGP(4, dev, "woke up: BulkOut full, returning 0 :(\n"); | ||
171 | else if (rc < 0) | ||
172 | DEBUGP(4, dev, "woke up: signal arrived\n"); | ||
173 | |||
174 | return rc; | ||
175 | } | ||
176 | |||
177 | /* Write to Sync Control Register */ | ||
178 | static int write_sync_reg(unsigned char val, struct reader_dev *dev) | ||
179 | { | ||
180 | int iobase = dev->link.io.BasePort1; | ||
181 | int rc; | ||
182 | |||
183 | rc = wait_for_bulk_out_ready(dev); | ||
184 | if (rc <= 0) | ||
185 | return rc; | ||
186 | |||
187 | xoutb(val, iobase + REG_OFFSET_SYNC_CONTROL); | ||
188 | rc = wait_for_bulk_out_ready(dev); | ||
189 | if (rc <= 0) | ||
190 | return rc; | ||
191 | |||
192 | return 1; | ||
193 | } | ||
194 | |||
195 | static int wait_for_bulk_in_ready(struct reader_dev *dev) | ||
196 | { | ||
197 | int i, rc; | ||
198 | int iobase = dev->link.io.BasePort1; | ||
199 | |||
200 | for (i = 0; i < POLL_LOOP_COUNT; i++) { | ||
201 | if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) | ||
202 | & BSR_BULK_IN_FULL) == BSR_BULK_IN_FULL) { | ||
203 | DEBUGP(3, dev, "BulkIn full (i=%d)\n", i); | ||
204 | return 1; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | DEBUGP(4, dev, "wait_event_interruptible_timeout(timeout=%ld\n", | ||
209 | dev->timeout); | ||
210 | rc = wait_event_interruptible_timeout(dev->read_wait, | ||
211 | test_and_clear_bit(BS_READABLE, | ||
212 | &dev->buffer_status), | ||
213 | dev->timeout); | ||
214 | if (rc > 0) | ||
215 | DEBUGP(4, dev, "woke up: BulkIn full\n"); | ||
216 | else if (rc == 0) | ||
217 | DEBUGP(4, dev, "woke up: BulkIn not full, returning 0 :(\n"); | ||
218 | else if (rc < 0) | ||
219 | DEBUGP(4, dev, "woke up: signal arrived\n"); | ||
220 | |||
221 | return rc; | ||
222 | } | ||
223 | |||
224 | static ssize_t cm4040_read(struct file *filp, char __user *buf, | ||
225 | size_t count, loff_t *ppos) | ||
226 | { | ||
227 | struct reader_dev *dev = filp->private_data; | ||
228 | int iobase = dev->link.io.BasePort1; | ||
229 | size_t bytes_to_read; | ||
230 | unsigned long i; | ||
231 | size_t min_bytes_to_read; | ||
232 | int rc; | ||
233 | unsigned char uc; | ||
234 | |||
235 | DEBUGP(2, dev, "-> cm4040_read(%s,%d)\n", current->comm, current->pid); | ||
236 | |||
237 | if (count == 0) | ||
238 | return 0; | ||
239 | |||
240 | if (count < 10) | ||
241 | return -EFAULT; | ||
242 | |||
243 | if (filp->f_flags & O_NONBLOCK) { | ||
244 | DEBUGP(4, dev, "filep->f_flags O_NONBLOCK set\n"); | ||
245 | DEBUGP(2, dev, "<- cm4040_read (failure)\n"); | ||
246 | return -EAGAIN; | ||
247 | } | ||
248 | |||
249 | if ((dev->link.state & DEV_PRESENT)==0) | ||
250 | return -ENODEV; | ||
251 | |||
252 | for (i = 0; i < 5; i++) { | ||
253 | rc = wait_for_bulk_in_ready(dev); | ||
254 | if (rc <= 0) { | ||
255 | DEBUGP(5, dev, "wait_for_bulk_in_ready rc=%.2x\n", rc); | ||
256 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
257 | if (rc == -ERESTARTSYS) | ||
258 | return rc; | ||
259 | return -EIO; | ||
260 | } | ||
261 | dev->r_buf[i] = xinb(iobase + REG_OFFSET_BULK_IN); | ||
262 | #ifdef PCMCIA_DEBUG | ||
263 | if (pc_debug >= 6) | ||
264 | printk(KERN_DEBUG "%lu:%2x ", i, dev->r_buf[i]); | ||
265 | } | ||
266 | printk("\n"); | ||
267 | #else | ||
268 | } | ||
269 | #endif | ||
270 | |||
271 | bytes_to_read = 5 + le32_to_cpu(*(__le32 *)&dev->r_buf[1]); | ||
272 | |||
273 | DEBUGP(6, dev, "BytesToRead=%lu\n", bytes_to_read); | ||
274 | |||
275 | min_bytes_to_read = min(count, bytes_to_read + 5); | ||
276 | |||
277 | DEBUGP(6, dev, "Min=%lu\n", min_bytes_to_read); | ||
278 | |||
279 | for (i = 0; i < (min_bytes_to_read-5); i++) { | ||
280 | rc = wait_for_bulk_in_ready(dev); | ||
281 | if (rc <= 0) { | ||
282 | DEBUGP(5, dev, "wait_for_bulk_in_ready rc=%.2x\n", rc); | ||
283 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
284 | if (rc == -ERESTARTSYS) | ||
285 | return rc; | ||
286 | return -EIO; | ||
287 | } | ||
288 | dev->r_buf[i+5] = xinb(iobase + REG_OFFSET_BULK_IN); | ||
289 | #ifdef PCMCIA_DEBUG | ||
290 | if (pc_debug >= 6) | ||
291 | printk(KERN_DEBUG "%lu:%2x ", i, dev->r_buf[i]); | ||
292 | } | ||
293 | printk("\n"); | ||
294 | #else | ||
295 | } | ||
296 | #endif | ||
297 | |||
298 | *ppos = min_bytes_to_read; | ||
299 | if (copy_to_user(buf, dev->r_buf, min_bytes_to_read)) | ||
300 | return -EFAULT; | ||
301 | |||
302 | rc = wait_for_bulk_in_ready(dev); | ||
303 | if (rc <= 0) { | ||
304 | DEBUGP(5, dev, "wait_for_bulk_in_ready rc=%.2x\n", rc); | ||
305 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
306 | if (rc == -ERESTARTSYS) | ||
307 | return rc; | ||
308 | return -EIO; | ||
309 | } | ||
310 | |||
311 | rc = write_sync_reg(SCR_READER_TO_HOST_DONE, dev); | ||
312 | if (rc <= 0) { | ||
313 | DEBUGP(5, dev, "write_sync_reg c=%.2x\n", rc); | ||
314 | DEBUGP(2, dev, "<- cm4040_read (failed)\n"); | ||
315 | if (rc == -ERESTARTSYS) | ||
316 | return rc; | ||
317 | else | ||
318 | return -EIO; | ||
319 | } | ||
320 | |||
321 | uc = xinb(iobase + REG_OFFSET_BULK_IN); | ||
322 | |||
323 | DEBUGP(2, dev, "<- cm4040_read (successfully)\n"); | ||
324 | return min_bytes_to_read; | ||
325 | } | ||
326 | |||
327 | static ssize_t cm4040_write(struct file *filp, const char __user *buf, | ||
328 | size_t count, loff_t *ppos) | ||
329 | { | ||
330 | struct reader_dev *dev = filp->private_data; | ||
331 | int iobase = dev->link.io.BasePort1; | ||
332 | ssize_t rc; | ||
333 | int i; | ||
334 | unsigned int bytes_to_write; | ||
335 | |||
336 | DEBUGP(2, dev, "-> cm4040_write(%s,%d)\n", current->comm, current->pid); | ||
337 | |||
338 | if (count == 0) { | ||
339 | DEBUGP(2, dev, "<- cm4040_write empty read (successfully)\n"); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | if (count < 5) { | ||
344 | DEBUGP(2, dev, "<- cm4040_write buffersize=%Zd < 5\n", count); | ||
345 | return -EIO; | ||
346 | } | ||
347 | |||
348 | if (filp->f_flags & O_NONBLOCK) { | ||
349 | DEBUGP(4, dev, "filep->f_flags O_NONBLOCK set\n"); | ||
350 | DEBUGP(4, dev, "<- cm4040_write (failure)\n"); | ||
351 | return -EAGAIN; | ||
352 | } | ||
353 | |||
354 | if ((dev->link.state & DEV_PRESENT) == 0) | ||
355 | return -ENODEV; | ||
356 | |||
357 | bytes_to_write = count; | ||
358 | if (copy_from_user(dev->s_buf, buf, bytes_to_write)) | ||
359 | return -EFAULT; | ||
360 | |||
361 | switch (dev->s_buf[0]) { | ||
362 | case CMD_PC_TO_RDR_XFRBLOCK: | ||
363 | case CMD_PC_TO_RDR_SECURE: | ||
364 | case CMD_PC_TO_RDR_TEST_SECURE: | ||
365 | case CMD_PC_TO_RDR_OK_SECURE: | ||
366 | dev->timeout = CCID_DRIVER_BULK_DEFAULT_TIMEOUT; | ||
367 | break; | ||
368 | |||
369 | case CMD_PC_TO_RDR_ICCPOWERON: | ||
370 | dev->timeout = CCID_DRIVER_ASYNC_POWERUP_TIMEOUT; | ||
371 | break; | ||
372 | |||
373 | case CMD_PC_TO_RDR_GETSLOTSTATUS: | ||
374 | case CMD_PC_TO_RDR_ICCPOWEROFF: | ||
375 | case CMD_PC_TO_RDR_GETPARAMETERS: | ||
376 | case CMD_PC_TO_RDR_RESETPARAMETERS: | ||
377 | case CMD_PC_TO_RDR_SETPARAMETERS: | ||
378 | case CMD_PC_TO_RDR_ESCAPE: | ||
379 | case CMD_PC_TO_RDR_ICCCLOCK: | ||
380 | default: | ||
381 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; | ||
382 | break; | ||
383 | } | ||
384 | |||
385 | rc = write_sync_reg(SCR_HOST_TO_READER_START, dev); | ||
386 | if (rc <= 0) { | ||
387 | DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); | ||
388 | DEBUGP(2, dev, "<- cm4040_write (failed)\n"); | ||
389 | if (rc == -ERESTARTSYS) | ||
390 | return rc; | ||
391 | else | ||
392 | return -EIO; | ||
393 | } | ||
394 | |||
395 | DEBUGP(4, dev, "start \n"); | ||
396 | |||
397 | for (i = 0; i < bytes_to_write; i++) { | ||
398 | rc = wait_for_bulk_out_ready(dev); | ||
399 | if (rc <= 0) { | ||
400 | DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2Zx\n", | ||
401 | rc); | ||
402 | DEBUGP(2, dev, "<- cm4040_write (failed)\n"); | ||
403 | if (rc == -ERESTARTSYS) | ||
404 | return rc; | ||
405 | else | ||
406 | return -EIO; | ||
407 | } | ||
408 | |||
409 | xoutb(dev->s_buf[i],iobase + REG_OFFSET_BULK_OUT); | ||
410 | } | ||
411 | DEBUGP(4, dev, "end\n"); | ||
412 | |||
413 | rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev); | ||
414 | |||
415 | if (rc <= 0) { | ||
416 | DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc); | ||
417 | DEBUGP(2, dev, "<- cm4040_write (failed)\n"); | ||
418 | if (rc == -ERESTARTSYS) | ||
419 | return rc; | ||
420 | else | ||
421 | return -EIO; | ||
422 | } | ||
423 | |||
424 | DEBUGP(2, dev, "<- cm4040_write (successfully)\n"); | ||
425 | return count; | ||
426 | } | ||
427 | |||
428 | static unsigned int cm4040_poll(struct file *filp, poll_table *wait) | ||
429 | { | ||
430 | struct reader_dev *dev = filp->private_data; | ||
431 | unsigned int mask = 0; | ||
432 | |||
433 | poll_wait(filp, &dev->poll_wait, wait); | ||
434 | |||
435 | if (test_and_clear_bit(BS_READABLE, &dev->buffer_status)) | ||
436 | mask |= POLLIN | POLLRDNORM; | ||
437 | if (test_and_clear_bit(BS_WRITABLE, &dev->buffer_status)) | ||
438 | mask |= POLLOUT | POLLWRNORM; | ||
439 | |||
440 | DEBUGP(2, dev, "<- cm4040_poll(%u)\n", mask); | ||
441 | |||
442 | return mask; | ||
443 | } | ||
444 | |||
445 | static int cm4040_open(struct inode *inode, struct file *filp) | ||
446 | { | ||
447 | struct reader_dev *dev; | ||
448 | dev_link_t *link; | ||
449 | int minor = iminor(inode); | ||
450 | |||
451 | if (minor >= CM_MAX_DEV) | ||
452 | return -ENODEV; | ||
453 | |||
454 | link = dev_table[minor]; | ||
455 | if (link == NULL || !(DEV_OK(link))) | ||
456 | return -ENODEV; | ||
457 | |||
458 | if (link->open) | ||
459 | return -EBUSY; | ||
460 | |||
461 | dev = link->priv; | ||
462 | filp->private_data = dev; | ||
463 | |||
464 | if (filp->f_flags & O_NONBLOCK) { | ||
465 | DEBUGP(4, dev, "filep->f_flags O_NONBLOCK set\n"); | ||
466 | return -EAGAIN; | ||
467 | } | ||
468 | |||
469 | link->open = 1; | ||
470 | |||
471 | dev->poll_timer.data = (unsigned long) dev; | ||
472 | mod_timer(&dev->poll_timer, jiffies + POLL_PERIOD); | ||
473 | |||
474 | DEBUGP(2, dev, "<- cm4040_open (successfully)\n"); | ||
475 | return nonseekable_open(inode, filp); | ||
476 | } | ||
477 | |||
478 | static int cm4040_close(struct inode *inode, struct file *filp) | ||
479 | { | ||
480 | struct reader_dev *dev = filp->private_data; | ||
481 | dev_link_t *link; | ||
482 | int minor = iminor(inode); | ||
483 | |||
484 | DEBUGP(2, dev, "-> cm4040_close(maj/min=%d.%d)\n", imajor(inode), | ||
485 | iminor(inode)); | ||
486 | |||
487 | if (minor >= CM_MAX_DEV) | ||
488 | return -ENODEV; | ||
489 | |||
490 | link = dev_table[minor]; | ||
491 | if (link == NULL) | ||
492 | return -ENODEV; | ||
493 | |||
494 | cm4040_stop_poll(dev); | ||
495 | |||
496 | link->open = 0; | ||
497 | wake_up(&dev->devq); | ||
498 | |||
499 | DEBUGP(2, dev, "<- cm4040_close\n"); | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | static void cm4040_reader_release(dev_link_t *link) | ||
504 | { | ||
505 | struct reader_dev *dev = link->priv; | ||
506 | |||
507 | DEBUGP(3, dev, "-> cm4040_reader_release\n"); | ||
508 | while (link->open) { | ||
509 | DEBUGP(3, dev, KERN_INFO MODULE_NAME ": delaying release " | ||
510 | "until process has terminated\n"); | ||
511 | wait_event(dev->devq, (link->open == 0)); | ||
512 | } | ||
513 | DEBUGP(3, dev, "<- cm4040_reader_release\n"); | ||
514 | return; | ||
515 | } | ||
516 | |||
517 | static void reader_config(dev_link_t *link, int devno) | ||
518 | { | ||
519 | client_handle_t handle; | ||
520 | struct reader_dev *dev; | ||
521 | tuple_t tuple; | ||
522 | cisparse_t parse; | ||
523 | config_info_t conf; | ||
524 | u_char buf[64]; | ||
525 | int fail_fn, fail_rc; | ||
526 | int rc; | ||
527 | |||
528 | handle = link->handle; | ||
529 | |||
530 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
531 | tuple.Attributes = 0; | ||
532 | tuple.TupleData = buf; | ||
533 | tuple.TupleDataMax = sizeof(buf); | ||
534 | tuple.TupleOffset = 0; | ||
535 | |||
536 | if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) { | ||
537 | fail_fn = GetFirstTuple; | ||
538 | goto cs_failed; | ||
539 | } | ||
540 | if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) { | ||
541 | fail_fn = GetTupleData; | ||
542 | goto cs_failed; | ||
543 | } | ||
544 | if ((fail_rc = pcmcia_parse_tuple(handle, &tuple, &parse)) | ||
545 | != CS_SUCCESS) { | ||
546 | fail_fn = ParseTuple; | ||
547 | goto cs_failed; | ||
548 | } | ||
549 | if ((fail_rc = pcmcia_get_configuration_info(handle, &conf)) | ||
550 | != CS_SUCCESS) { | ||
551 | fail_fn = GetConfigurationInfo; | ||
552 | goto cs_failed; | ||
553 | } | ||
554 | |||
555 | link->state |= DEV_CONFIG; | ||
556 | link->conf.ConfigBase = parse.config.base; | ||
557 | link->conf.Present = parse.config.rmask[0]; | ||
558 | link->conf.Vcc = conf.Vcc; | ||
559 | |||
560 | link->io.BasePort2 = 0; | ||
561 | link->io.NumPorts2 = 0; | ||
562 | link->io.Attributes2 = 0; | ||
563 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
564 | for (rc = pcmcia_get_first_tuple(handle, &tuple); | ||
565 | rc == CS_SUCCESS; | ||
566 | rc = pcmcia_get_next_tuple(handle, &tuple)) { | ||
567 | rc = pcmcia_get_tuple_data(handle, &tuple); | ||
568 | if (rc != CS_SUCCESS) | ||
569 | continue; | ||
570 | rc = pcmcia_parse_tuple(handle, &tuple, &parse); | ||
571 | if (rc != CS_SUCCESS) | ||
572 | continue; | ||
573 | |||
574 | link->conf.ConfigIndex = parse.cftable_entry.index; | ||
575 | |||
576 | if (!parse.cftable_entry.io.nwin) | ||
577 | continue; | ||
578 | |||
579 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; | ||
580 | link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; | ||
581 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
582 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT)) | ||
583 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
584 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT)) | ||
585 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
586 | link->io.IOAddrLines = parse.cftable_entry.io.flags | ||
587 | & CISTPL_IO_LINES_MASK; | ||
588 | rc = pcmcia_request_io(handle, &link->io); | ||
589 | |||
590 | dev_printk(KERN_INFO, &handle_to_dev(handle), "foo"); | ||
591 | if (rc == CS_SUCCESS) | ||
592 | break; | ||
593 | else | ||
594 | dev_printk(KERN_INFO, &handle_to_dev(handle), | ||
595 | "pcmcia_request_io failed 0x%x\n", rc); | ||
596 | } | ||
597 | if (rc != CS_SUCCESS) | ||
598 | goto cs_release; | ||
599 | |||
600 | link->conf.IntType = 00000002; | ||
601 | |||
602 | if ((fail_rc = pcmcia_request_configuration(handle,&link->conf)) | ||
603 | !=CS_SUCCESS) { | ||
604 | fail_fn = RequestConfiguration; | ||
605 | dev_printk(KERN_INFO, &handle_to_dev(handle), | ||
606 | "pcmcia_request_configuration failed 0x%x\n", | ||
607 | fail_rc); | ||
608 | goto cs_release; | ||
609 | } | ||
610 | |||
611 | dev = link->priv; | ||
612 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); | ||
613 | dev->node.major = major; | ||
614 | dev->node.minor = devno; | ||
615 | dev->node.next = NULL; | ||
616 | link->dev = &dev->node; | ||
617 | link->state &= ~DEV_CONFIG_PENDING; | ||
618 | |||
619 | DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno, | ||
620 | link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1); | ||
621 | DEBUGP(2, dev, "<- reader_config (succ)\n"); | ||
622 | |||
623 | return; | ||
624 | |||
625 | cs_failed: | ||
626 | cs_error(handle, fail_fn, fail_rc); | ||
627 | cs_release: | ||
628 | reader_release(link); | ||
629 | link->state &= ~DEV_CONFIG_PENDING; | ||
630 | } | ||
631 | |||
632 | static int reader_event(event_t event, int priority, | ||
633 | event_callback_args_t *args) | ||
634 | { | ||
635 | dev_link_t *link; | ||
636 | struct reader_dev *dev; | ||
637 | int devno; | ||
638 | |||
639 | link = args->client_data; | ||
640 | dev = link->priv; | ||
641 | DEBUGP(3, dev, "-> reader_event\n"); | ||
642 | for (devno = 0; devno < CM_MAX_DEV; devno++) { | ||
643 | if (dev_table[devno] == link) | ||
644 | break; | ||
645 | } | ||
646 | if (devno == CM_MAX_DEV) | ||
647 | return CS_BAD_ADAPTER; | ||
648 | |||
649 | switch (event) { | ||
650 | case CS_EVENT_CARD_INSERTION: | ||
651 | DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n"); | ||
652 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
653 | reader_config(link, devno); | ||
654 | break; | ||
655 | case CS_EVENT_CARD_REMOVAL: | ||
656 | DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); | ||
657 | link->state &= ~DEV_PRESENT; | ||
658 | break; | ||
659 | case CS_EVENT_PM_SUSPEND: | ||
660 | DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " | ||
661 | "(fall-through to CS_EVENT_RESET_PHYSICAL)\n"); | ||
662 | link->state |= DEV_SUSPEND; | ||
663 | |||
664 | case CS_EVENT_RESET_PHYSICAL: | ||
665 | DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n"); | ||
666 | if (link->state & DEV_CONFIG) { | ||
667 | DEBUGP(5, dev, "ReleaseConfiguration\n"); | ||
668 | pcmcia_release_configuration(link->handle); | ||
669 | } | ||
670 | break; | ||
671 | case CS_EVENT_PM_RESUME: | ||
672 | DEBUGP(5, dev, "CS_EVENT_PM_RESUME " | ||
673 | "(fall-through to CS_EVENT_CARD_RESET)\n"); | ||
674 | link->state &= ~DEV_SUSPEND; | ||
675 | |||
676 | case CS_EVENT_CARD_RESET: | ||
677 | DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n"); | ||
678 | if ((link->state & DEV_CONFIG)) { | ||
679 | DEBUGP(5, dev, "RequestConfiguration\n"); | ||
680 | pcmcia_request_configuration(link->handle, | ||
681 | &link->conf); | ||
682 | } | ||
683 | break; | ||
684 | default: | ||
685 | DEBUGP(5, dev, "reader_event: unknown event %.2x\n", | ||
686 | event); | ||
687 | break; | ||
688 | } | ||
689 | DEBUGP(3, dev, "<- reader_event\n"); | ||
690 | return CS_SUCCESS; | ||
691 | } | ||
692 | |||
693 | static void reader_release(dev_link_t *link) | ||
694 | { | ||
695 | cm4040_reader_release(link->priv); | ||
696 | pcmcia_release_configuration(link->handle); | ||
697 | pcmcia_release_io(link->handle, &link->io); | ||
698 | } | ||
699 | |||
700 | static dev_link_t *reader_attach(void) | ||
701 | { | ||
702 | struct reader_dev *dev; | ||
703 | dev_link_t *link; | ||
704 | client_reg_t client_reg; | ||
705 | int i; | ||
706 | |||
707 | for (i = 0; i < CM_MAX_DEV; i++) { | ||
708 | if (dev_table[i] == NULL) | ||
709 | break; | ||
710 | } | ||
711 | |||
712 | if (i == CM_MAX_DEV) | ||
713 | return NULL; | ||
714 | |||
715 | dev = kzalloc(sizeof(struct reader_dev), GFP_KERNEL); | ||
716 | if (dev == NULL) | ||
717 | return NULL; | ||
718 | |||
719 | dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; | ||
720 | dev->buffer_status = 0; | ||
721 | |||
722 | link = &dev->link; | ||
723 | link->priv = dev; | ||
724 | |||
725 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
726 | dev_table[i] = link; | ||
727 | |||
728 | client_reg.dev_info = &dev_info; | ||
729 | client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; | ||
730 | client_reg.EventMask= | ||
731 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
732 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
733 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
734 | client_reg.Version = 0x0210; | ||
735 | client_reg.event_callback_args.client_data = link; | ||
736 | i = pcmcia_register_client(&link->handle, &client_reg); | ||
737 | if (i) { | ||
738 | cs_error(link->handle, RegisterClient, i); | ||
739 | reader_detach(link); | ||
740 | return NULL; | ||
741 | } | ||
742 | init_waitqueue_head(&dev->devq); | ||
743 | init_waitqueue_head(&dev->poll_wait); | ||
744 | init_waitqueue_head(&dev->read_wait); | ||
745 | init_waitqueue_head(&dev->write_wait); | ||
746 | init_timer(&dev->poll_timer); | ||
747 | dev->poll_timer.function = &cm4040_do_poll; | ||
748 | |||
749 | return link; | ||
750 | } | ||
751 | |||
752 | static void reader_detach_by_devno(int devno, dev_link_t *link) | ||
753 | { | ||
754 | struct reader_dev *dev = link->priv; | ||
755 | |||
756 | if (link->state & DEV_CONFIG) { | ||
757 | DEBUGP(5, dev, "device still configured (try to release it)\n"); | ||
758 | reader_release(link); | ||
759 | } | ||
760 | |||
761 | pcmcia_deregister_client(link->handle); | ||
762 | dev_table[devno] = NULL; | ||
763 | DEBUGP(5, dev, "freeing dev=%p\n", dev); | ||
764 | cm4040_stop_poll(dev); | ||
765 | kfree(dev); | ||
766 | return; | ||
767 | } | ||
768 | |||
769 | static void reader_detach(dev_link_t *link) | ||
770 | { | ||
771 | int i; | ||
772 | |||
773 | /* find device */ | ||
774 | for (i = 0; i < CM_MAX_DEV; i++) { | ||
775 | if (dev_table[i] == link) | ||
776 | break; | ||
777 | } | ||
778 | if (i == CM_MAX_DEV) | ||
779 | return; | ||
780 | |||
781 | reader_detach_by_devno(i, link); | ||
782 | return; | ||
783 | } | ||
784 | |||
785 | static struct file_operations reader_fops = { | ||
786 | .owner = THIS_MODULE, | ||
787 | .read = cm4040_read, | ||
788 | .write = cm4040_write, | ||
789 | .open = cm4040_open, | ||
790 | .release = cm4040_close, | ||
791 | .poll = cm4040_poll, | ||
792 | }; | ||
793 | |||
794 | static struct pcmcia_device_id cm4040_ids[] = { | ||
795 | PCMCIA_DEVICE_MANF_CARD(0x0223, 0x0200), | ||
796 | PCMCIA_DEVICE_PROD_ID12("OMNIKEY", "CardMan 4040", | ||
797 | 0xE32CDD8C, 0x8F23318B), | ||
798 | PCMCIA_DEVICE_NULL, | ||
799 | }; | ||
800 | MODULE_DEVICE_TABLE(pcmcia, cm4040_ids); | ||
801 | |||
802 | static struct pcmcia_driver reader_driver = { | ||
803 | .owner = THIS_MODULE, | ||
804 | .drv = { | ||
805 | .name = "cm4040_cs", | ||
806 | }, | ||
807 | .attach = reader_attach, | ||
808 | .detach = reader_detach, | ||
809 | .event = reader_event, | ||
810 | .id_table = cm4040_ids, | ||
811 | }; | ||
812 | |||
813 | static int __init cm4040_init(void) | ||
814 | { | ||
815 | printk(KERN_INFO "%s\n", version); | ||
816 | pcmcia_register_driver(&reader_driver); | ||
817 | major = register_chrdev(0, DEVICE_NAME, &reader_fops); | ||
818 | if (major < 0) { | ||
819 | printk(KERN_WARNING MODULE_NAME | ||
820 | ": could not get major number\n"); | ||
821 | return -1; | ||
822 | } | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static void __exit cm4040_exit(void) | ||
827 | { | ||
828 | int i; | ||
829 | |||
830 | printk(KERN_INFO MODULE_NAME ": unloading\n"); | ||
831 | pcmcia_unregister_driver(&reader_driver); | ||
832 | for (i = 0; i < CM_MAX_DEV; i++) { | ||
833 | if (dev_table[i]) | ||
834 | reader_detach_by_devno(i, dev_table[i]); | ||
835 | } | ||
836 | unregister_chrdev(major, DEVICE_NAME); | ||
837 | } | ||
838 | |||
839 | module_init(cm4040_init); | ||
840 | module_exit(cm4040_exit); | ||
841 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/char/pcmcia/cm4040_cs.h b/drivers/char/pcmcia/cm4040_cs.h new file mode 100644 index 000000000000..9a8b805c5095 --- /dev/null +++ b/drivers/char/pcmcia/cm4040_cs.h | |||
@@ -0,0 +1,47 @@ | |||
1 | #ifndef _CM4040_H_ | ||
2 | #define _CM4040_H_ | ||
3 | |||
4 | #define CM_MAX_DEV 4 | ||
5 | |||
6 | #define DEVICE_NAME "cmx" | ||
7 | #define MODULE_NAME "cm4040_cs" | ||
8 | |||
9 | #define REG_OFFSET_BULK_OUT 0 | ||
10 | #define REG_OFFSET_BULK_IN 0 | ||
11 | #define REG_OFFSET_BUFFER_STATUS 1 | ||
12 | #define REG_OFFSET_SYNC_CONTROL 2 | ||
13 | |||
14 | #define BSR_BULK_IN_FULL 0x02 | ||
15 | #define BSR_BULK_OUT_FULL 0x01 | ||
16 | |||
17 | #define SCR_HOST_TO_READER_START 0x80 | ||
18 | #define SCR_ABORT 0x40 | ||
19 | #define SCR_EN_NOTIFY 0x20 | ||
20 | #define SCR_ACK_NOTIFY 0x10 | ||
21 | #define SCR_READER_TO_HOST_DONE 0x08 | ||
22 | #define SCR_HOST_TO_READER_DONE 0x04 | ||
23 | #define SCR_PULSE_INTERRUPT 0x02 | ||
24 | #define SCR_POWER_DOWN 0x01 | ||
25 | |||
26 | |||
27 | #define CMD_PC_TO_RDR_ICCPOWERON 0x62 | ||
28 | #define CMD_PC_TO_RDR_GETSLOTSTATUS 0x65 | ||
29 | #define CMD_PC_TO_RDR_ICCPOWEROFF 0x63 | ||
30 | #define CMD_PC_TO_RDR_SECURE 0x69 | ||
31 | #define CMD_PC_TO_RDR_GETPARAMETERS 0x6C | ||
32 | #define CMD_PC_TO_RDR_RESETPARAMETERS 0x6D | ||
33 | #define CMD_PC_TO_RDR_SETPARAMETERS 0x61 | ||
34 | #define CMD_PC_TO_RDR_XFRBLOCK 0x6F | ||
35 | #define CMD_PC_TO_RDR_ESCAPE 0x6B | ||
36 | #define CMD_PC_TO_RDR_ICCCLOCK 0x6E | ||
37 | #define CMD_PC_TO_RDR_TEST_SECURE 0x74 | ||
38 | #define CMD_PC_TO_RDR_OK_SECURE 0x89 | ||
39 | |||
40 | |||
41 | #define CMD_RDR_TO_PC_SLOTSTATUS 0x81 | ||
42 | #define CMD_RDR_TO_PC_DATABLOCK 0x80 | ||
43 | #define CMD_RDR_TO_PC_PARAMETERS 0x82 | ||
44 | #define CMD_RDR_TO_PC_ESCAPE 0x83 | ||
45 | #define CMD_RDR_TO_PC_OK_SECURE 0x89 | ||
46 | |||
47 | #endif /* _CM4040_H_ */ | ||
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 82c6abde68df..62aa0e534a6d 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/synclink.c | 2 | * linux/drivers/char/synclink.c |
3 | * | 3 | * |
4 | * $Id: synclink.c,v 4.37 2005/09/07 13:13:19 paulkf Exp $ | 4 | * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $ |
5 | * | 5 | * |
6 | * Device driver for Microgate SyncLink ISA and PCI | 6 | * Device driver for Microgate SyncLink ISA and PCI |
7 | * high speed multiprotocol serial adapters. | 7 | * high speed multiprotocol serial adapters. |
@@ -101,6 +101,7 @@ | |||
101 | #include <linux/termios.h> | 101 | #include <linux/termios.h> |
102 | #include <linux/workqueue.h> | 102 | #include <linux/workqueue.h> |
103 | #include <linux/hdlc.h> | 103 | #include <linux/hdlc.h> |
104 | #include <linux/dma-mapping.h> | ||
104 | 105 | ||
105 | #ifdef CONFIG_HDLC_MODULE | 106 | #ifdef CONFIG_HDLC_MODULE |
106 | #define CONFIG_HDLC 1 | 107 | #define CONFIG_HDLC 1 |
@@ -148,6 +149,7 @@ typedef struct _DMABUFFERENTRY | |||
148 | u32 link; /* 32-bit flat link to next buffer entry */ | 149 | u32 link; /* 32-bit flat link to next buffer entry */ |
149 | char *virt_addr; /* virtual address of data buffer */ | 150 | char *virt_addr; /* virtual address of data buffer */ |
150 | u32 phys_entry; /* physical address of this buffer entry */ | 151 | u32 phys_entry; /* physical address of this buffer entry */ |
152 | dma_addr_t dma_addr; | ||
151 | } DMABUFFERENTRY, *DMAPBUFFERENTRY; | 153 | } DMABUFFERENTRY, *DMAPBUFFERENTRY; |
152 | 154 | ||
153 | /* The queue of BH actions to be performed */ | 155 | /* The queue of BH actions to be performed */ |
@@ -233,7 +235,8 @@ struct mgsl_struct { | |||
233 | int ri_chkcount; | 235 | int ri_chkcount; |
234 | 236 | ||
235 | char *buffer_list; /* virtual address of Rx & Tx buffer lists */ | 237 | char *buffer_list; /* virtual address of Rx & Tx buffer lists */ |
236 | unsigned long buffer_list_phys; | 238 | u32 buffer_list_phys; |
239 | dma_addr_t buffer_list_dma_addr; | ||
237 | 240 | ||
238 | unsigned int rx_buffer_count; /* count of total allocated Rx buffers */ | 241 | unsigned int rx_buffer_count; /* count of total allocated Rx buffers */ |
239 | DMABUFFERENTRY *rx_buffer_list; /* list of receive buffer entries */ | 242 | DMABUFFERENTRY *rx_buffer_list; /* list of receive buffer entries */ |
@@ -896,7 +899,7 @@ module_param_array(txdmabufs, int, NULL, 0); | |||
896 | module_param_array(txholdbufs, int, NULL, 0); | 899 | module_param_array(txholdbufs, int, NULL, 0); |
897 | 900 | ||
898 | static char *driver_name = "SyncLink serial driver"; | 901 | static char *driver_name = "SyncLink serial driver"; |
899 | static char *driver_version = "$Revision: 4.37 $"; | 902 | static char *driver_version = "$Revision: 4.38 $"; |
900 | 903 | ||
901 | static int synclink_init_one (struct pci_dev *dev, | 904 | static int synclink_init_one (struct pci_dev *dev, |
902 | const struct pci_device_id *ent); | 905 | const struct pci_device_id *ent); |
@@ -3811,11 +3814,10 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) | |||
3811 | /* inspect portions of the buffer while other portions are being */ | 3814 | /* inspect portions of the buffer while other portions are being */ |
3812 | /* updated by the adapter using Bus Master DMA. */ | 3815 | /* updated by the adapter using Bus Master DMA. */ |
3813 | 3816 | ||
3814 | info->buffer_list = kmalloc(BUFFERLISTSIZE, GFP_KERNEL | GFP_DMA); | 3817 | info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL); |
3815 | if ( info->buffer_list == NULL ) | 3818 | if (info->buffer_list == NULL) |
3816 | return -ENOMEM; | 3819 | return -ENOMEM; |
3817 | 3820 | info->buffer_list_phys = (u32)(info->buffer_list_dma_addr); | |
3818 | info->buffer_list_phys = isa_virt_to_bus(info->buffer_list); | ||
3819 | } | 3821 | } |
3820 | 3822 | ||
3821 | /* We got the memory for the buffer entry lists. */ | 3823 | /* We got the memory for the buffer entry lists. */ |
@@ -3882,8 +3884,8 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) | |||
3882 | */ | 3884 | */ |
3883 | static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) | 3885 | static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) |
3884 | { | 3886 | { |
3885 | if ( info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI ) | 3887 | if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI) |
3886 | kfree(info->buffer_list); | 3888 | dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr); |
3887 | 3889 | ||
3888 | info->buffer_list = NULL; | 3890 | info->buffer_list = NULL; |
3889 | info->rx_buffer_list = NULL; | 3891 | info->rx_buffer_list = NULL; |
@@ -3910,7 +3912,7 @@ static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) | |||
3910 | static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) | 3912 | static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount) |
3911 | { | 3913 | { |
3912 | int i; | 3914 | int i; |
3913 | unsigned long phys_addr; | 3915 | u32 phys_addr; |
3914 | 3916 | ||
3915 | /* Allocate page sized buffers for the receive buffer list */ | 3917 | /* Allocate page sized buffers for the receive buffer list */ |
3916 | 3918 | ||
@@ -3922,11 +3924,10 @@ static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *Buff | |||
3922 | info->last_mem_alloc += DMABUFFERSIZE; | 3924 | info->last_mem_alloc += DMABUFFERSIZE; |
3923 | } else { | 3925 | } else { |
3924 | /* ISA adapter uses system memory. */ | 3926 | /* ISA adapter uses system memory. */ |
3925 | BufferList[i].virt_addr = | 3927 | BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL); |
3926 | kmalloc(DMABUFFERSIZE, GFP_KERNEL | GFP_DMA); | 3928 | if (BufferList[i].virt_addr == NULL) |
3927 | if ( BufferList[i].virt_addr == NULL ) | ||
3928 | return -ENOMEM; | 3929 | return -ENOMEM; |
3929 | phys_addr = isa_virt_to_bus(BufferList[i].virt_addr); | 3930 | phys_addr = (u32)(BufferList[i].dma_addr); |
3930 | } | 3931 | } |
3931 | BufferList[i].phys_addr = phys_addr; | 3932 | BufferList[i].phys_addr = phys_addr; |
3932 | } | 3933 | } |
@@ -3957,7 +3958,7 @@ static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *Buf | |||
3957 | for ( i = 0 ; i < Buffercount ; i++ ) { | 3958 | for ( i = 0 ; i < Buffercount ; i++ ) { |
3958 | if ( BufferList[i].virt_addr ) { | 3959 | if ( BufferList[i].virt_addr ) { |
3959 | if ( info->bus_type != MGSL_BUS_TYPE_PCI ) | 3960 | if ( info->bus_type != MGSL_BUS_TYPE_PCI ) |
3960 | kfree(BufferList[i].virt_addr); | 3961 | dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr); |
3961 | BufferList[i].virt_addr = NULL; | 3962 | BufferList[i].virt_addr = NULL; |
3962 | } | 3963 | } |
3963 | } | 3964 | } |
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index b58adfe3ed19..a6873bf89ffa 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -6,7 +6,7 @@ menu "TPM devices" | |||
6 | 6 | ||
7 | config TCG_TPM | 7 | config TCG_TPM |
8 | tristate "TPM Hardware Support" | 8 | tristate "TPM Hardware Support" |
9 | depends on EXPERIMENTAL && PCI | 9 | depends on EXPERIMENTAL |
10 | ---help--- | 10 | ---help--- |
11 | If you have a TPM security chip in your system, which | 11 | If you have a TPM security chip in your system, which |
12 | implements the Trusted Computing Group's specification, | 12 | implements the Trusted Computing Group's specification, |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 303f15880466..a9be0e8eaea5 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -43,6 +43,13 @@ static void user_reader_timeout(unsigned long ptr) | |||
43 | { | 43 | { |
44 | struct tpm_chip *chip = (struct tpm_chip *) ptr; | 44 | struct tpm_chip *chip = (struct tpm_chip *) ptr; |
45 | 45 | ||
46 | schedule_work(&chip->work); | ||
47 | } | ||
48 | |||
49 | static void timeout_work(void * ptr) | ||
50 | { | ||
51 | struct tpm_chip *chip = ptr; | ||
52 | |||
46 | down(&chip->buffer_mutex); | 53 | down(&chip->buffer_mutex); |
47 | atomic_set(&chip->data_pending, 0); | 54 | atomic_set(&chip->data_pending, 0); |
48 | memset(chip->data_buffer, 0, TPM_BUFSIZE); | 55 | memset(chip->data_buffer, 0, TPM_BUFSIZE); |
@@ -370,6 +377,7 @@ int tpm_release(struct inode *inode, struct file *file) | |||
370 | file->private_data = NULL; | 377 | file->private_data = NULL; |
371 | chip->num_opens--; | 378 | chip->num_opens--; |
372 | del_singleshot_timer_sync(&chip->user_read_timer); | 379 | del_singleshot_timer_sync(&chip->user_read_timer); |
380 | flush_scheduled_work(); | ||
373 | atomic_set(&chip->data_pending, 0); | 381 | atomic_set(&chip->data_pending, 0); |
374 | put_device(chip->dev); | 382 | put_device(chip->dev); |
375 | kfree(chip->data_buffer); | 383 | kfree(chip->data_buffer); |
@@ -421,6 +429,7 @@ ssize_t tpm_read(struct file * file, char __user *buf, | |||
421 | int ret_size; | 429 | int ret_size; |
422 | 430 | ||
423 | del_singleshot_timer_sync(&chip->user_read_timer); | 431 | del_singleshot_timer_sync(&chip->user_read_timer); |
432 | flush_scheduled_work(); | ||
424 | ret_size = atomic_read(&chip->data_pending); | 433 | ret_size = atomic_read(&chip->data_pending); |
425 | atomic_set(&chip->data_pending, 0); | 434 | atomic_set(&chip->data_pending, 0); |
426 | if (ret_size > 0) { /* relay data */ | 435 | if (ret_size > 0) { /* relay data */ |
@@ -428,8 +437,7 @@ ssize_t tpm_read(struct file * file, char __user *buf, | |||
428 | ret_size = size; | 437 | ret_size = size; |
429 | 438 | ||
430 | down(&chip->buffer_mutex); | 439 | down(&chip->buffer_mutex); |
431 | if (copy_to_user | 440 | if (copy_to_user(buf, chip->data_buffer, ret_size)) |
432 | ((void __user *) buf, chip->data_buffer, ret_size)) | ||
433 | ret_size = -EFAULT; | 441 | ret_size = -EFAULT; |
434 | up(&chip->buffer_mutex); | 442 | up(&chip->buffer_mutex); |
435 | } | 443 | } |
@@ -460,7 +468,7 @@ void tpm_remove_hardware(struct device *dev) | |||
460 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); | 468 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); |
461 | 469 | ||
462 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= | 470 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= |
463 | !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); | 471 | ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); |
464 | 472 | ||
465 | kfree(chip); | 473 | kfree(chip); |
466 | 474 | ||
@@ -528,6 +536,8 @@ int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) | |||
528 | init_MUTEX(&chip->tpm_mutex); | 536 | init_MUTEX(&chip->tpm_mutex); |
529 | INIT_LIST_HEAD(&chip->list); | 537 | INIT_LIST_HEAD(&chip->list); |
530 | 538 | ||
539 | INIT_WORK(&chip->work, timeout_work, chip); | ||
540 | |||
531 | init_timer(&chip->user_read_timer); | 541 | init_timer(&chip->user_read_timer); |
532 | chip->user_read_timer.function = user_reader_timeout; | 542 | chip->user_read_timer.function = user_reader_timeout; |
533 | chip->user_read_timer.data = (unsigned long) chip; | 543 | chip->user_read_timer.data = (unsigned long) chip; |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 9293bcc4dc62..159882ca69dd 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -50,7 +50,11 @@ struct tpm_vendor_specific { | |||
50 | u8 req_complete_mask; | 50 | u8 req_complete_mask; |
51 | u8 req_complete_val; | 51 | u8 req_complete_val; |
52 | u8 req_canceled; | 52 | u8 req_canceled; |
53 | u16 base; /* TPM base address */ | 53 | void __iomem *iobase; /* ioremapped address */ |
54 | unsigned long base; /* TPM base address */ | ||
55 | |||
56 | int region_size; | ||
57 | int have_region; | ||
54 | 58 | ||
55 | int (*recv) (struct tpm_chip *, u8 *, size_t); | 59 | int (*recv) (struct tpm_chip *, u8 *, size_t); |
56 | int (*send) (struct tpm_chip *, u8 *, size_t); | 60 | int (*send) (struct tpm_chip *, u8 *, size_t); |
@@ -73,6 +77,7 @@ struct tpm_chip { | |||
73 | struct semaphore buffer_mutex; | 77 | struct semaphore buffer_mutex; |
74 | 78 | ||
75 | struct timer_list user_read_timer; /* user needs to claim result */ | 79 | struct timer_list user_read_timer; /* user needs to claim result */ |
80 | struct work_struct work; | ||
76 | struct semaphore tpm_mutex; /* tpm is processing */ | 81 | struct semaphore tpm_mutex; /* tpm is processing */ |
77 | 82 | ||
78 | struct tpm_vendor_specific *vendor; | 83 | struct tpm_vendor_specific *vendor; |
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 32e01450c425..ff3654964fe3 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -19,14 +19,8 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/platform_device.h> | ||
23 | #include "tpm.h" | 22 | #include "tpm.h" |
24 | 23 | #include "tpm_atmel.h" | |
25 | /* Atmel definitions */ | ||
26 | enum tpm_atmel_addr { | ||
27 | TPM_ATMEL_BASE_ADDR_LO = 0x08, | ||
28 | TPM_ATMEL_BASE_ADDR_HI = 0x09 | ||
29 | }; | ||
30 | 24 | ||
31 | /* write status bits */ | 25 | /* write status bits */ |
32 | enum tpm_atmel_write_status { | 26 | enum tpm_atmel_write_status { |
@@ -53,13 +47,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
53 | return -EIO; | 47 | return -EIO; |
54 | 48 | ||
55 | for (i = 0; i < 6; i++) { | 49 | for (i = 0; i < 6; i++) { |
56 | status = inb(chip->vendor->base + 1); | 50 | status = ioread8(chip->vendor->iobase + 1); |
57 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 51 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
58 | dev_err(chip->dev, | 52 | dev_err(chip->dev, "error reading header\n"); |
59 | "error reading header\n"); | ||
60 | return -EIO; | 53 | return -EIO; |
61 | } | 54 | } |
62 | *buf++ = inb(chip->vendor->base); | 55 | *buf++ = ioread8(chip->vendor->iobase); |
63 | } | 56 | } |
64 | 57 | ||
65 | /* size of the data received */ | 58 | /* size of the data received */ |
@@ -70,10 +63,9 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
70 | dev_err(chip->dev, | 63 | dev_err(chip->dev, |
71 | "Recv size(%d) less than available space\n", size); | 64 | "Recv size(%d) less than available space\n", size); |
72 | for (; i < size; i++) { /* clear the waiting data anyway */ | 65 | for (; i < size; i++) { /* clear the waiting data anyway */ |
73 | status = inb(chip->vendor->base + 1); | 66 | status = ioread8(chip->vendor->iobase + 1); |
74 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 67 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
75 | dev_err(chip->dev, | 68 | dev_err(chip->dev, "error reading data\n"); |
76 | "error reading data\n"); | ||
77 | return -EIO; | 69 | return -EIO; |
78 | } | 70 | } |
79 | } | 71 | } |
@@ -82,17 +74,17 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
82 | 74 | ||
83 | /* read all the data available */ | 75 | /* read all the data available */ |
84 | for (; i < size; i++) { | 76 | for (; i < size; i++) { |
85 | status = inb(chip->vendor->base + 1); | 77 | status = ioread8(chip->vendor->iobase + 1); |
86 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 78 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
87 | dev_err(chip->dev, | 79 | dev_err(chip->dev, "error reading data\n"); |
88 | "error reading data\n"); | ||
89 | return -EIO; | 80 | return -EIO; |
90 | } | 81 | } |
91 | *buf++ = inb(chip->vendor->base); | 82 | *buf++ = ioread8(chip->vendor->iobase); |
92 | } | 83 | } |
93 | 84 | ||
94 | /* make sure data available is gone */ | 85 | /* make sure data available is gone */ |
95 | status = inb(chip->vendor->base + 1); | 86 | status = ioread8(chip->vendor->iobase + 1); |
87 | |||
96 | if (status & ATML_STATUS_DATA_AVAIL) { | 88 | if (status & ATML_STATUS_DATA_AVAIL) { |
97 | dev_err(chip->dev, "data available is stuck\n"); | 89 | dev_err(chip->dev, "data available is stuck\n"); |
98 | return -EIO; | 90 | return -EIO; |
@@ -108,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
108 | dev_dbg(chip->dev, "tpm_atml_send:\n"); | 100 | dev_dbg(chip->dev, "tpm_atml_send:\n"); |
109 | for (i = 0; i < count; i++) { | 101 | for (i = 0; i < count; i++) { |
110 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); | 102 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); |
111 | outb(buf[i], chip->vendor->base); | 103 | iowrite8(buf[i], chip->vendor->iobase); |
112 | } | 104 | } |
113 | 105 | ||
114 | return count; | 106 | return count; |
@@ -116,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
116 | 108 | ||
117 | static void tpm_atml_cancel(struct tpm_chip *chip) | 109 | static void tpm_atml_cancel(struct tpm_chip *chip) |
118 | { | 110 | { |
119 | outb(ATML_STATUS_ABORT, chip->vendor->base + 1); | 111 | iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1); |
120 | } | 112 | } |
121 | 113 | ||
122 | static u8 tpm_atml_status(struct tpm_chip *chip) | 114 | static u8 tpm_atml_status(struct tpm_chip *chip) |
123 | { | 115 | { |
124 | return inb(chip->vendor->base + 1); | 116 | return ioread8(chip->vendor->iobase + 1); |
125 | } | 117 | } |
126 | 118 | ||
127 | static struct file_operations atmel_ops = { | 119 | static struct file_operations atmel_ops = { |
@@ -162,12 +154,17 @@ static struct tpm_vendor_specific tpm_atmel = { | |||
162 | 154 | ||
163 | static struct platform_device *pdev; | 155 | static struct platform_device *pdev; |
164 | 156 | ||
165 | static void __devexit tpm_atml_remove(struct device *dev) | 157 | static void atml_plat_remove(void) |
166 | { | 158 | { |
167 | struct tpm_chip *chip = dev_get_drvdata(dev); | 159 | struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); |
160 | |||
168 | if (chip) { | 161 | if (chip) { |
169 | release_region(chip->vendor->base, 2); | 162 | if (chip->vendor->have_region) |
163 | atmel_release_region(chip->vendor->base, | ||
164 | chip->vendor->region_size); | ||
165 | atmel_put_base_addr(chip->vendor); | ||
170 | tpm_remove_hardware(chip->dev); | 166 | tpm_remove_hardware(chip->dev); |
167 | platform_device_unregister(pdev); | ||
171 | } | 168 | } |
172 | } | 169 | } |
173 | 170 | ||
@@ -182,72 +179,46 @@ static struct device_driver atml_drv = { | |||
182 | static int __init init_atmel(void) | 179 | static int __init init_atmel(void) |
183 | { | 180 | { |
184 | int rc = 0; | 181 | int rc = 0; |
185 | int lo, hi; | ||
186 | 182 | ||
187 | driver_register(&atml_drv); | 183 | driver_register(&atml_drv); |
188 | 184 | ||
189 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); | 185 | if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) { |
190 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); | 186 | rc = -ENODEV; |
191 | 187 | goto err_unreg_drv; | |
192 | tpm_atmel.base = (hi<<8)|lo; | ||
193 | |||
194 | /* verify that it is an Atmel part */ | ||
195 | if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T' | ||
196 | || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') { | ||
197 | return -ENODEV; | ||
198 | } | 188 | } |
199 | 189 | ||
200 | /* verify chip version number is 1.1 */ | 190 | tpm_atmel.have_region = |
201 | if ( (tpm_read_index(TPM_ADDR, 0x00) != 0x01) || | 191 | (atmel_request_region |
202 | (tpm_read_index(TPM_ADDR, 0x01) != 0x01 )) | 192 | (tpm_atmel.base, tpm_atmel.region_size, |
203 | return -ENODEV; | 193 | "tpm_atmel0") == NULL) ? 0 : 1; |
204 | |||
205 | pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL); | ||
206 | if ( !pdev ) | ||
207 | return -ENOMEM; | ||
208 | |||
209 | pdev->name = "tpm_atmel0"; | ||
210 | pdev->id = -1; | ||
211 | pdev->num_resources = 0; | ||
212 | pdev->dev.release = tpm_atml_remove; | ||
213 | pdev->dev.driver = &atml_drv; | ||
214 | |||
215 | if ((rc = platform_device_register(pdev)) < 0) { | ||
216 | kfree(pdev); | ||
217 | pdev = NULL; | ||
218 | return rc; | ||
219 | } | ||
220 | 194 | ||
221 | if (request_region(tpm_atmel.base, 2, "tpm_atmel0") == NULL ) { | 195 | if (IS_ERR |
222 | platform_device_unregister(pdev); | 196 | (pdev = |
223 | kfree(pdev); | 197 | platform_device_register_simple("tpm_atmel", -1, NULL, 0))) { |
224 | pdev = NULL; | 198 | rc = PTR_ERR(pdev); |
225 | return -EBUSY; | 199 | goto err_rel_reg; |
226 | } | 200 | } |
227 | 201 | ||
228 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) { | 202 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) |
229 | release_region(tpm_atmel.base, 2); | 203 | goto err_unreg_dev; |
230 | platform_device_unregister(pdev); | ||
231 | kfree(pdev); | ||
232 | pdev = NULL; | ||
233 | return rc; | ||
234 | } | ||
235 | |||
236 | dev_info(&pdev->dev, "Atmel TPM 1.1, Base Address: 0x%x\n", | ||
237 | tpm_atmel.base); | ||
238 | return 0; | 204 | return 0; |
205 | |||
206 | err_unreg_dev: | ||
207 | platform_device_unregister(pdev); | ||
208 | err_rel_reg: | ||
209 | atmel_put_base_addr(&tpm_atmel); | ||
210 | if (tpm_atmel.have_region) | ||
211 | atmel_release_region(tpm_atmel.base, | ||
212 | tpm_atmel.region_size); | ||
213 | err_unreg_drv: | ||
214 | driver_unregister(&atml_drv); | ||
215 | return rc; | ||
239 | } | 216 | } |
240 | 217 | ||
241 | static void __exit cleanup_atmel(void) | 218 | static void __exit cleanup_atmel(void) |
242 | { | 219 | { |
243 | if (pdev) { | ||
244 | tpm_atml_remove(&pdev->dev); | ||
245 | platform_device_unregister(pdev); | ||
246 | kfree(pdev); | ||
247 | pdev = NULL; | ||
248 | } | ||
249 | |||
250 | driver_unregister(&atml_drv); | 220 | driver_unregister(&atml_drv); |
221 | atml_plat_remove(); | ||
251 | } | 222 | } |
252 | 223 | ||
253 | module_init(init_atmel); | 224 | module_init(init_atmel); |
diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h new file mode 100644 index 000000000000..d3478aaadd77 --- /dev/null +++ b/drivers/char/tpm/tpm_atmel.h | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 IBM Corporation | ||
3 | * | ||
4 | * Authors: | ||
5 | * Kylene Hall <kjhall@us.ibm.com> | ||
6 | * | ||
7 | * Maintained by: <tpmdd_devel@lists.sourceforge.net> | ||
8 | * | ||
9 | * Device driver for TCG/TCPA TPM (trusted platform module). | ||
10 | * Specifications at www.trustedcomputinggroup.org | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License as | ||
14 | * published by the Free Software Foundation, version 2 of the | ||
15 | * License. | ||
16 | * | ||
17 | * These difference are required on power because the device must be | ||
18 | * discovered through the device tree and iomap must be used to get | ||
19 | * around the need for holes in the io_page_mask. This does not happen | ||
20 | * automatically because the tpm is not a normal pci device and lives | ||
21 | * under the root node. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifdef CONFIG_PPC64 | ||
26 | #define atmel_getb(chip, offset) readb(chip->vendor->iobase + offset); | ||
27 | #define atmel_putb(val, chip, offset) writeb(val, chip->vendor->iobase + offset) | ||
28 | #define atmel_request_region request_mem_region | ||
29 | #define atmel_release_region release_mem_region | ||
30 | |||
31 | static inline void atmel_put_base_addr(struct tpm_vendor_specific | ||
32 | *vendor) | ||
33 | { | ||
34 | iounmap(vendor->iobase); | ||
35 | } | ||
36 | |||
37 | static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor) | ||
38 | { | ||
39 | struct device_node *dn; | ||
40 | unsigned long address, size; | ||
41 | unsigned int *reg; | ||
42 | int reglen; | ||
43 | int naddrc; | ||
44 | int nsizec; | ||
45 | |||
46 | dn = of_find_node_by_name(NULL, "tpm"); | ||
47 | |||
48 | if (!dn) | ||
49 | return NULL; | ||
50 | |||
51 | if (!device_is_compatible(dn, "AT97SC3201")) { | ||
52 | of_node_put(dn); | ||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | reg = (unsigned int *) get_property(dn, "reg", ®len); | ||
57 | naddrc = prom_n_addr_cells(dn); | ||
58 | nsizec = prom_n_size_cells(dn); | ||
59 | |||
60 | of_node_put(dn); | ||
61 | |||
62 | |||
63 | if (naddrc == 2) | ||
64 | address = ((unsigned long) reg[0] << 32) | reg[1]; | ||
65 | else | ||
66 | address = reg[0]; | ||
67 | |||
68 | if (nsizec == 2) | ||
69 | size = | ||
70 | ((unsigned long) reg[naddrc] << 32) | reg[naddrc + 1]; | ||
71 | else | ||
72 | size = reg[naddrc]; | ||
73 | |||
74 | vendor->base = address; | ||
75 | vendor->region_size = size; | ||
76 | return ioremap(vendor->base, vendor->region_size); | ||
77 | } | ||
78 | #else | ||
79 | #define atmel_getb(chip, offset) inb(chip->vendor->base + offset) | ||
80 | #define atmel_putb(val, chip, offset) outb(val, chip->vendor->base + offset) | ||
81 | #define atmel_request_region request_region | ||
82 | #define atmel_release_region release_region | ||
83 | /* Atmel definitions */ | ||
84 | enum tpm_atmel_addr { | ||
85 | TPM_ATMEL_BASE_ADDR_LO = 0x08, | ||
86 | TPM_ATMEL_BASE_ADDR_HI = 0x09 | ||
87 | }; | ||
88 | |||
89 | /* Verify this is a 1.1 Atmel TPM */ | ||
90 | static int atmel_verify_tpm11(void) | ||
91 | { | ||
92 | |||
93 | /* verify that it is an Atmel part */ | ||
94 | if (tpm_read_index(TPM_ADDR, 4) != 'A' || | ||
95 | tpm_read_index(TPM_ADDR, 5) != 'T' || | ||
96 | tpm_read_index(TPM_ADDR, 6) != 'M' || | ||
97 | tpm_read_index(TPM_ADDR, 7) != 'L') | ||
98 | return 1; | ||
99 | |||
100 | /* query chip for its version number */ | ||
101 | if (tpm_read_index(TPM_ADDR, 0x00) != 1 || | ||
102 | tpm_read_index(TPM_ADDR, 0x01) != 1) | ||
103 | return 1; | ||
104 | |||
105 | /* This is an atmel supported part */ | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static inline void atmel_put_base_addr(struct tpm_vendor_specific | ||
110 | *vendor) | ||
111 | { | ||
112 | } | ||
113 | |||
114 | /* Determine where to talk to device */ | ||
115 | static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific | ||
116 | *vendor) | ||
117 | { | ||
118 | int lo, hi; | ||
119 | |||
120 | if (atmel_verify_tpm11() != 0) | ||
121 | return NULL; | ||
122 | |||
123 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); | ||
124 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); | ||
125 | |||
126 | vendor->base = (hi << 8) | lo; | ||
127 | vendor->region_size = 2; | ||
128 | |||
129 | return ioport_map(vendor->base, vendor->region_size); | ||
130 | } | ||
131 | #endif | ||
diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/watchdog/booke_wdt.c index abc30cca6645..65830ec71042 100644 --- a/drivers/char/watchdog/booke_wdt.c +++ b/drivers/char/watchdog/booke_wdt.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Watchdog timer for PowerPC Book-E systems | 4 | * Watchdog timer for PowerPC Book-E systems |
5 | * | 5 | * |
6 | * Author: Matthew McClintock | 6 | * Author: Matthew McClintock |
7 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | 7 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
8 | * | 8 | * |
9 | * Copyright 2005 Freescale Semiconductor Inc. | 9 | * Copyright 2005 Freescale Semiconductor Inc. |
10 | * | 10 | * |
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c index aa36855fa995..f87220be3c87 100644 --- a/drivers/i2c/busses/i2c-ixp4xx.c +++ b/drivers/i2c/busses/i2c-ixp4xx.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | #include <asm/hardware.h> /* Pick up IXP4xx-specific bits */ | 36 | #include <asm/hardware.h> /* Pick up IXP4xx-specific bits */ |
37 | 37 | ||
38 | static struct device_driver ixp4xx_i2c_driver; | 38 | static struct platform_driver ixp4xx_i2c_driver; |
39 | 39 | ||
40 | static inline int ixp4xx_scl_pin(void *data) | 40 | static inline int ixp4xx_scl_pin(void *data) |
41 | { | 41 | { |
@@ -128,7 +128,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev) | |||
128 | drv_data->algo_data.timeout = 100; | 128 | drv_data->algo_data.timeout = 100; |
129 | 129 | ||
130 | drv_data->adapter.id = I2C_HW_B_IXP4XX; | 130 | drv_data->adapter.id = I2C_HW_B_IXP4XX; |
131 | strlcpy(drv_data->adapter.name, ixp4xx_i2c_driver.name, | 131 | strlcpy(drv_data->adapter.name, ixp4xx_i2c_driver.driver.name, |
132 | I2C_NAME_SIZE); | 132 | I2C_NAME_SIZE); |
133 | drv_data->adapter.algo_data = &drv_data->algo_data; | 133 | drv_data->adapter.algo_data = &drv_data->algo_data; |
134 | 134 | ||
@@ -140,7 +140,8 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev) | |||
140 | gpio_line_set(gpio->sda_pin, 0); | 140 | gpio_line_set(gpio->sda_pin, 0); |
141 | 141 | ||
142 | if ((err = i2c_bit_add_bus(&drv_data->adapter) != 0)) { | 142 | if ((err = i2c_bit_add_bus(&drv_data->adapter) != 0)) { |
143 | printk(KERN_ERR "ERROR: Could not install %s\n", dev->bus_id); | 143 | printk(KERN_ERR "ERROR: Could not install %s\n", |
144 | plat_dev->dev.bus_id); | ||
144 | 145 | ||
145 | kfree(drv_data); | 146 | kfree(drv_data); |
146 | return err; | 147 | return err; |
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 42e5b8175cbf..ed2bc87f475b 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
@@ -787,6 +787,10 @@ config BLK_DEV_IDE_PMAC_BLINK | |||
787 | This option enables the use of the sleep LED as a hard drive | 787 | This option enables the use of the sleep LED as a hard drive |
788 | activity LED. | 788 | activity LED. |
789 | 789 | ||
790 | config BLK_DEV_IDE_SWARM | ||
791 | tristate "IDE for Sibyte evaluation boards" | ||
792 | depends on SIBYTE_SB1xxx_SOC | ||
793 | |||
790 | config BLK_DEV_IDE_AU1XXX | 794 | config BLK_DEV_IDE_AU1XXX |
791 | bool "IDE for AMD Alchemy Au1200" | 795 | bool "IDE for AMD Alchemy Au1200" |
792 | depends on SOC_AU1200 | 796 | depends on SOC_AU1200 |
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index cca9c075966d..569fae717503 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile | |||
@@ -48,6 +48,6 @@ obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o | |||
48 | obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o | 48 | obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o |
49 | obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o | 49 | obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o |
50 | 50 | ||
51 | obj-$(CONFIG_BLK_DEV_IDE) += legacy/ arm/ | 51 | obj-$(CONFIG_BLK_DEV_IDE) += legacy/ arm/ mips/ |
52 | obj-$(CONFIG_BLK_DEV_HD) += legacy/ | 52 | obj-$(CONFIG_BLK_DEV_HD) += legacy/ |
53 | obj-$(CONFIG_ETRAX_IDE) += cris/ | 53 | obj-$(CONFIG_ETRAX_IDE) += cris/ |
diff --git a/drivers/ide/mips/Makefile b/drivers/ide/mips/Makefile new file mode 100644 index 000000000000..578e52a59588 --- /dev/null +++ b/drivers/ide/mips/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_BLK_DEV_IDE_SWARM) += swarm.o | |||
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c new file mode 100644 index 000000000000..66f6064f4640 --- /dev/null +++ b/drivers/ide/mips/swarm.c | |||
@@ -0,0 +1,201 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001, 2002, 2003 Broadcom Corporation | ||
3 | * Copyright (C) 2004 MontaVista Software Inc. | ||
4 | * Author: Manish Lachwani, mlachwani@mvista.com | ||
5 | * Copyright (C) 2004 MIPS Technologies, Inc. All rights reserved. | ||
6 | * Author: Maciej W. Rozycki <macro@mips.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version 2 | ||
11 | * of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * Derived loosely from ide-pmac.c, so: | ||
25 | * Copyright (C) 1998 Paul Mackerras. | ||
26 | * Copyright (C) 1995-1998 Mark Lord | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | * Boards with SiByte processors so far have supported IDE devices via | ||
31 | * the Generic Bus, PCI bus, and built-in PCMCIA interface. In all | ||
32 | * cases, byte-swapping must be avoided for these devices (whereas | ||
33 | * other PCI devices, for example, will require swapping). Any | ||
34 | * SiByte-targetted kernel including IDE support will include this | ||
35 | * file. Probing of a Generic Bus for an IDE device is controlled by | ||
36 | * the definition of "SIBYTE_HAVE_IDE", which is provided by | ||
37 | * <asm/sibyte/board.h> for Broadcom boards. | ||
38 | */ | ||
39 | |||
40 | #include <linux/ide.h> | ||
41 | #include <linux/ioport.h> | ||
42 | #include <linux/kernel.h> | ||
43 | #include <linux/types.h> | ||
44 | #include <linux/platform_device.h> | ||
45 | |||
46 | #include <asm/io.h> | ||
47 | |||
48 | #include <asm/sibyte/board.h> | ||
49 | #include <asm/sibyte/sb1250_genbus.h> | ||
50 | #include <asm/sibyte/sb1250_regs.h> | ||
51 | |||
52 | #define DRV_NAME "ide-swarm" | ||
53 | |||
54 | static char swarm_ide_string[] = DRV_NAME; | ||
55 | |||
56 | static struct resource swarm_ide_resource = { | ||
57 | .name = "SWARM GenBus IDE", | ||
58 | .flags = IORESOURCE_MEM, | ||
59 | }; | ||
60 | |||
61 | static struct platform_device *swarm_ide_dev; | ||
62 | |||
63 | /* | ||
64 | * swarm_ide_probe - if the board header indicates the existence of | ||
65 | * Generic Bus IDE, allocate a HWIF for it. | ||
66 | */ | ||
67 | static int __devinit swarm_ide_probe(struct device *dev) | ||
68 | { | ||
69 | ide_hwif_t *hwif; | ||
70 | u8 __iomem *base; | ||
71 | phys_t offset, size; | ||
72 | int i; | ||
73 | |||
74 | if (!SIBYTE_HAVE_IDE) | ||
75 | return -ENODEV; | ||
76 | |||
77 | /* Find an empty slot. */ | ||
78 | for (i = 0; i < MAX_HWIFS; i++) | ||
79 | if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET]) | ||
80 | break; | ||
81 | if (i >= MAX_HWIFS) { | ||
82 | printk(KERN_ERR DRV_NAME ": no free slot for interface\n"); | ||
83 | return -ENOMEM; | ||
84 | } | ||
85 | |||
86 | hwif = ide_hwifs + i; | ||
87 | |||
88 | base = ioremap(A_IO_EXT_BASE, 0x800); | ||
89 | offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS)); | ||
90 | size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS)); | ||
91 | iounmap(base); | ||
92 | |||
93 | offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE; | ||
94 | size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE; | ||
95 | if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) { | ||
96 | printk(KERN_INFO DRV_NAME | ||
97 | ": IDE interface at GenBus disabled\n"); | ||
98 | return -EBUSY; | ||
99 | } | ||
100 | |||
101 | printk(KERN_INFO DRV_NAME ": IDE interface at GenBus slot %i\n", | ||
102 | IDE_CS); | ||
103 | |||
104 | swarm_ide_resource.start = offset; | ||
105 | swarm_ide_resource.end = offset + size - 1; | ||
106 | if (request_resource(&iomem_resource, &swarm_ide_resource)) { | ||
107 | printk(KERN_ERR DRV_NAME | ||
108 | ": can't request I/O memory resource\n"); | ||
109 | return -EBUSY; | ||
110 | } | ||
111 | |||
112 | base = ioremap(offset, size); | ||
113 | |||
114 | /* Setup MMIO ops. */ | ||
115 | default_hwif_mmiops(hwif); | ||
116 | /* Prevent resource map manipulation. */ | ||
117 | hwif->mmio = 2; | ||
118 | hwif->noprobe = 0; | ||
119 | |||
120 | for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) | ||
121 | hwif->hw.io_ports[i] = | ||
122 | (unsigned long)(base + ((0x1f0 + i) << 5)); | ||
123 | hwif->hw.io_ports[IDE_CONTROL_OFFSET] = | ||
124 | (unsigned long)(base + (0x3f6 << 5)); | ||
125 | hwif->hw.irq = K_INT_GB_IDE; | ||
126 | |||
127 | memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); | ||
128 | hwif->irq = hwif->hw.irq; | ||
129 | |||
130 | dev_set_drvdata(dev, hwif); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static struct device_driver swarm_ide_driver = { | ||
136 | .name = swarm_ide_string, | ||
137 | .bus = &platform_bus_type, | ||
138 | .probe = swarm_ide_probe, | ||
139 | }; | ||
140 | |||
141 | static void swarm_ide_platform_release(struct device *device) | ||
142 | { | ||
143 | struct platform_device *pldev; | ||
144 | |||
145 | /* free device */ | ||
146 | pldev = to_platform_device(device); | ||
147 | kfree(pldev); | ||
148 | } | ||
149 | |||
150 | static int __devinit swarm_ide_init_module(void) | ||
151 | { | ||
152 | struct platform_device *pldev; | ||
153 | int err; | ||
154 | |||
155 | printk(KERN_INFO "SWARM IDE driver\n"); | ||
156 | |||
157 | if (driver_register(&swarm_ide_driver)) { | ||
158 | printk(KERN_ERR "Driver registration failed\n"); | ||
159 | err = -ENODEV; | ||
160 | goto out; | ||
161 | } | ||
162 | |||
163 | if (!(pldev = kmalloc(sizeof (*pldev), GFP_KERNEL))) { | ||
164 | err = -ENOMEM; | ||
165 | goto out_unregister_driver; | ||
166 | } | ||
167 | |||
168 | memset (pldev, 0, sizeof (*pldev)); | ||
169 | pldev->name = swarm_ide_string; | ||
170 | pldev->id = 0; | ||
171 | pldev->dev.release = swarm_ide_platform_release; | ||
172 | |||
173 | if (platform_device_register(pldev)) { | ||
174 | err = -ENODEV; | ||
175 | goto out_free_pldev; | ||
176 | } | ||
177 | |||
178 | if (!pldev->dev.driver) { | ||
179 | /* | ||
180 | * The driver was not bound to this device, there was | ||
181 | * no hardware at this address. Unregister it, as the | ||
182 | * release fuction will take care of freeing the | ||
183 | * allocated structure | ||
184 | */ | ||
185 | platform_device_unregister (pldev); | ||
186 | } | ||
187 | |||
188 | swarm_ide_dev = pldev; | ||
189 | |||
190 | return 0; | ||
191 | |||
192 | out_free_pldev: | ||
193 | kfree(pldev); | ||
194 | |||
195 | out_unregister_driver: | ||
196 | driver_unregister(&swarm_ide_driver); | ||
197 | out: | ||
198 | return err; | ||
199 | } | ||
200 | |||
201 | module_init(swarm_ide_init_module); | ||
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index ea0806c82be0..8a5c7b286b2b 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c | |||
@@ -399,34 +399,6 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c | |||
399 | return dev->irq; | 399 | return dev->irq; |
400 | } | 400 | } |
401 | 401 | ||
402 | static void __devinit init_dma_sl82c105(ide_hwif_t *hwif, unsigned long dma_base) | ||
403 | { | ||
404 | unsigned int rev; | ||
405 | u8 dma_state; | ||
406 | |||
407 | DBG(("init_dma_sl82c105(hwif: ide%d, dma_base: 0x%08x)\n", hwif->index, dma_base)); | ||
408 | |||
409 | hwif->autodma = 0; | ||
410 | |||
411 | if (!dma_base) | ||
412 | return; | ||
413 | |||
414 | dma_state = hwif->INB(dma_base + 2); | ||
415 | rev = sl82c105_bridge_revision(hwif->pci_dev); | ||
416 | if (rev <= 5) { | ||
417 | printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", | ||
418 | hwif->name, rev); | ||
419 | dma_state &= ~0x60; | ||
420 | } else { | ||
421 | dma_state |= 0x60; | ||
422 | if (!noautodma) | ||
423 | hwif->autodma = 1; | ||
424 | } | ||
425 | hwif->OUTB(dma_state, dma_base + 2); | ||
426 | |||
427 | ide_setup_dma(hwif, dma_base, 8); | ||
428 | } | ||
429 | |||
430 | /* | 402 | /* |
431 | * Initialise the chip | 403 | * Initialise the chip |
432 | */ | 404 | */ |
@@ -434,6 +406,8 @@ static void __devinit init_dma_sl82c105(ide_hwif_t *hwif, unsigned long dma_base | |||
434 | static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) | 406 | static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) |
435 | { | 407 | { |
436 | struct pci_dev *dev = hwif->pci_dev; | 408 | struct pci_dev *dev = hwif->pci_dev; |
409 | unsigned int rev; | ||
410 | u8 dma_state; | ||
437 | u32 val; | 411 | u32 val; |
438 | 412 | ||
439 | DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); | 413 | DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); |
@@ -455,33 +429,54 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) | |||
455 | pci_read_config_dword(dev, 0x40, &val); | 429 | pci_read_config_dword(dev, 0x40, &val); |
456 | *((u32 *)&hwif->hwif_data) = val; | 430 | *((u32 *)&hwif->hwif_data) = val; |
457 | 431 | ||
432 | hwif->atapi_dma = 0; | ||
433 | hwif->mwdma_mask = 0; | ||
434 | hwif->swdma_mask = 0; | ||
435 | hwif->autodma = 0; | ||
436 | |||
458 | if (!hwif->dma_base) | 437 | if (!hwif->dma_base) |
459 | return; | 438 | return; |
460 | 439 | ||
461 | hwif->atapi_dma = 1; | 440 | dma_state = hwif->INB(hwif->dma_base + 2) & ~0x60; |
462 | hwif->mwdma_mask = 0x07; | 441 | rev = sl82c105_bridge_revision(hwif->pci_dev); |
463 | hwif->swdma_mask = 0x07; | 442 | if (rev <= 5) { |
464 | 443 | /* | |
444 | * Never ever EVER under any circumstances enable | ||
445 | * DMA when the bridge is this old. | ||
446 | */ | ||
447 | printk(" %s: Winbond 553 bridge revision %d, BM-DMA disabled\n", | ||
448 | hwif->name, rev); | ||
449 | } else { | ||
465 | #ifdef CONFIG_BLK_DEV_IDEDMA | 450 | #ifdef CONFIG_BLK_DEV_IDEDMA |
466 | hwif->ide_dma_check = &sl82c105_check_drive; | 451 | dma_state |= 0x60; |
467 | hwif->ide_dma_on = &sl82c105_ide_dma_on; | 452 | |
468 | hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; | 453 | hwif->atapi_dma = 1; |
469 | hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; | 454 | hwif->mwdma_mask = 0x07; |
470 | hwif->dma_start = &sl82c105_ide_dma_start; | 455 | hwif->swdma_mask = 0x07; |
471 | hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; | 456 | |
472 | 457 | hwif->ide_dma_check = &sl82c105_check_drive; | |
473 | if (!noautodma) | 458 | hwif->ide_dma_on = &sl82c105_ide_dma_on; |
474 | hwif->autodma = 1; | 459 | hwif->ide_dma_off_quietly = &sl82c105_ide_dma_off_quietly; |
475 | hwif->drives[0].autodma = hwif->autodma; | 460 | hwif->ide_dma_lostirq = &sl82c105_ide_dma_lost_irq; |
476 | hwif->drives[1].autodma = hwif->autodma; | 461 | hwif->dma_start = &sl82c105_ide_dma_start; |
462 | hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout; | ||
463 | |||
464 | if (!noautodma) | ||
465 | hwif->autodma = 1; | ||
466 | hwif->drives[0].autodma = hwif->autodma; | ||
467 | hwif->drives[1].autodma = hwif->autodma; | ||
468 | |||
469 | if (hwif->mate) | ||
470 | hwif->serialized = hwif->mate->serialized = 1; | ||
477 | #endif /* CONFIG_BLK_DEV_IDEDMA */ | 471 | #endif /* CONFIG_BLK_DEV_IDEDMA */ |
472 | } | ||
473 | hwif->OUTB(dma_state, hwif->dma_base + 2); | ||
478 | } | 474 | } |
479 | 475 | ||
480 | static ide_pci_device_t sl82c105_chipset __devinitdata = { | 476 | static ide_pci_device_t sl82c105_chipset __devinitdata = { |
481 | .name = "W82C105", | 477 | .name = "W82C105", |
482 | .init_chipset = init_chipset_sl82c105, | 478 | .init_chipset = init_chipset_sl82c105, |
483 | .init_hwif = init_hwif_sl82c105, | 479 | .init_hwif = init_hwif_sl82c105, |
484 | .init_dma = init_dma_sl82c105, | ||
485 | .channels = 2, | 480 | .channels = 2, |
486 | .autodma = NOAUTODMA, | 481 | .autodma = NOAUTODMA, |
487 | .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, | 482 | .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, |
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index b3e65a65d202..136911a86e84 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c | |||
@@ -1667,11 +1667,16 @@ static struct macio_driver pmac_ide_macio_driver = | |||
1667 | }; | 1667 | }; |
1668 | 1668 | ||
1669 | static struct pci_device_id pmac_ide_pci_match[] = { | 1669 | static struct pci_device_id pmac_ide_pci_match[] = { |
1670 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1670 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA, |
1671 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1671 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
1672 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1672 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, |
1673 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1674 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, | ||
1675 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1673 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA, | 1676 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA, |
1674 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 1677 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
1678 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA, | ||
1679 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1675 | }; | 1680 | }; |
1676 | 1681 | ||
1677 | static struct pci_driver pmac_ide_pci_driver = { | 1682 | static struct pci_driver pmac_ide_pci_driver = { |
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c index 32bf0d5d0f9a..f8457ef48826 100644 --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c | |||
@@ -71,78 +71,68 @@ typedef struct { | |||
71 | /****************************************/ | 71 | /****************************************/ |
72 | static struct usb_device_id hfcusb_idtab[] = { | 72 | static struct usb_device_id hfcusb_idtab[] = { |
73 | { | 73 | { |
74 | .idVendor = 0x0959, | 74 | USB_DEVICE(0x0959, 0x2bd0), |
75 | .idProduct = 0x2bd0, | ||
76 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 75 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
77 | {LED_OFF, {4, 0, 2, 1}, | 76 | {LED_OFF, {4, 0, 2, 1}, |
78 | "ISDN USB TA (Cologne Chip HFC-S USB based)"}), | 77 | "ISDN USB TA (Cologne Chip HFC-S USB based)"}), |
79 | }, | 78 | }, |
80 | { | 79 | { |
81 | .idVendor = 0x0675, | 80 | USB_DEVICE(0x0675, 0x1688), |
82 | .idProduct = 0x1688, | ||
83 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 81 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
84 | {LED_SCHEME1, {1, 2, 0, 0}, | 82 | {LED_SCHEME1, {1, 2, 0, 0}, |
85 | "DrayTek miniVigor 128 USB ISDN TA"}), | 83 | "DrayTek miniVigor 128 USB ISDN TA"}), |
86 | }, | 84 | }, |
87 | { | 85 | { |
88 | .idVendor = 0x07b0, | 86 | USB_DEVICE(0x07b0, 0x0007), |
89 | .idProduct = 0x0007, | ||
90 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 87 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
91 | {LED_SCHEME1, {0x80, -64, -32, -16}, | 88 | {LED_SCHEME1, {0x80, -64, -32, -16}, |
92 | "Billion tiny USB ISDN TA 128"}), | 89 | "Billion tiny USB ISDN TA 128"}), |
93 | }, | 90 | }, |
94 | { | 91 | { |
95 | .idVendor = 0x0742, | 92 | USB_DEVICE(0x0742, 0x2008), |
96 | .idProduct = 0x2008, | ||
97 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 93 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
98 | {LED_SCHEME1, {4, 0, 2, 1}, | 94 | {LED_SCHEME1, {4, 0, 2, 1}, |
99 | "Stollmann USB TA"}), | 95 | "Stollmann USB TA"}), |
100 | }, | 96 | }, |
101 | { | 97 | { |
102 | .idVendor = 0x0742, | 98 | USB_DEVICE(0x0742, 0x2009), |
103 | .idProduct = 0x2009, | ||
104 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 99 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
105 | {LED_SCHEME1, {4, 0, 2, 1}, | 100 | {LED_SCHEME1, {4, 0, 2, 1}, |
106 | "Aceex USB ISDN TA"}), | 101 | "Aceex USB ISDN TA"}), |
107 | }, | 102 | }, |
108 | { | 103 | { |
109 | .idVendor = 0x0742, | 104 | USB_DEVICE(0x0742, 0x200A), |
110 | .idProduct = 0x200A, | ||
111 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 105 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
112 | {LED_SCHEME1, {4, 0, 2, 1}, | 106 | {LED_SCHEME1, {4, 0, 2, 1}, |
113 | "OEM USB ISDN TA"}), | 107 | "OEM USB ISDN TA"}), |
114 | }, | 108 | }, |
115 | { | 109 | { |
116 | .idVendor = 0x08e3, | 110 | USB_DEVICE(0x08e3, 0x0301), |
117 | .idProduct = 0x0301, | ||
118 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 111 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
119 | {LED_SCHEME1, {2, 0, 1, 4}, | 112 | {LED_SCHEME1, {2, 0, 1, 4}, |
120 | "Olitec USB RNIS"}), | 113 | "Olitec USB RNIS"}), |
121 | }, | 114 | }, |
122 | { | 115 | { |
123 | .idVendor = 0x07fa, | 116 | USB_DEVICE(0x07fa, 0x0846), |
124 | .idProduct = 0x0846, | ||
125 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 117 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
126 | {LED_SCHEME1, {0x80, -64, -32, -16}, | 118 | {LED_SCHEME1, {0x80, -64, -32, -16}, |
127 | "Bewan Modem RNIS USB"}), | 119 | "Bewan Modem RNIS USB"}), |
128 | }, | 120 | }, |
129 | { | 121 | { |
130 | .idVendor = 0x07fa, | 122 | USB_DEVICE(0x07fa, 0x0847), |
131 | .idProduct = 0x0847, | ||
132 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 123 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
133 | {LED_SCHEME1, {0x80, -64, -32, -16}, | 124 | {LED_SCHEME1, {0x80, -64, -32, -16}, |
134 | "Djinn Numeris USB"}), | 125 | "Djinn Numeris USB"}), |
135 | }, | 126 | }, |
136 | { | 127 | { |
137 | .idVendor = 0x07b0, | 128 | USB_DEVICE(0x07b0, 0x0006), |
138 | .idProduct = 0x0006, | ||
139 | .driver_info = (unsigned long) &((hfcsusb_vdata) | 129 | .driver_info = (unsigned long) &((hfcsusb_vdata) |
140 | {LED_SCHEME1, {0x80, -64, -32, -16}, | 130 | {LED_SCHEME1, {0x80, -64, -32, -16}, |
141 | "Twister ISDN TA"}), | 131 | "Twister ISDN TA"}), |
142 | }, | 132 | }, |
133 | { } | ||
143 | }; | 134 | }; |
144 | 135 | ||
145 | |||
146 | /***************************************************************/ | 136 | /***************************************************************/ |
147 | /* structure defining input+output fifos (interrupt/bulk mode) */ | 137 | /* structure defining input+output fifos (interrupt/bulk mode) */ |
148 | /***************************************************************/ | 138 | /***************************************************************/ |
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 51315302a85e..252d55df9642 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -326,9 +326,9 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait) | |||
326 | } | 326 | } |
327 | } | 327 | } |
328 | 328 | ||
329 | ret = page->mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE); | 329 | ret = page->mapping->a_ops->prepare_write(bitmap->file, page, 0, PAGE_SIZE); |
330 | if (!ret) | 330 | if (!ret) |
331 | ret = page->mapping->a_ops->commit_write(NULL, page, 0, | 331 | ret = page->mapping->a_ops->commit_write(bitmap->file, page, 0, |
332 | PAGE_SIZE); | 332 | PAGE_SIZE); |
333 | if (ret) { | 333 | if (ret) { |
334 | unlock_page(page); | 334 | unlock_page(page); |
diff --git a/drivers/md/md.c b/drivers/md/md.c index adf960d8a7c9..78c7418478d6 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3156,7 +3156,7 @@ static int md_ioctl(struct inode *inode, struct file *file, | |||
3156 | if (cnt > 0 ) { | 3156 | if (cnt > 0 ) { |
3157 | printk(KERN_WARNING | 3157 | printk(KERN_WARNING |
3158 | "md: %s(pid %d) used deprecated START_ARRAY ioctl. " | 3158 | "md: %s(pid %d) used deprecated START_ARRAY ioctl. " |
3159 | "This will not be supported beyond 2.6\n", | 3159 | "This will not be supported beyond July 2006\n", |
3160 | current->comm, current->pid); | 3160 | current->comm, current->pid); |
3161 | cnt--; | 3161 | cnt--; |
3162 | } | 3162 | } |
@@ -3437,10 +3437,19 @@ static int md_thread(void * arg) | |||
3437 | allow_signal(SIGKILL); | 3437 | allow_signal(SIGKILL); |
3438 | while (!kthread_should_stop()) { | 3438 | while (!kthread_should_stop()) { |
3439 | 3439 | ||
3440 | wait_event_timeout(thread->wqueue, | 3440 | /* We need to wait INTERRUPTIBLE so that |
3441 | test_bit(THREAD_WAKEUP, &thread->flags) | 3441 | * we don't add to the load-average. |
3442 | || kthread_should_stop(), | 3442 | * That means we need to be sure no signals are |
3443 | thread->timeout); | 3443 | * pending |
3444 | */ | ||
3445 | if (signal_pending(current)) | ||
3446 | flush_signals(current); | ||
3447 | |||
3448 | wait_event_interruptible_timeout | ||
3449 | (thread->wqueue, | ||
3450 | test_bit(THREAD_WAKEUP, &thread->flags) | ||
3451 | || kthread_should_stop(), | ||
3452 | thread->timeout); | ||
3444 | try_to_freeze(); | 3453 | try_to_freeze(); |
3445 | 3454 | ||
3446 | clear_bit(THREAD_WAKEUP, &thread->flags); | 3455 | clear_bit(THREAD_WAKEUP, &thread->flags); |
@@ -3837,11 +3846,20 @@ static int is_mddev_idle(mddev_t *mddev) | |||
3837 | curr_events = disk_stat_read(disk, sectors[0]) + | 3846 | curr_events = disk_stat_read(disk, sectors[0]) + |
3838 | disk_stat_read(disk, sectors[1]) - | 3847 | disk_stat_read(disk, sectors[1]) - |
3839 | atomic_read(&disk->sync_io); | 3848 | atomic_read(&disk->sync_io); |
3840 | /* Allow some slack between valud of curr_events and last_events, | 3849 | /* The difference between curr_events and last_events |
3841 | * as there are some uninteresting races. | 3850 | * will be affected by any new non-sync IO (making |
3851 | * curr_events bigger) and any difference in the amount of | ||
3852 | * in-flight syncio (making current_events bigger or smaller) | ||
3853 | * The amount in-flight is currently limited to | ||
3854 | * 32*64K in raid1/10 and 256*PAGE_SIZE in raid5/6 | ||
3855 | * which is at most 4096 sectors. | ||
3856 | * These numbers are fairly fragile and should be made | ||
3857 | * more robust, probably by enforcing the | ||
3858 | * 'window size' that md_do_sync sort-of uses. | ||
3859 | * | ||
3842 | * Note: the following is an unsigned comparison. | 3860 | * Note: the following is an unsigned comparison. |
3843 | */ | 3861 | */ |
3844 | if ((curr_events - rdev->last_events + 32) > 64) { | 3862 | if ((curr_events - rdev->last_events + 4096) > 8192) { |
3845 | rdev->last_events = curr_events; | 3863 | rdev->last_events = curr_events; |
3846 | idle = 0; | 3864 | idle = 0; |
3847 | } | 3865 | } |
@@ -4100,7 +4118,7 @@ static void md_do_sync(mddev_t *mddev) | |||
4100 | if (currspeed > sysctl_speed_limit_min) { | 4118 | if (currspeed > sysctl_speed_limit_min) { |
4101 | if ((currspeed > sysctl_speed_limit_max) || | 4119 | if ((currspeed > sysctl_speed_limit_max) || |
4102 | !is_mddev_idle(mddev)) { | 4120 | !is_mddev_idle(mddev)) { |
4103 | msleep(250); | 4121 | msleep(500); |
4104 | goto repeat; | 4122 | goto repeat; |
4105 | } | 4123 | } |
4106 | } | 4124 | } |
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c index 4b71fd6f7aed..7972c73bc14e 100644 --- a/drivers/media/common/ir-common.c +++ b/drivers/media/common/ir-common.c | |||
@@ -126,6 +126,66 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { | |||
126 | }; | 126 | }; |
127 | EXPORT_SYMBOL_GPL(ir_codes_winfast); | 127 | EXPORT_SYMBOL_GPL(ir_codes_winfast); |
128 | 128 | ||
129 | IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { | ||
130 | [ 0x59 ] = KEY_MUTE, | ||
131 | [ 0x4a ] = KEY_POWER, | ||
132 | |||
133 | [ 0x18 ] = KEY_TEXT, | ||
134 | [ 0x26 ] = KEY_TV, | ||
135 | [ 0x3d ] = KEY_PRINT, | ||
136 | |||
137 | [ 0x48 ] = KEY_RED, | ||
138 | [ 0x04 ] = KEY_GREEN, | ||
139 | [ 0x11 ] = KEY_YELLOW, | ||
140 | [ 0x00 ] = KEY_BLUE, | ||
141 | |||
142 | [ 0x2d ] = KEY_VOLUMEUP, | ||
143 | [ 0x1e ] = KEY_VOLUMEDOWN, | ||
144 | |||
145 | [ 0x49 ] = KEY_MENU, | ||
146 | |||
147 | [ 0x16 ] = KEY_CHANNELUP, | ||
148 | [ 0x17 ] = KEY_CHANNELDOWN, | ||
149 | |||
150 | [ 0x20 ] = KEY_UP, | ||
151 | [ 0x21 ] = KEY_DOWN, | ||
152 | [ 0x22 ] = KEY_LEFT, | ||
153 | [ 0x23 ] = KEY_RIGHT, | ||
154 | [ 0x0d ] = KEY_SELECT, | ||
155 | |||
156 | |||
157 | |||
158 | [ 0x08 ] = KEY_BACK, | ||
159 | [ 0x07 ] = KEY_REFRESH, | ||
160 | |||
161 | [ 0x2f ] = KEY_ZOOM, | ||
162 | [ 0x29 ] = KEY_RECORD, | ||
163 | |||
164 | [ 0x4b ] = KEY_PAUSE, | ||
165 | [ 0x4d ] = KEY_REWIND, | ||
166 | [ 0x2e ] = KEY_PLAY, | ||
167 | [ 0x4e ] = KEY_FORWARD, | ||
168 | [ 0x53 ] = KEY_PREVIOUS, | ||
169 | [ 0x4c ] = KEY_STOP, | ||
170 | [ 0x54 ] = KEY_NEXT, | ||
171 | |||
172 | [ 0x69 ] = KEY_KP0, | ||
173 | [ 0x6a ] = KEY_KP1, | ||
174 | [ 0x6b ] = KEY_KP2, | ||
175 | [ 0x6c ] = KEY_KP3, | ||
176 | [ 0x6d ] = KEY_KP4, | ||
177 | [ 0x6e ] = KEY_KP5, | ||
178 | [ 0x6f ] = KEY_KP6, | ||
179 | [ 0x70 ] = KEY_KP7, | ||
180 | [ 0x71 ] = KEY_KP8, | ||
181 | [ 0x72 ] = KEY_KP9, | ||
182 | |||
183 | [ 0x74 ] = KEY_CHANNEL, | ||
184 | [ 0x0a ] = KEY_BACKSPACE, | ||
185 | }; | ||
186 | |||
187 | EXPORT_SYMBOL_GPL(ir_codes_pinnacle); | ||
188 | |||
129 | /* empty keytable, can be used as placeholder for not-yet created keytables */ | 189 | /* empty keytable, can be used as placeholder for not-yet created keytables */ |
130 | IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { | 190 | IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { |
131 | [ 42 ] = KEY_COFFEE, | 191 | [ 42 ] = KEY_COFFEE, |
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index d7417eac2aba..2583a865a58e 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig | |||
@@ -7,6 +7,7 @@ config DVB_B2C2_FLEXCOP | |||
7 | select DVB_NXT2002 | 7 | select DVB_NXT2002 |
8 | select DVB_STV0297 | 8 | select DVB_STV0297 |
9 | select DVB_BCM3510 | 9 | select DVB_BCM3510 |
10 | select DVB_LGDT330X | ||
10 | help | 11 | help |
11 | Support for the digital TV receiver chip made by B2C2 Inc. included in | 12 | Support for the digital TV receiver chip made by B2C2 Inc. included in |
12 | Technisats PCI cards and USB boxes. | 13 | Technisats PCI cards and USB boxes. |
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index a1607e7d6d6b..fb394a0d838c 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c | |||
@@ -276,7 +276,7 @@ static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2) | |||
276 | if (cinergyt2->stream_urb[i]) | 276 | if (cinergyt2->stream_urb[i]) |
277 | usb_free_urb(cinergyt2->stream_urb[i]); | 277 | usb_free_urb(cinergyt2->stream_urb[i]); |
278 | 278 | ||
279 | pci_free_consistent(NULL, STREAM_URB_COUNT*STREAM_BUF_SIZE, | 279 | usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, |
280 | cinergyt2->streambuf, cinergyt2->streambuf_dmahandle); | 280 | cinergyt2->streambuf, cinergyt2->streambuf_dmahandle); |
281 | } | 281 | } |
282 | 282 | ||
@@ -284,9 +284,8 @@ static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2) | |||
284 | { | 284 | { |
285 | int i; | 285 | int i; |
286 | 286 | ||
287 | cinergyt2->streambuf = pci_alloc_consistent(NULL, | 287 | cinergyt2->streambuf = usb_buffer_alloc(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, |
288 | STREAM_URB_COUNT*STREAM_BUF_SIZE, | 288 | SLAB_KERNEL, &cinergyt2->streambuf_dmahandle); |
289 | &cinergyt2->streambuf_dmahandle); | ||
290 | if (!cinergyt2->streambuf) { | 289 | if (!cinergyt2->streambuf) { |
291 | dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n"); | 290 | dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n"); |
292 | return -ENOMEM; | 291 | return -ENOMEM; |
@@ -780,6 +779,8 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) | |||
780 | 779 | ||
781 | input_register_device(cinergyt2->rc_input_dev); | 780 | input_register_device(cinergyt2->rc_input_dev); |
782 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); | 781 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); |
782 | |||
783 | return 0; | ||
783 | } | 784 | } |
784 | 785 | ||
785 | static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) | 786 | static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2) |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 199b01188858..1a3b3c7e5e99 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -333,4 +333,18 @@ config VIDEO_M32R_AR_M64278 | |||
333 | Say Y here to use the Renesas M64278E-800 camera module, | 333 | Say Y here to use the Renesas M64278E-800 camera module, |
334 | which supports VGA(640x480 pixcels) size of images. | 334 | which supports VGA(640x480 pixcels) size of images. |
335 | 335 | ||
336 | config VIDEO_AUDIO_DECODER | ||
337 | tristate "Add support for additional audio chipsets" | ||
338 | depends on VIDEO_DEV && I2C && EXPERIMENTAL | ||
339 | ---help--- | ||
340 | Say Y here to compile drivers for WM8775 and CS53L32A audio | ||
341 | decoders. | ||
342 | |||
343 | config VIDEO_DECODER | ||
344 | tristate "Add support for additional video chipsets" | ||
345 | depends on VIDEO_DEV && I2C && EXPERIMENTAL | ||
346 | ---help--- | ||
347 | Say Y here to compile drivers for SAA7115, SAA7127 and CX25840 | ||
348 | video decoders. | ||
349 | |||
336 | endmenu | 350 | endmenu |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 3ac465992400..82060f9909d8 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -36,10 +36,11 @@ obj-$(CONFIG_VIDEO_CPIA) += cpia.o | |||
36 | obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o | 36 | obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o |
37 | obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o | 37 | obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o |
38 | obj-$(CONFIG_VIDEO_MEYE) += meye.o | 38 | obj-$(CONFIG_VIDEO_MEYE) += meye.o |
39 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ | 39 | obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/ |
40 | obj-$(CONFIG_VIDEO_CX88) += cx88/ | 40 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
41 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | 41 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ |
42 | obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o | 42 | obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o |
43 | obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o | ||
43 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ | 44 | obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ |
44 | obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o | 45 | obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o |
45 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o | 46 | obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o |
@@ -55,4 +56,6 @@ obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | |||
55 | 56 | ||
56 | obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o | 57 | obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o |
57 | 58 | ||
59 | obj-$(CONFIG_VIDEO_DECODER) += saa7115.o cx25840/ saa7127.o | ||
60 | |||
58 | EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core | 61 | EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core |
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 3413bace443a..e31ebb11c468 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c | |||
@@ -2133,7 +2133,10 @@ struct tvcard bttv_tvcards[] = { | |||
2133 | .tuner_addr = ADDR_UNSET, | 2133 | .tuner_addr = ADDR_UNSET, |
2134 | .radio_addr = ADDR_UNSET, | 2134 | .radio_addr = ADDR_UNSET, |
2135 | .has_dvb = 1, | 2135 | .has_dvb = 1, |
2136 | .has_remote = 1, | ||
2137 | .gpiomask = 0x1b, | ||
2136 | .no_gpioirq = 1, | 2138 | .no_gpioirq = 1, |
2139 | .any_irq = 1, | ||
2137 | }, | 2140 | }, |
2138 | [BTTV_BOARD_PV143] = { | 2141 | [BTTV_BOARD_PV143] = { |
2139 | /* Jorge Boncompte - DTI2 <jorge@dti2.net> */ | 2142 | /* Jorge Boncompte - DTI2 <jorge@dti2.net> */ |
@@ -2796,7 +2799,24 @@ struct tvcard bttv_tvcards[] = { | |||
2796 | .tuner_addr = ADDR_UNSET, | 2799 | .tuner_addr = ADDR_UNSET, |
2797 | .radio_addr = ADDR_UNSET, | 2800 | .radio_addr = ADDR_UNSET, |
2798 | }, | 2801 | }, |
2799 | 2802 | /* ---- card 0x8e ---------------------------------- */ | |
2803 | [BTTV_BOARD_SABRENT_TVFM] = { | ||
2804 | .name = "Sabrent TV-FM (bttv version)", | ||
2805 | .video_inputs = 3, | ||
2806 | .audio_inputs = 1, | ||
2807 | .tuner = 0, | ||
2808 | .svhs = 2, | ||
2809 | .gpiomask = 0x108007, | ||
2810 | .muxsel = { 2, 3, 1, 1}, | ||
2811 | .audiomux = { 100000, 100002, 100002, 100000}, | ||
2812 | .no_msp34xx = 1, | ||
2813 | .no_tda9875 = 1, | ||
2814 | .no_tda7432 = 1, | ||
2815 | .pll = PLL_28, | ||
2816 | .tuner_type = TUNER_TNF_5335MF, | ||
2817 | .tuner_addr = ADDR_UNSET, | ||
2818 | .has_radio = 1, | ||
2819 | }, | ||
2800 | }; | 2820 | }; |
2801 | 2821 | ||
2802 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); | 2822 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); |
@@ -3367,6 +3387,8 @@ void __devinit bttv_init_card2(struct bttv *btv) | |||
3367 | btv->has_remote=1; | 3387 | btv->has_remote=1; |
3368 | if (!bttv_tvcards[btv->c.type].no_gpioirq) | 3388 | if (!bttv_tvcards[btv->c.type].no_gpioirq) |
3369 | btv->gpioirq=1; | 3389 | btv->gpioirq=1; |
3390 | if (bttv_tvcards[btv->c.type].any_irq) | ||
3391 | btv->any_irq = 1; | ||
3370 | if (bttv_tvcards[btv->c.type].audio_hook) | 3392 | if (bttv_tvcards[btv->c.type].audio_hook) |
3371 | btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; | 3393 | btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook; |
3372 | 3394 | ||
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 0005741d5514..709099f03bd2 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c | |||
@@ -3667,6 +3667,10 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) | |||
3667 | int handled = 0; | 3667 | int handled = 0; |
3668 | 3668 | ||
3669 | btv=(struct bttv *)dev_id; | 3669 | btv=(struct bttv *)dev_id; |
3670 | |||
3671 | if (btv->any_irq) | ||
3672 | handled = bttv_any_irq(&btv->c); | ||
3673 | |||
3670 | count=0; | 3674 | count=0; |
3671 | while (1) { | 3675 | while (1) { |
3672 | /* get/clear interrupt status bits */ | 3676 | /* get/clear interrupt status bits */ |
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c index 575ce8b8e714..616a5b7e510c 100644 --- a/drivers/media/video/bttv-gpio.c +++ b/drivers/media/video/bttv-gpio.c | |||
@@ -113,6 +113,24 @@ void bttv_gpio_irq(struct bttv_core *core) | |||
113 | } | 113 | } |
114 | } | 114 | } |
115 | 115 | ||
116 | int bttv_any_irq(struct bttv_core *core) | ||
117 | { | ||
118 | struct bttv_sub_driver *drv; | ||
119 | struct bttv_sub_device *dev; | ||
120 | struct list_head *item; | ||
121 | int handled = 0; | ||
122 | |||
123 | list_for_each(item,&core->subs) { | ||
124 | dev = list_entry(item,struct bttv_sub_device,list); | ||
125 | drv = to_bttv_sub_drv(dev->dev.driver); | ||
126 | if (drv && drv->any_irq) { | ||
127 | if (drv->any_irq(dev)) | ||
128 | handled = 1; | ||
129 | } | ||
130 | } | ||
131 | return handled; | ||
132 | } | ||
133 | |||
116 | /* ----------------------------------------------------------------------- */ | 134 | /* ----------------------------------------------------------------------- */ |
117 | /* external: sub-driver register/unregister */ | 135 | /* external: sub-driver register/unregister */ |
118 | 136 | ||
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 124ea41dada4..93298f06e019 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h | |||
@@ -162,6 +162,7 @@ | |||
162 | #define BTTV_BOARD_PV_M4900 0x8b | 162 | #define BTTV_BOARD_PV_M4900 0x8b |
163 | #define BTTV_BOARD_OSPREY440 0x8c | 163 | #define BTTV_BOARD_OSPREY440 0x8c |
164 | #define BTTV_BOARD_ASOUND_SKYEYE 0x8d | 164 | #define BTTV_BOARD_ASOUND_SKYEYE 0x8d |
165 | #define BTTV_BOARD_SABRENT_TVFM 0x8e | ||
165 | 166 | ||
166 | /* i2c address list */ | 167 | /* i2c address list */ |
167 | #define I2C_TSA5522 0xc2 | 168 | #define I2C_TSA5522 0xc2 |
@@ -234,6 +235,7 @@ struct tvcard | |||
234 | unsigned int has_dvb:1; | 235 | unsigned int has_dvb:1; |
235 | unsigned int has_remote:1; | 236 | unsigned int has_remote:1; |
236 | unsigned int no_gpioirq:1; | 237 | unsigned int no_gpioirq:1; |
238 | unsigned int any_irq:1; | ||
237 | 239 | ||
238 | /* other settings */ | 240 | /* other settings */ |
239 | unsigned int pll; | 241 | unsigned int pll; |
@@ -333,6 +335,7 @@ struct bttv_sub_driver { | |||
333 | struct device_driver drv; | 335 | struct device_driver drv; |
334 | char wanted[BUS_ID_SIZE]; | 336 | char wanted[BUS_ID_SIZE]; |
335 | void (*gpio_irq)(struct bttv_sub_device *sub); | 337 | void (*gpio_irq)(struct bttv_sub_device *sub); |
338 | int (*any_irq)(struct bttv_sub_device *sub); | ||
336 | }; | 339 | }; |
337 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) | 340 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) |
338 | 341 | ||
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index 386f546f7d11..3aa9c6e4fc33 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h | |||
@@ -208,6 +208,7 @@ extern struct bus_type bttv_sub_bus_type; | |||
208 | int bttv_sub_add_device(struct bttv_core *core, char *name); | 208 | int bttv_sub_add_device(struct bttv_core *core, char *name); |
209 | int bttv_sub_del_devices(struct bttv_core *core); | 209 | int bttv_sub_del_devices(struct bttv_core *core); |
210 | void bttv_gpio_irq(struct bttv_core *core); | 210 | void bttv_gpio_irq(struct bttv_core *core); |
211 | int bttv_any_irq(struct bttv_core *core); | ||
211 | 212 | ||
212 | 213 | ||
213 | /* ---------------------------------------------------------- */ | 214 | /* ---------------------------------------------------------- */ |
@@ -273,6 +274,7 @@ struct bttv { | |||
273 | struct bttv_pll_info pll; | 274 | struct bttv_pll_info pll; |
274 | int triton1; | 275 | int triton1; |
275 | int gpioirq; | 276 | int gpioirq; |
277 | int any_irq; | ||
276 | int use_i2c_hw; | 278 | int use_i2c_hw; |
277 | 279 | ||
278 | /* old gpio interface */ | 280 | /* old gpio interface */ |
diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile new file mode 100644 index 000000000000..543ebacdc9d7 --- /dev/null +++ b/drivers/media/video/cx25840/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \ | ||
2 | cx25840-vbi.o | ||
3 | |||
4 | obj-$(CONFIG_VIDEO_DECODER) += cx25840.o | ||
5 | |||
6 | EXTRA_CFLAGS += -I$(src)/.. | ||
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c new file mode 100644 index 000000000000..740908f8027d --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-audio.c | |||
@@ -0,0 +1,368 @@ | |||
1 | /* cx25840 audio functions | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version 2 | ||
6 | * of the License, or (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/videodev2.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <media/audiochip.h> | ||
22 | #include <media/v4l2-common.h> | ||
23 | |||
24 | #include "cx25840.h" | ||
25 | |||
26 | inline static int set_audclk_freq(struct i2c_client *client, | ||
27 | enum v4l2_audio_clock_freq freq) | ||
28 | { | ||
29 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
30 | |||
31 | /* assert soft reset */ | ||
32 | cx25840_and_or(client, 0x810, ~0x1, 0x01); | ||
33 | |||
34 | /* common for all inputs and rates */ | ||
35 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ | ||
36 | cx25840_write(client, 0x127, 0x50); | ||
37 | |||
38 | switch (state->audio_input) { | ||
39 | case AUDIO_TUNER: | ||
40 | switch (freq) { | ||
41 | case V4L2_AUDCLK_32_KHZ: | ||
42 | /* VID_PLL and AUX_PLL */ | ||
43 | cx25840_write4(client, 0x108, 0x0f040610); | ||
44 | |||
45 | /* AUX_PLL_FRAC */ | ||
46 | cx25840_write4(client, 0x110, 0xee39bb01); | ||
47 | |||
48 | /* src3/4/6_ctl = 0x0801f77f */ | ||
49 | cx25840_write4(client, 0x900, 0x7ff70108); | ||
50 | cx25840_write4(client, 0x904, 0x7ff70108); | ||
51 | cx25840_write4(client, 0x90c, 0x7ff70108); | ||
52 | break; | ||
53 | |||
54 | case V4L2_AUDCLK_441_KHZ: | ||
55 | /* VID_PLL and AUX_PLL */ | ||
56 | cx25840_write4(client, 0x108, 0x0f040910); | ||
57 | |||
58 | /* AUX_PLL_FRAC */ | ||
59 | cx25840_write4(client, 0x110, 0xd66bec00); | ||
60 | |||
61 | /* src3/4/6_ctl = 0x08016d59 */ | ||
62 | cx25840_write4(client, 0x900, 0x596d0108); | ||
63 | cx25840_write4(client, 0x904, 0x596d0108); | ||
64 | cx25840_write4(client, 0x90c, 0x596d0108); | ||
65 | break; | ||
66 | |||
67 | case V4L2_AUDCLK_48_KHZ: | ||
68 | /* VID_PLL and AUX_PLL */ | ||
69 | cx25840_write4(client, 0x108, 0x0f040a10); | ||
70 | |||
71 | /* AUX_PLL_FRAC */ | ||
72 | cx25840_write4(client, 0x110, 0xe5d69800); | ||
73 | |||
74 | /* src3/4/6_ctl = 0x08014faa */ | ||
75 | cx25840_write4(client, 0x900, 0xaa4f0108); | ||
76 | cx25840_write4(client, 0x904, 0xaa4f0108); | ||
77 | cx25840_write4(client, 0x90c, 0xaa4f0108); | ||
78 | break; | ||
79 | } | ||
80 | break; | ||
81 | |||
82 | case AUDIO_EXTERN_1: | ||
83 | case AUDIO_EXTERN_2: | ||
84 | case AUDIO_INTERN: | ||
85 | case AUDIO_RADIO: | ||
86 | switch (freq) { | ||
87 | case V4L2_AUDCLK_32_KHZ: | ||
88 | /* VID_PLL and AUX_PLL */ | ||
89 | cx25840_write4(client, 0x108, 0x0f04081e); | ||
90 | |||
91 | /* AUX_PLL_FRAC */ | ||
92 | cx25840_write4(client, 0x110, 0x69082a01); | ||
93 | |||
94 | /* src1_ctl = 0x08010000 */ | ||
95 | cx25840_write4(client, 0x8f8, 0x00000108); | ||
96 | |||
97 | /* src3/4/6_ctl = 0x08020000 */ | ||
98 | cx25840_write4(client, 0x900, 0x00000208); | ||
99 | cx25840_write4(client, 0x904, 0x00000208); | ||
100 | cx25840_write4(client, 0x90c, 0x00000208); | ||
101 | |||
102 | /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */ | ||
103 | cx25840_write(client, 0x127, 0x54); | ||
104 | break; | ||
105 | |||
106 | case V4L2_AUDCLK_441_KHZ: | ||
107 | /* VID_PLL and AUX_PLL */ | ||
108 | cx25840_write4(client, 0x108, 0x0f040918); | ||
109 | |||
110 | /* AUX_PLL_FRAC */ | ||
111 | cx25840_write4(client, 0x110, 0xd66bec00); | ||
112 | |||
113 | /* src1_ctl = 0x08010000 */ | ||
114 | cx25840_write4(client, 0x8f8, 0xcd600108); | ||
115 | |||
116 | /* src3/4/6_ctl = 0x08020000 */ | ||
117 | cx25840_write4(client, 0x900, 0x85730108); | ||
118 | cx25840_write4(client, 0x904, 0x85730108); | ||
119 | cx25840_write4(client, 0x90c, 0x85730108); | ||
120 | break; | ||
121 | |||
122 | case V4L2_AUDCLK_48_KHZ: | ||
123 | /* VID_PLL and AUX_PLL */ | ||
124 | cx25840_write4(client, 0x108, 0x0f040a18); | ||
125 | |||
126 | /* AUX_PLL_FRAC */ | ||
127 | cx25840_write4(client, 0x110, 0xe5d69800); | ||
128 | |||
129 | /* src1_ctl = 0x08010000 */ | ||
130 | cx25840_write4(client, 0x8f8, 0x00800108); | ||
131 | |||
132 | /* src3/4/6_ctl = 0x08020000 */ | ||
133 | cx25840_write4(client, 0x900, 0x55550108); | ||
134 | cx25840_write4(client, 0x904, 0x55550108); | ||
135 | cx25840_write4(client, 0x90c, 0x55550108); | ||
136 | break; | ||
137 | } | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | /* deassert soft reset */ | ||
142 | cx25840_and_or(client, 0x810, ~0x1, 0x00); | ||
143 | |||
144 | state->audclk_freq = freq; | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int set_input(struct i2c_client *client, int audio_input) | ||
150 | { | ||
151 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
152 | |||
153 | cx25840_dbg("set audio input (%d)\n", audio_input); | ||
154 | |||
155 | /* stop microcontroller */ | ||
156 | cx25840_and_or(client, 0x803, ~0x10, 0); | ||
157 | |||
158 | /* Mute everything to prevent the PFFT! */ | ||
159 | cx25840_write(client, 0x8d3, 0x1f); | ||
160 | |||
161 | switch (audio_input) { | ||
162 | case AUDIO_TUNER: | ||
163 | /* Set Path1 to Analog Demod Main Channel */ | ||
164 | cx25840_write4(client, 0x8d0, 0x7038061f); | ||
165 | |||
166 | /* When the microcontroller detects the | ||
167 | * audio format, it will unmute the lines */ | ||
168 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
169 | break; | ||
170 | |||
171 | case AUDIO_EXTERN_1: | ||
172 | case AUDIO_EXTERN_2: | ||
173 | case AUDIO_INTERN: | ||
174 | case AUDIO_RADIO: | ||
175 | /* Set Path1 to Serial Audio Input */ | ||
176 | cx25840_write4(client, 0x8d0, 0x12100101); | ||
177 | |||
178 | /* The microcontroller should not be started for the | ||
179 | * non-tuner inputs: autodetection is specific for | ||
180 | * TV audio. */ | ||
181 | break; | ||
182 | |||
183 | default: | ||
184 | cx25840_dbg("Invalid audio input selection %d\n", audio_input); | ||
185 | return -EINVAL; | ||
186 | } | ||
187 | |||
188 | state->audio_input = audio_input; | ||
189 | |||
190 | return set_audclk_freq(client, state->audclk_freq); | ||
191 | } | ||
192 | |||
193 | inline static int get_volume(struct i2c_client *client) | ||
194 | { | ||
195 | /* Volume runs +18dB to -96dB in 1/2dB steps | ||
196 | * change to fit the msp3400 -114dB to +12dB range */ | ||
197 | |||
198 | /* check PATH1_VOLUME */ | ||
199 | int vol = 228 - cx25840_read(client, 0x8d4); | ||
200 | vol = (vol / 2) + 23; | ||
201 | return vol << 9; | ||
202 | } | ||
203 | |||
204 | inline static void set_volume(struct i2c_client *client, int volume) | ||
205 | { | ||
206 | /* First convert the volume to msp3400 values (0-127) */ | ||
207 | int vol = volume >> 9; | ||
208 | /* now scale it up to cx25840 values | ||
209 | * -114dB to -96dB maps to 0 | ||
210 | * this should be 19, but in my testing that was 4dB too loud */ | ||
211 | if (vol <= 23) { | ||
212 | vol = 0; | ||
213 | } else { | ||
214 | vol -= 23; | ||
215 | } | ||
216 | |||
217 | /* PATH1_VOLUME */ | ||
218 | cx25840_write(client, 0x8d4, 228 - (vol * 2)); | ||
219 | } | ||
220 | |||
221 | inline static int get_bass(struct i2c_client *client) | ||
222 | { | ||
223 | /* bass is 49 steps +12dB to -12dB */ | ||
224 | |||
225 | /* check PATH1_EQ_BASS_VOL */ | ||
226 | int bass = cx25840_read(client, 0x8d9) & 0x3f; | ||
227 | bass = (((48 - bass) * 0xffff) + 47) / 48; | ||
228 | return bass; | ||
229 | } | ||
230 | |||
231 | inline static void set_bass(struct i2c_client *client, int bass) | ||
232 | { | ||
233 | /* PATH1_EQ_BASS_VOL */ | ||
234 | cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff)); | ||
235 | } | ||
236 | |||
237 | inline static int get_treble(struct i2c_client *client) | ||
238 | { | ||
239 | /* treble is 49 steps +12dB to -12dB */ | ||
240 | |||
241 | /* check PATH1_EQ_TREBLE_VOL */ | ||
242 | int treble = cx25840_read(client, 0x8db) & 0x3f; | ||
243 | treble = (((48 - treble) * 0xffff) + 47) / 48; | ||
244 | return treble; | ||
245 | } | ||
246 | |||
247 | inline static void set_treble(struct i2c_client *client, int treble) | ||
248 | { | ||
249 | /* PATH1_EQ_TREBLE_VOL */ | ||
250 | cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff)); | ||
251 | } | ||
252 | |||
253 | inline static int get_balance(struct i2c_client *client) | ||
254 | { | ||
255 | /* balance is 7 bit, 0 to -96dB */ | ||
256 | |||
257 | /* check PATH1_BAL_LEVEL */ | ||
258 | int balance = cx25840_read(client, 0x8d5) & 0x7f; | ||
259 | /* check PATH1_BAL_LEFT */ | ||
260 | if ((cx25840_read(client, 0x8d5) & 0x80) == 0) | ||
261 | balance = 0x80 - balance; | ||
262 | else | ||
263 | balance = 0x80 + balance; | ||
264 | return balance << 8; | ||
265 | } | ||
266 | |||
267 | inline static void set_balance(struct i2c_client *client, int balance) | ||
268 | { | ||
269 | int bal = balance >> 8; | ||
270 | if (bal > 0x80) { | ||
271 | /* PATH1_BAL_LEFT */ | ||
272 | cx25840_and_or(client, 0x8d5, 0x7f, 0x80); | ||
273 | /* PATH1_BAL_LEVEL */ | ||
274 | cx25840_and_or(client, 0x8d5, ~0x7f, bal & 0x7f); | ||
275 | } else { | ||
276 | /* PATH1_BAL_LEFT */ | ||
277 | cx25840_and_or(client, 0x8d5, 0x7f, 0x00); | ||
278 | /* PATH1_BAL_LEVEL */ | ||
279 | cx25840_and_or(client, 0x8d5, ~0x7f, 0x80 - bal); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | inline static int get_mute(struct i2c_client *client) | ||
284 | { | ||
285 | /* check SRC1_MUTE_EN */ | ||
286 | return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0; | ||
287 | } | ||
288 | |||
289 | inline static void set_mute(struct i2c_client *client, int mute) | ||
290 | { | ||
291 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
292 | |||
293 | if (state->audio_input == AUDIO_TUNER) { | ||
294 | /* Must turn off microcontroller in order to mute sound. | ||
295 | * Not sure if this is the best method, but it does work. | ||
296 | * If the microcontroller is running, then it will undo any | ||
297 | * changes to the mute register. */ | ||
298 | if (mute) { | ||
299 | /* disable microcontroller */ | ||
300 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
301 | cx25840_write(client, 0x8d3, 0x1f); | ||
302 | } else { | ||
303 | /* enable microcontroller */ | ||
304 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
305 | } | ||
306 | } else { | ||
307 | /* SRC1_MUTE_EN */ | ||
308 | cx25840_and_or(client, 0x8d3, ~0x2, mute ? 0x02 : 0x00); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg) | ||
313 | { | ||
314 | struct v4l2_control *ctrl = arg; | ||
315 | |||
316 | switch (cmd) { | ||
317 | case AUDC_SET_INPUT: | ||
318 | return set_input(client, *(int *)arg); | ||
319 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
320 | return set_audclk_freq(client, *(enum v4l2_audio_clock_freq *)arg); | ||
321 | case VIDIOC_G_CTRL: | ||
322 | switch (ctrl->id) { | ||
323 | case V4L2_CID_AUDIO_VOLUME: | ||
324 | ctrl->value = get_volume(client); | ||
325 | break; | ||
326 | case V4L2_CID_AUDIO_BASS: | ||
327 | ctrl->value = get_bass(client); | ||
328 | break; | ||
329 | case V4L2_CID_AUDIO_TREBLE: | ||
330 | ctrl->value = get_treble(client); | ||
331 | break; | ||
332 | case V4L2_CID_AUDIO_BALANCE: | ||
333 | ctrl->value = get_balance(client); | ||
334 | break; | ||
335 | case V4L2_CID_AUDIO_MUTE: | ||
336 | ctrl->value = get_mute(client); | ||
337 | break; | ||
338 | default: | ||
339 | return -EINVAL; | ||
340 | } | ||
341 | break; | ||
342 | case VIDIOC_S_CTRL: | ||
343 | switch (ctrl->id) { | ||
344 | case V4L2_CID_AUDIO_VOLUME: | ||
345 | set_volume(client, ctrl->value); | ||
346 | break; | ||
347 | case V4L2_CID_AUDIO_BASS: | ||
348 | set_bass(client, ctrl->value); | ||
349 | break; | ||
350 | case V4L2_CID_AUDIO_TREBLE: | ||
351 | set_treble(client, ctrl->value); | ||
352 | break; | ||
353 | case V4L2_CID_AUDIO_BALANCE: | ||
354 | set_balance(client, ctrl->value); | ||
355 | break; | ||
356 | case V4L2_CID_AUDIO_MUTE: | ||
357 | set_mute(client, ctrl->value); | ||
358 | break; | ||
359 | default: | ||
360 | return -EINVAL; | ||
361 | } | ||
362 | break; | ||
363 | default: | ||
364 | return -EINVAL; | ||
365 | } | ||
366 | |||
367 | return 0; | ||
368 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c new file mode 100644 index 000000000000..f6afeec499c5 --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -0,0 +1,1020 @@ | |||
1 | /* cx25840 - Conexant CX25840 audio/video decoder driver | ||
2 | * | ||
3 | * Copyright (C) 2004 Ulf Eklund | ||
4 | * | ||
5 | * Based on the saa7115 driver and on the first verison of Chris Kennedy's | ||
6 | * cx25840 driver. | ||
7 | * | ||
8 | * Changes by Tyler Trafford <tatrafford@comcast.net> | ||
9 | * - cleanup/rewrite for V4L2 API (2005) | ||
10 | * | ||
11 | * VBI support by Hans Verkuil <hverkuil@xs4all.nl>. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/videodev2.h> | ||
33 | #include <linux/i2c.h> | ||
34 | #include <media/audiochip.h> | ||
35 | #include <media/v4l2-common.h> | ||
36 | |||
37 | #include "cx25840.h" | ||
38 | |||
39 | MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver"); | ||
40 | MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; | ||
44 | |||
45 | |||
46 | int cx25840_debug = 0; | ||
47 | |||
48 | module_param(cx25840_debug, bool, 0644); | ||
49 | |||
50 | MODULE_PARM_DESC(cx25840_debug, "Debugging messages [0=Off (default) 1=On]"); | ||
51 | |||
52 | I2C_CLIENT_INSMOD; | ||
53 | |||
54 | /* ----------------------------------------------------------------------- */ | ||
55 | |||
56 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value) | ||
57 | { | ||
58 | u8 buffer[3]; | ||
59 | buffer[0] = addr >> 8; | ||
60 | buffer[1] = addr & 0xff; | ||
61 | buffer[2] = value; | ||
62 | return i2c_master_send(client, buffer, 3); | ||
63 | } | ||
64 | |||
65 | int cx25840_write4(struct i2c_client *client, u16 addr, u32 value) | ||
66 | { | ||
67 | u8 buffer[6]; | ||
68 | buffer[0] = addr >> 8; | ||
69 | buffer[1] = addr & 0xff; | ||
70 | buffer[2] = value >> 24; | ||
71 | buffer[3] = (value >> 16) & 0xff; | ||
72 | buffer[4] = (value >> 8) & 0xff; | ||
73 | buffer[5] = value & 0xff; | ||
74 | return i2c_master_send(client, buffer, 6); | ||
75 | } | ||
76 | |||
77 | u8 cx25840_read(struct i2c_client * client, u16 addr) | ||
78 | { | ||
79 | u8 buffer[2]; | ||
80 | buffer[0] = addr >> 8; | ||
81 | buffer[1] = addr & 0xff; | ||
82 | |||
83 | if (i2c_master_send(client, buffer, 2) < 2) | ||
84 | return 0; | ||
85 | |||
86 | if (i2c_master_recv(client, buffer, 1) < 1) | ||
87 | return 0; | ||
88 | |||
89 | return buffer[0]; | ||
90 | } | ||
91 | |||
92 | u32 cx25840_read4(struct i2c_client * client, u16 addr) | ||
93 | { | ||
94 | u8 buffer[4]; | ||
95 | buffer[0] = addr >> 8; | ||
96 | buffer[1] = addr & 0xff; | ||
97 | |||
98 | if (i2c_master_send(client, buffer, 2) < 2) | ||
99 | return 0; | ||
100 | |||
101 | if (i2c_master_recv(client, buffer, 4) < 4) | ||
102 | return 0; | ||
103 | |||
104 | return (buffer[0] << 24) | (buffer[1] << 16) | | ||
105 | (buffer[2] << 8) | buffer[3]; | ||
106 | } | ||
107 | |||
108 | int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask, | ||
109 | u8 or_value) | ||
110 | { | ||
111 | return cx25840_write(client, addr, | ||
112 | (cx25840_read(client, addr) & and_mask) | | ||
113 | or_value); | ||
114 | } | ||
115 | |||
116 | /* ----------------------------------------------------------------------- */ | ||
117 | |||
118 | static int set_input(struct i2c_client *, enum cx25840_input); | ||
119 | static void input_change(struct i2c_client *); | ||
120 | static void log_status(struct i2c_client *client); | ||
121 | |||
122 | /* ----------------------------------------------------------------------- */ | ||
123 | |||
124 | static inline void init_dll1(struct i2c_client *client) | ||
125 | { | ||
126 | /* This is the Hauppauge sequence used to | ||
127 | * initialize the Delay Lock Loop 1 (ADC DLL). */ | ||
128 | cx25840_write(client, 0x159, 0x23); | ||
129 | cx25840_write(client, 0x15a, 0x87); | ||
130 | cx25840_write(client, 0x15b, 0x06); | ||
131 | cx25840_write(client, 0x159, 0xe1); | ||
132 | cx25840_write(client, 0x15a, 0x86); | ||
133 | cx25840_write(client, 0x159, 0xe0); | ||
134 | cx25840_write(client, 0x159, 0xe1); | ||
135 | cx25840_write(client, 0x15b, 0x10); | ||
136 | } | ||
137 | |||
138 | static inline void init_dll2(struct i2c_client *client) | ||
139 | { | ||
140 | /* This is the Hauppauge sequence used to | ||
141 | * initialize the Delay Lock Loop 2 (ADC DLL). */ | ||
142 | cx25840_write(client, 0x15d, 0xe3); | ||
143 | cx25840_write(client, 0x15e, 0x86); | ||
144 | cx25840_write(client, 0x15f, 0x06); | ||
145 | cx25840_write(client, 0x15d, 0xe1); | ||
146 | cx25840_write(client, 0x15d, 0xe0); | ||
147 | cx25840_write(client, 0x15d, 0xe1); | ||
148 | } | ||
149 | |||
150 | static void cx25840_initialize(struct i2c_client *client, int loadfw) | ||
151 | { | ||
152 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
153 | |||
154 | /* datasheet startup in numbered steps, refer to page 3-77 */ | ||
155 | /* 2. */ | ||
156 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
157 | /* The default of this register should be 4, but I get 0 instead. | ||
158 | * Set this register to 4 manually. */ | ||
159 | cx25840_write(client, 0x000, 0x04); | ||
160 | /* 3. */ | ||
161 | init_dll1(client); | ||
162 | init_dll2(client); | ||
163 | cx25840_write(client, 0x136, 0x0a); | ||
164 | /* 4. */ | ||
165 | cx25840_write(client, 0x13c, 0x01); | ||
166 | cx25840_write(client, 0x13c, 0x00); | ||
167 | /* 5. */ | ||
168 | if (loadfw) | ||
169 | cx25840_loadfw(client); | ||
170 | /* 6. */ | ||
171 | cx25840_write(client, 0x115, 0x8c); | ||
172 | cx25840_write(client, 0x116, 0x07); | ||
173 | cx25840_write(client, 0x118, 0x02); | ||
174 | /* 7. */ | ||
175 | cx25840_write(client, 0x4a5, 0x80); | ||
176 | cx25840_write(client, 0x4a5, 0x00); | ||
177 | cx25840_write(client, 0x402, 0x00); | ||
178 | /* 8. */ | ||
179 | cx25840_write(client, 0x401, 0x18); | ||
180 | cx25840_write(client, 0x4a2, 0x10); | ||
181 | cx25840_write(client, 0x402, 0x04); | ||
182 | /* 10. */ | ||
183 | cx25840_write(client, 0x8d3, 0x1f); | ||
184 | cx25840_write(client, 0x8e3, 0x03); | ||
185 | |||
186 | cx25840_vbi_setup(client); | ||
187 | |||
188 | /* trial and error says these are needed to get audio */ | ||
189 | cx25840_write(client, 0x914, 0xa0); | ||
190 | cx25840_write(client, 0x918, 0xa0); | ||
191 | cx25840_write(client, 0x919, 0x01); | ||
192 | |||
193 | /* stereo prefered */ | ||
194 | cx25840_write(client, 0x809, 0x04); | ||
195 | /* AC97 shift */ | ||
196 | cx25840_write(client, 0x8cf, 0x0f); | ||
197 | |||
198 | /* (re)set video input */ | ||
199 | set_input(client, state->input); | ||
200 | /* (re)set audio input */ | ||
201 | cx25840_audio(client, AUDC_SET_INPUT, &state->audio_input); | ||
202 | |||
203 | /* start microcontroller */ | ||
204 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
205 | } | ||
206 | |||
207 | /* ----------------------------------------------------------------------- */ | ||
208 | |||
209 | static void input_change(struct i2c_client *client) | ||
210 | { | ||
211 | v4l2_std_id std = cx25840_get_v4lstd(client); | ||
212 | |||
213 | if (std & V4L2_STD_PAL) { | ||
214 | /* Follow tuner change procedure for PAL */ | ||
215 | cx25840_write(client, 0x808, 0xff); | ||
216 | cx25840_write(client, 0x80b, 0x10); | ||
217 | } else if (std & V4L2_STD_SECAM) { | ||
218 | /* Select autodetect for SECAM */ | ||
219 | cx25840_write(client, 0x808, 0xff); | ||
220 | cx25840_write(client, 0x80b, 0x10); | ||
221 | } else if (std & V4L2_STD_NTSC) { | ||
222 | /* NTSC */ | ||
223 | cx25840_write(client, 0x808, 0xf6); | ||
224 | cx25840_write(client, 0x80b, 0x00); | ||
225 | } | ||
226 | |||
227 | if (cx25840_read(client, 0x803) & 0x10) { | ||
228 | /* restart audio decoder microcontroller */ | ||
229 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
230 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | static int set_input(struct i2c_client *client, enum cx25840_input input) | ||
235 | { | ||
236 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
237 | |||
238 | cx25840_dbg("decoder set input (%d)\n", input); | ||
239 | |||
240 | switch (input) { | ||
241 | case CX25840_TUNER: | ||
242 | cx25840_dbg("now setting Tuner input\n"); | ||
243 | |||
244 | if (state->cardtype == CARDTYPE_PVR150) { | ||
245 | /* CH_SEL_ADC2=1 */ | ||
246 | cx25840_and_or(client, 0x102, ~0x2, 0x02); | ||
247 | } | ||
248 | |||
249 | /* Video Input Control */ | ||
250 | if (state->cardtype == CARDTYPE_PG600) { | ||
251 | cx25840_write(client, 0x103, 0x11); | ||
252 | } else { | ||
253 | cx25840_write(client, 0x103, 0x46); | ||
254 | } | ||
255 | |||
256 | /* INPUT_MODE=0 */ | ||
257 | cx25840_and_or(client, 0x401, ~0x6, 0x00); | ||
258 | break; | ||
259 | |||
260 | case CX25840_COMPOSITE0: | ||
261 | case CX25840_COMPOSITE1: | ||
262 | cx25840_dbg("now setting Composite input\n"); | ||
263 | |||
264 | /* Video Input Control */ | ||
265 | if (state->cardtype == CARDTYPE_PG600) { | ||
266 | cx25840_write(client, 0x103, 0x00); | ||
267 | } else { | ||
268 | cx25840_write(client, 0x103, 0x02); | ||
269 | } | ||
270 | |||
271 | /* INPUT_MODE=0 */ | ||
272 | cx25840_and_or(client, 0x401, ~0x6, 0x00); | ||
273 | break; | ||
274 | |||
275 | case CX25840_SVIDEO0: | ||
276 | case CX25840_SVIDEO1: | ||
277 | cx25840_dbg("now setting S-Video input\n"); | ||
278 | |||
279 | /* CH_SEL_ADC2=0 */ | ||
280 | cx25840_and_or(client, 0x102, ~0x2, 0x00); | ||
281 | |||
282 | /* Video Input Control */ | ||
283 | if (state->cardtype == CARDTYPE_PG600) { | ||
284 | cx25840_write(client, 0x103, 0x02); | ||
285 | } else { | ||
286 | cx25840_write(client, 0x103, 0x10); | ||
287 | } | ||
288 | |||
289 | /* INPUT_MODE=1 */ | ||
290 | cx25840_and_or(client, 0x401, ~0x6, 0x02); | ||
291 | break; | ||
292 | |||
293 | default: | ||
294 | cx25840_err("%d is not a valid input!\n", input); | ||
295 | return -EINVAL; | ||
296 | } | ||
297 | |||
298 | state->input = input; | ||
299 | input_change(client); | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | /* ----------------------------------------------------------------------- */ | ||
304 | |||
305 | static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) | ||
306 | { | ||
307 | u8 fmt; | ||
308 | |||
309 | switch (std) { | ||
310 | /* zero is autodetect */ | ||
311 | case 0: fmt = 0x0; break; | ||
312 | /* default ntsc to ntsc-m */ | ||
313 | case V4L2_STD_NTSC: | ||
314 | case V4L2_STD_NTSC_M: fmt = 0x1; break; | ||
315 | case V4L2_STD_NTSC_M_JP: fmt = 0x2; break; | ||
316 | case V4L2_STD_NTSC_443: fmt = 0x3; break; | ||
317 | case V4L2_STD_PAL: fmt = 0x4; break; | ||
318 | case V4L2_STD_PAL_M: fmt = 0x5; break; | ||
319 | case V4L2_STD_PAL_N: fmt = 0x6; break; | ||
320 | case V4L2_STD_PAL_Nc: fmt = 0x7; break; | ||
321 | case V4L2_STD_PAL_60: fmt = 0x8; break; | ||
322 | case V4L2_STD_SECAM: fmt = 0xc; break; | ||
323 | default: | ||
324 | return -ERANGE; | ||
325 | } | ||
326 | |||
327 | cx25840_and_or(client, 0x400, ~0xf, fmt); | ||
328 | cx25840_vbi_setup(client); | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) | ||
333 | { | ||
334 | /* check VID_FMT_SEL first */ | ||
335 | u8 fmt = cx25840_read(client, 0x400) & 0xf; | ||
336 | |||
337 | if (!fmt) { | ||
338 | /* check AFD_FMT_STAT if set to autodetect */ | ||
339 | fmt = cx25840_read(client, 0x40d) & 0xf; | ||
340 | } | ||
341 | |||
342 | switch (fmt) { | ||
343 | case 0x1: return V4L2_STD_NTSC_M; | ||
344 | case 0x2: return V4L2_STD_NTSC_M_JP; | ||
345 | case 0x3: return V4L2_STD_NTSC_443; | ||
346 | case 0x4: return V4L2_STD_PAL; | ||
347 | case 0x5: return V4L2_STD_PAL_M; | ||
348 | case 0x6: return V4L2_STD_PAL_N; | ||
349 | case 0x7: return V4L2_STD_PAL_Nc; | ||
350 | case 0x8: return V4L2_STD_PAL_60; | ||
351 | case 0xc: return V4L2_STD_SECAM; | ||
352 | default: return V4L2_STD_UNKNOWN; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | /* ----------------------------------------------------------------------- */ | ||
357 | |||
358 | static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
359 | { | ||
360 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
361 | |||
362 | switch (ctrl->id) { | ||
363 | case CX25840_CID_CARDTYPE: | ||
364 | switch (ctrl->value) { | ||
365 | case CARDTYPE_PVR150: | ||
366 | case CARDTYPE_PG600: | ||
367 | state->cardtype = ctrl->value; | ||
368 | break; | ||
369 | default: | ||
370 | return -ERANGE; | ||
371 | } | ||
372 | |||
373 | set_input(client, state->input); | ||
374 | break; | ||
375 | |||
376 | case V4L2_CID_BRIGHTNESS: | ||
377 | if (ctrl->value < 0 || ctrl->value > 255) { | ||
378 | cx25840_err("invalid brightness setting %d\n", | ||
379 | ctrl->value); | ||
380 | return -ERANGE; | ||
381 | } | ||
382 | |||
383 | cx25840_write(client, 0x414, ctrl->value - 128); | ||
384 | break; | ||
385 | |||
386 | case V4L2_CID_CONTRAST: | ||
387 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
388 | cx25840_err("invalid contrast setting %d\n", | ||
389 | ctrl->value); | ||
390 | return -ERANGE; | ||
391 | } | ||
392 | |||
393 | cx25840_write(client, 0x415, ctrl->value << 1); | ||
394 | break; | ||
395 | |||
396 | case V4L2_CID_SATURATION: | ||
397 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
398 | cx25840_err("invalid saturation setting %d\n", | ||
399 | ctrl->value); | ||
400 | return -ERANGE; | ||
401 | } | ||
402 | |||
403 | cx25840_write(client, 0x420, ctrl->value << 1); | ||
404 | cx25840_write(client, 0x421, ctrl->value << 1); | ||
405 | break; | ||
406 | |||
407 | case V4L2_CID_HUE: | ||
408 | if (ctrl->value < -127 || ctrl->value > 127) { | ||
409 | cx25840_err("invalid hue setting %d\n", ctrl->value); | ||
410 | return -ERANGE; | ||
411 | } | ||
412 | |||
413 | cx25840_write(client, 0x422, ctrl->value); | ||
414 | break; | ||
415 | |||
416 | case V4L2_CID_AUDIO_VOLUME: | ||
417 | case V4L2_CID_AUDIO_BASS: | ||
418 | case V4L2_CID_AUDIO_TREBLE: | ||
419 | case V4L2_CID_AUDIO_BALANCE: | ||
420 | case V4L2_CID_AUDIO_MUTE: | ||
421 | return cx25840_audio(client, VIDIOC_S_CTRL, ctrl); | ||
422 | } | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
428 | { | ||
429 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
430 | |||
431 | switch (ctrl->id) { | ||
432 | case CX25840_CID_CARDTYPE: | ||
433 | ctrl->value = state->cardtype; | ||
434 | break; | ||
435 | case V4L2_CID_BRIGHTNESS: | ||
436 | ctrl->value = cx25840_read(client, 0x414) + 128; | ||
437 | break; | ||
438 | case V4L2_CID_CONTRAST: | ||
439 | ctrl->value = cx25840_read(client, 0x415) >> 1; | ||
440 | break; | ||
441 | case V4L2_CID_SATURATION: | ||
442 | ctrl->value = cx25840_read(client, 0x420) >> 1; | ||
443 | break; | ||
444 | case V4L2_CID_HUE: | ||
445 | ctrl->value = cx25840_read(client, 0x422); | ||
446 | break; | ||
447 | case V4L2_CID_AUDIO_VOLUME: | ||
448 | case V4L2_CID_AUDIO_BASS: | ||
449 | case V4L2_CID_AUDIO_TREBLE: | ||
450 | case V4L2_CID_AUDIO_BALANCE: | ||
451 | case V4L2_CID_AUDIO_MUTE: | ||
452 | return cx25840_audio(client, VIDIOC_G_CTRL, ctrl); | ||
453 | default: | ||
454 | return -EINVAL; | ||
455 | } | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | /* ----------------------------------------------------------------------- */ | ||
461 | |||
462 | static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
463 | { | ||
464 | switch (fmt->type) { | ||
465 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
466 | return cx25840_vbi(client, VIDIOC_G_FMT, fmt); | ||
467 | default: | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
475 | { | ||
476 | struct v4l2_pix_format *pix; | ||
477 | int HSC, VSC, Vsrc, Hsrc, filter, Vlines; | ||
478 | int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); | ||
479 | |||
480 | switch (fmt->type) { | ||
481 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
482 | pix = &(fmt->fmt.pix); | ||
483 | |||
484 | Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4; | ||
485 | Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4; | ||
486 | |||
487 | Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4; | ||
488 | Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4; | ||
489 | |||
490 | Vlines = pix->height + (is_pal ? 4 : 7); | ||
491 | |||
492 | if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || | ||
493 | (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { | ||
494 | cx25840_err("%dx%d is not a valid size!\n", | ||
495 | pix->width, pix->height); | ||
496 | return -ERANGE; | ||
497 | } | ||
498 | |||
499 | HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20); | ||
500 | VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9)); | ||
501 | VSC &= 0x1fff; | ||
502 | |||
503 | if (pix->width >= 385) | ||
504 | filter = 0; | ||
505 | else if (pix->width > 192) | ||
506 | filter = 1; | ||
507 | else if (pix->width > 96) | ||
508 | filter = 2; | ||
509 | else | ||
510 | filter = 3; | ||
511 | |||
512 | cx25840_dbg("decoder set size %dx%d -> scale %ux%u\n", | ||
513 | pix->width, pix->height, HSC, VSC); | ||
514 | |||
515 | /* HSCALE=HSC */ | ||
516 | cx25840_write(client, 0x418, HSC & 0xff); | ||
517 | cx25840_write(client, 0x419, (HSC >> 8) & 0xff); | ||
518 | cx25840_write(client, 0x41a, HSC >> 16); | ||
519 | /* VSCALE=VSC */ | ||
520 | cx25840_write(client, 0x41c, VSC & 0xff); | ||
521 | cx25840_write(client, 0x41d, VSC >> 8); | ||
522 | /* VS_INTRLACE=1 VFILT=filter */ | ||
523 | cx25840_write(client, 0x41e, 0x8 | filter); | ||
524 | break; | ||
525 | |||
526 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
527 | return cx25840_vbi(client, VIDIOC_S_FMT, fmt); | ||
528 | |||
529 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
530 | return cx25840_vbi(client, VIDIOC_S_FMT, fmt); | ||
531 | |||
532 | default: | ||
533 | return -EINVAL; | ||
534 | } | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | /* ----------------------------------------------------------------------- */ | ||
540 | |||
541 | static int cx25840_command(struct i2c_client *client, unsigned int cmd, | ||
542 | void *arg) | ||
543 | { | ||
544 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
545 | struct v4l2_tuner *vt = arg; | ||
546 | int result = 0; | ||
547 | |||
548 | switch (cmd) { | ||
549 | case 0: | ||
550 | break; | ||
551 | |||
552 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
553 | /* ioctls to allow direct access to the | ||
554 | * cx25840 registers for testing */ | ||
555 | case VIDIOC_INT_G_REGISTER: | ||
556 | { | ||
557 | struct v4l2_register *reg = arg; | ||
558 | |||
559 | if (reg->i2c_id != I2C_DRIVERID_CX25840) | ||
560 | return -EINVAL; | ||
561 | reg->val = cx25840_read(client, reg->reg & 0x0fff); | ||
562 | break; | ||
563 | } | ||
564 | |||
565 | case VIDIOC_INT_S_REGISTER: | ||
566 | { | ||
567 | struct v4l2_register *reg = arg; | ||
568 | |||
569 | if (reg->i2c_id != I2C_DRIVERID_CX25840) | ||
570 | return -EINVAL; | ||
571 | if (!capable(CAP_SYS_ADMIN)) | ||
572 | return -EPERM; | ||
573 | cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); | ||
574 | break; | ||
575 | } | ||
576 | #endif | ||
577 | |||
578 | case VIDIOC_INT_DECODE_VBI_LINE: | ||
579 | return cx25840_vbi(client, cmd, arg); | ||
580 | |||
581 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
582 | case AUDC_SET_INPUT: | ||
583 | result = cx25840_audio(client, cmd, arg); | ||
584 | break; | ||
585 | |||
586 | case VIDIOC_STREAMON: | ||
587 | cx25840_dbg("enable output\n"); | ||
588 | cx25840_write(client, 0x115, 0x8c); | ||
589 | cx25840_write(client, 0x116, 0x07); | ||
590 | break; | ||
591 | |||
592 | case VIDIOC_STREAMOFF: | ||
593 | cx25840_dbg("disable output\n"); | ||
594 | cx25840_write(client, 0x115, 0x00); | ||
595 | cx25840_write(client, 0x116, 0x00); | ||
596 | break; | ||
597 | |||
598 | case VIDIOC_LOG_STATUS: | ||
599 | log_status(client); | ||
600 | break; | ||
601 | |||
602 | case VIDIOC_G_CTRL: | ||
603 | result = get_v4lctrl(client, (struct v4l2_control *)arg); | ||
604 | break; | ||
605 | |||
606 | case VIDIOC_S_CTRL: | ||
607 | result = set_v4lctrl(client, (struct v4l2_control *)arg); | ||
608 | break; | ||
609 | |||
610 | case VIDIOC_G_STD: | ||
611 | *(v4l2_std_id *)arg = cx25840_get_v4lstd(client); | ||
612 | break; | ||
613 | |||
614 | case VIDIOC_S_STD: | ||
615 | result = set_v4lstd(client, *(v4l2_std_id *)arg); | ||
616 | break; | ||
617 | |||
618 | case VIDIOC_G_INPUT: | ||
619 | *(int *)arg = state->input; | ||
620 | break; | ||
621 | |||
622 | case VIDIOC_S_INPUT: | ||
623 | result = set_input(client, *(int *)arg); | ||
624 | break; | ||
625 | |||
626 | case VIDIOC_S_FREQUENCY: | ||
627 | input_change(client); | ||
628 | break; | ||
629 | |||
630 | case VIDIOC_G_TUNER: | ||
631 | { | ||
632 | u8 mode = cx25840_read(client, 0x804); | ||
633 | u8 pref = cx25840_read(client, 0x809) & 0xf; | ||
634 | u8 vpres = cx25840_read(client, 0x80a) & 0x10; | ||
635 | int val = 0; | ||
636 | |||
637 | vt->capability |= | ||
638 | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | | ||
639 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; | ||
640 | |||
641 | vt->signal = vpres ? 0xffff : 0x0; | ||
642 | |||
643 | /* get rxsubchans and audmode */ | ||
644 | if ((mode & 0xf) == 1) | ||
645 | val |= V4L2_TUNER_SUB_STEREO; | ||
646 | else | ||
647 | val |= V4L2_TUNER_SUB_MONO; | ||
648 | |||
649 | if (mode == 2 || mode == 4) | ||
650 | val |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
651 | |||
652 | if (mode & 0x10) | ||
653 | val |= V4L2_TUNER_SUB_SAP; | ||
654 | |||
655 | vt->rxsubchans = val; | ||
656 | |||
657 | switch (pref) { | ||
658 | case 0: | ||
659 | vt->audmode = V4L2_TUNER_MODE_MONO; | ||
660 | break; | ||
661 | case 1: | ||
662 | case 2: | ||
663 | vt->audmode = V4L2_TUNER_MODE_LANG2; | ||
664 | break; | ||
665 | case 4: | ||
666 | default: | ||
667 | vt->audmode = V4L2_TUNER_MODE_STEREO; | ||
668 | } | ||
669 | break; | ||
670 | } | ||
671 | |||
672 | case VIDIOC_S_TUNER: | ||
673 | switch (vt->audmode) { | ||
674 | case V4L2_TUNER_MODE_MONO: | ||
675 | case V4L2_TUNER_MODE_LANG1: | ||
676 | /* Force PREF_MODE to MONO */ | ||
677 | cx25840_and_or(client, 0x809, ~0xf, 0x00); | ||
678 | break; | ||
679 | case V4L2_TUNER_MODE_STEREO: | ||
680 | /* Force PREF_MODE to STEREO */ | ||
681 | cx25840_and_or(client, 0x809, ~0xf, 0x04); | ||
682 | break; | ||
683 | case V4L2_TUNER_MODE_LANG2: | ||
684 | /* Force PREF_MODE to LANG2 */ | ||
685 | cx25840_and_or(client, 0x809, ~0xf, 0x01); | ||
686 | break; | ||
687 | } | ||
688 | break; | ||
689 | |||
690 | case VIDIOC_G_FMT: | ||
691 | result = get_v4lfmt(client, (struct v4l2_format *)arg); | ||
692 | break; | ||
693 | |||
694 | case VIDIOC_S_FMT: | ||
695 | result = set_v4lfmt(client, (struct v4l2_format *)arg); | ||
696 | break; | ||
697 | |||
698 | case VIDIOC_INT_RESET: | ||
699 | cx25840_initialize(client, 0); | ||
700 | break; | ||
701 | |||
702 | case VIDIOC_INT_G_CHIP_IDENT: | ||
703 | *(enum v4l2_chip_ident *)arg = | ||
704 | V4L2_IDENT_CX25840 + ((cx25840_read(client, 0x100) >> 4) & 0xf); | ||
705 | break; | ||
706 | |||
707 | default: | ||
708 | cx25840_err("invalid ioctl %x\n", cmd); | ||
709 | return -EINVAL; | ||
710 | } | ||
711 | |||
712 | return result; | ||
713 | } | ||
714 | |||
715 | /* ----------------------------------------------------------------------- */ | ||
716 | |||
717 | struct i2c_driver i2c_driver_cx25840; | ||
718 | |||
719 | static int cx25840_detect_client(struct i2c_adapter *adapter, int address, | ||
720 | int kind) | ||
721 | { | ||
722 | struct i2c_client *client; | ||
723 | struct cx25840_state *state; | ||
724 | u16 device_id; | ||
725 | |||
726 | /* Check if the adapter supports the needed features | ||
727 | * Not until kernel version 2.6.11 did the bit-algo | ||
728 | * correctly report that it would do an I2C-level xfer */ | ||
729 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) | ||
730 | return 0; | ||
731 | |||
732 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
733 | if (client == 0) | ||
734 | return -ENOMEM; | ||
735 | |||
736 | memset(client, 0, sizeof(struct i2c_client)); | ||
737 | client->addr = address; | ||
738 | client->adapter = adapter; | ||
739 | client->driver = &i2c_driver_cx25840; | ||
740 | client->flags = I2C_CLIENT_ALLOW_USE; | ||
741 | snprintf(client->name, sizeof(client->name) - 1, "cx25840"); | ||
742 | |||
743 | cx25840_dbg("detecting cx25840 client on address 0x%x\n", address << 1); | ||
744 | |||
745 | device_id = cx25840_read(client, 0x101) << 8; | ||
746 | device_id |= cx25840_read(client, 0x100); | ||
747 | |||
748 | /* The high byte of the device ID should be | ||
749 | * 0x84 if chip is present */ | ||
750 | if ((device_id & 0xff00) != 0x8400) { | ||
751 | cx25840_dbg("cx25840 not found\n"); | ||
752 | kfree(client); | ||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | cx25840_info("cx25%3x-2%x found @ 0x%x (%s)\n", | ||
757 | (device_id & 0xfff0) >> 4, | ||
758 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3, | ||
759 | address << 1, adapter->name); | ||
760 | |||
761 | state = kmalloc(sizeof(struct cx25840_state), GFP_KERNEL); | ||
762 | if (state == NULL) { | ||
763 | kfree(client); | ||
764 | return -ENOMEM; | ||
765 | } | ||
766 | |||
767 | i2c_set_clientdata(client, state); | ||
768 | memset(state, 0, sizeof(struct cx25840_state)); | ||
769 | state->input = CX25840_TUNER; | ||
770 | state->audclk_freq = V4L2_AUDCLK_48_KHZ; | ||
771 | state->audio_input = AUDIO_TUNER; | ||
772 | state->cardtype = CARDTYPE_PVR150; | ||
773 | |||
774 | cx25840_initialize(client, 1); | ||
775 | |||
776 | i2c_attach_client(client); | ||
777 | |||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | static int cx25840_attach_adapter(struct i2c_adapter *adapter) | ||
782 | { | ||
783 | #ifdef I2C_CLASS_TV_ANALOG | ||
784 | if (adapter->class & I2C_CLASS_TV_ANALOG) | ||
785 | #else | ||
786 | if (adapter->id == I2C_HW_B_BT848) | ||
787 | #endif | ||
788 | return i2c_probe(adapter, &addr_data, &cx25840_detect_client); | ||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static int cx25840_detach_client(struct i2c_client *client) | ||
793 | { | ||
794 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
795 | int err; | ||
796 | |||
797 | err = i2c_detach_client(client); | ||
798 | if (err) { | ||
799 | return err; | ||
800 | } | ||
801 | |||
802 | kfree(state); | ||
803 | kfree(client); | ||
804 | |||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | /* ----------------------------------------------------------------------- */ | ||
809 | |||
810 | struct i2c_driver i2c_driver_cx25840 = { | ||
811 | .name = "cx25840", | ||
812 | |||
813 | .id = I2C_DRIVERID_CX25840, | ||
814 | .flags = I2C_DF_NOTIFY, | ||
815 | |||
816 | .attach_adapter = cx25840_attach_adapter, | ||
817 | .detach_client = cx25840_detach_client, | ||
818 | .command = cx25840_command, | ||
819 | .owner = THIS_MODULE, | ||
820 | }; | ||
821 | |||
822 | |||
823 | static int __init m__init(void) | ||
824 | { | ||
825 | return i2c_add_driver(&i2c_driver_cx25840); | ||
826 | } | ||
827 | |||
828 | static void __exit m__exit(void) | ||
829 | { | ||
830 | i2c_del_driver(&i2c_driver_cx25840); | ||
831 | } | ||
832 | |||
833 | module_init(m__init); | ||
834 | module_exit(m__exit); | ||
835 | |||
836 | /* ----------------------------------------------------------------------- */ | ||
837 | |||
838 | static void log_status(struct i2c_client *client) | ||
839 | { | ||
840 | static const char *const fmt_strs[] = { | ||
841 | "0x0", | ||
842 | "NTSC-M", "NTSC-J", "NTSC-4.43", | ||
843 | "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60", | ||
844 | "0x9", "0xA", "0xB", | ||
845 | "SECAM", | ||
846 | "0xD", "0xE", "0xF" | ||
847 | }; | ||
848 | |||
849 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
850 | u8 microctrl_vidfmt = cx25840_read(client, 0x80a); | ||
851 | u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf; | ||
852 | u8 gen_stat1 = cx25840_read(client, 0x40d); | ||
853 | u8 download_ctl = cx25840_read(client, 0x803); | ||
854 | u8 mod_det_stat0 = cx25840_read(client, 0x804); | ||
855 | u8 mod_det_stat1 = cx25840_read(client, 0x805); | ||
856 | u8 audio_config = cx25840_read(client, 0x808); | ||
857 | u8 pref_mode = cx25840_read(client, 0x809); | ||
858 | u8 afc0 = cx25840_read(client, 0x80b); | ||
859 | u8 mute_ctl = cx25840_read(client, 0x8d3); | ||
860 | char *p; | ||
861 | |||
862 | cx25840_info("Video signal: %spresent\n", | ||
863 | (microctrl_vidfmt & 0x10) ? "" : "not "); | ||
864 | cx25840_info("Detected format: %s\n", | ||
865 | fmt_strs[gen_stat1 & 0xf]); | ||
866 | |||
867 | switch (mod_det_stat0) { | ||
868 | case 0x00: p = "mono"; break; | ||
869 | case 0x01: p = "stereo"; break; | ||
870 | case 0x02: p = "dual"; break; | ||
871 | case 0x04: p = "tri"; break; | ||
872 | case 0x10: p = "mono with SAP"; break; | ||
873 | case 0x11: p = "stereo with SAP"; break; | ||
874 | case 0x12: p = "dual with SAP"; break; | ||
875 | case 0x14: p = "tri with SAP"; break; | ||
876 | case 0xfe: p = "forced mode"; break; | ||
877 | default: p = "not defined"; | ||
878 | } | ||
879 | cx25840_info("Detected audio mode: %s\n", p); | ||
880 | |||
881 | switch (mod_det_stat1) { | ||
882 | case 0x00: p = "not defined"; break; | ||
883 | case 0x01: p = "EIAJ"; break; | ||
884 | case 0x02: p = "A2-M"; break; | ||
885 | case 0x03: p = "A2-BG"; break; | ||
886 | case 0x04: p = "A2-DK1"; break; | ||
887 | case 0x05: p = "A2-DK2"; break; | ||
888 | case 0x06: p = "A2-DK3"; break; | ||
889 | case 0x07: p = "A1 (6.0 MHz FM Mono)"; break; | ||
890 | case 0x08: p = "AM-L"; break; | ||
891 | case 0x09: p = "NICAM-BG"; break; | ||
892 | case 0x0a: p = "NICAM-DK"; break; | ||
893 | case 0x0b: p = "NICAM-I"; break; | ||
894 | case 0x0c: p = "NICAM-L"; break; | ||
895 | case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break; | ||
896 | case 0x0e: p = "IF FM Radio"; break; | ||
897 | case 0x0f: p = "BTSC"; break; | ||
898 | case 0x10: p = "high-deviation FM"; break; | ||
899 | case 0x11: p = "very high-deviation FM"; break; | ||
900 | case 0xfd: p = "unknown audio standard"; break; | ||
901 | case 0xfe: p = "forced audio standard"; break; | ||
902 | case 0xff: p = "no detected audio standard"; break; | ||
903 | default: p = "not defined"; | ||
904 | } | ||
905 | cx25840_info("Detected audio standard: %s\n", p); | ||
906 | cx25840_info("Audio muted: %s\n", | ||
907 | (mute_ctl & 0x2) ? "yes" : "no"); | ||
908 | cx25840_info("Audio microcontroller: %s\n", | ||
909 | (download_ctl & 0x10) ? "running" : "stopped"); | ||
910 | |||
911 | switch (audio_config >> 4) { | ||
912 | case 0x00: p = "undefined"; break; | ||
913 | case 0x01: p = "BTSC"; break; | ||
914 | case 0x02: p = "EIAJ"; break; | ||
915 | case 0x03: p = "A2-M"; break; | ||
916 | case 0x04: p = "A2-BG"; break; | ||
917 | case 0x05: p = "A2-DK1"; break; | ||
918 | case 0x06: p = "A2-DK2"; break; | ||
919 | case 0x07: p = "A2-DK3"; break; | ||
920 | case 0x08: p = "A1 (6.0 MHz FM Mono)"; break; | ||
921 | case 0x09: p = "AM-L"; break; | ||
922 | case 0x0a: p = "NICAM-BG"; break; | ||
923 | case 0x0b: p = "NICAM-DK"; break; | ||
924 | case 0x0c: p = "NICAM-I"; break; | ||
925 | case 0x0d: p = "NICAM-L"; break; | ||
926 | case 0x0e: p = "FM radio"; break; | ||
927 | case 0x0f: p = "automatic detection"; break; | ||
928 | default: p = "undefined"; | ||
929 | } | ||
930 | cx25840_info("Configured audio standard: %s\n", p); | ||
931 | |||
932 | if ((audio_config >> 4) < 0xF) { | ||
933 | switch (audio_config & 0xF) { | ||
934 | case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break; | ||
935 | case 0x01: p = "MONO2 (LANGUAGE B)"; break; | ||
936 | case 0x02: p = "MONO3 (STEREO forced MONO)"; break; | ||
937 | case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break; | ||
938 | case 0x04: p = "STEREO"; break; | ||
939 | case 0x05: p = "DUAL1 (AB)"; break; | ||
940 | case 0x06: p = "DUAL2 (AC) (FM)"; break; | ||
941 | case 0x07: p = "DUAL3 (BC) (FM)"; break; | ||
942 | case 0x08: p = "DUAL4 (AC) (AM)"; break; | ||
943 | case 0x09: p = "DUAL5 (BC) (AM)"; break; | ||
944 | case 0x0a: p = "SAP"; break; | ||
945 | default: p = "undefined"; | ||
946 | } | ||
947 | cx25840_info("Configured audio mode: %s\n", p); | ||
948 | } else { | ||
949 | switch (audio_config & 0xF) { | ||
950 | case 0x00: p = "BG"; break; | ||
951 | case 0x01: p = "DK1"; break; | ||
952 | case 0x02: p = "DK2"; break; | ||
953 | case 0x03: p = "DK3"; break; | ||
954 | case 0x04: p = "I"; break; | ||
955 | case 0x05: p = "L"; break; | ||
956 | case 0x06: p = "BTSC"; break; | ||
957 | case 0x07: p = "EIAJ"; break; | ||
958 | case 0x08: p = "A2-M"; break; | ||
959 | case 0x09: p = "FM Radio"; break; | ||
960 | case 0x0f: p = "automatic standard and mode detection"; break; | ||
961 | default: p = "undefined"; | ||
962 | } | ||
963 | cx25840_info("Configured audio system: %s\n", p); | ||
964 | } | ||
965 | |||
966 | cx25840_info("Specified standard: %s\n", | ||
967 | vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); | ||
968 | |||
969 | switch (state->input) { | ||
970 | case CX25840_COMPOSITE0: p = "Composite 0"; break; | ||
971 | case CX25840_COMPOSITE1: p = "Composite 1"; break; | ||
972 | case CX25840_SVIDEO0: p = "S-Video 0"; break; | ||
973 | case CX25840_SVIDEO1: p = "S-Video 1"; break; | ||
974 | case CX25840_TUNER: p = "Tuner"; break; | ||
975 | } | ||
976 | cx25840_info("Specified input: %s\n", p); | ||
977 | cx25840_info("Specified audio input: %s\n", | ||
978 | state->audio_input == 0 ? "Tuner" : "External"); | ||
979 | |||
980 | switch (state->audclk_freq) { | ||
981 | case V4L2_AUDCLK_441_KHZ: p = "44.1 kHz"; break; | ||
982 | case V4L2_AUDCLK_48_KHZ: p = "48 kHz"; break; | ||
983 | case V4L2_AUDCLK_32_KHZ: p = "32 kHz"; break; | ||
984 | default: p = "undefined"; | ||
985 | } | ||
986 | cx25840_info("Specified audioclock freq: %s\n", p); | ||
987 | |||
988 | switch (pref_mode & 0xf) { | ||
989 | case 0: p = "mono/language A"; break; | ||
990 | case 1: p = "language B"; break; | ||
991 | case 2: p = "language C"; break; | ||
992 | case 3: p = "analog fallback"; break; | ||
993 | case 4: p = "stereo"; break; | ||
994 | case 5: p = "language AC"; break; | ||
995 | case 6: p = "language BC"; break; | ||
996 | case 7: p = "language AB"; break; | ||
997 | default: p = "undefined"; | ||
998 | } | ||
999 | cx25840_info("Preferred audio mode: %s\n", p); | ||
1000 | |||
1001 | if ((audio_config & 0xf) == 0xf) { | ||
1002 | switch ((afc0 >> 3) & 0x3) { | ||
1003 | case 0: p = "system DK"; break; | ||
1004 | case 1: p = "system L"; break; | ||
1005 | case 2: p = "autodetect"; break; | ||
1006 | default: p = "undefined"; | ||
1007 | } | ||
1008 | cx25840_info("Selected 65 MHz format: %s\n", p); | ||
1009 | |||
1010 | switch (afc0 & 0x7) { | ||
1011 | case 0: p = "chroma"; break; | ||
1012 | case 1: p = "BTSC"; break; | ||
1013 | case 2: p = "EIAJ"; break; | ||
1014 | case 3: p = "A2-M"; break; | ||
1015 | case 4: p = "autodetect"; break; | ||
1016 | default: p = "undefined"; | ||
1017 | } | ||
1018 | cx25840_info("Selected 45 MHz format: %s\n", p); | ||
1019 | } | ||
1020 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c new file mode 100644 index 000000000000..df9d50a75542 --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-firmware.c | |||
@@ -0,0 +1,167 @@ | |||
1 | /* cx25840 firmware functions | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version 2 | ||
6 | * of the License, or (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/i2c-algo-bit.h> | ||
22 | #include <linux/firmware.h> | ||
23 | #include <media/v4l2-common.h> | ||
24 | |||
25 | #include "cx25840.h" | ||
26 | |||
27 | #define FWFILE "v4l-cx25840.fw" | ||
28 | #define FWSEND 1024 | ||
29 | |||
30 | #define FWDEV(x) &((x)->adapter->dev) | ||
31 | |||
32 | static int fastfw = 1; | ||
33 | static char *firmware = FWFILE; | ||
34 | |||
35 | module_param(fastfw, bool, 0444); | ||
36 | module_param(firmware, charp, 0444); | ||
37 | |||
38 | MODULE_PARM_DESC(fastfw, "Load firmware fast [0=100MHz 1=333MHz (default)]"); | ||
39 | MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]"); | ||
40 | |||
41 | static inline void set_i2c_delay(struct i2c_client *client, int delay) | ||
42 | { | ||
43 | struct i2c_algo_bit_data *algod = client->adapter->algo_data; | ||
44 | |||
45 | /* We aren't guaranteed to be using algo_bit, | ||
46 | * so avoid the null pointer dereference | ||
47 | * and disable the 'fast firmware load' */ | ||
48 | if (algod) { | ||
49 | algod->udelay = delay; | ||
50 | } else { | ||
51 | fastfw = 0; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static inline void start_fw_load(struct i2c_client *client) | ||
56 | { | ||
57 | /* DL_ADDR_LB=0 DL_ADDR_HB=0 */ | ||
58 | cx25840_write(client, 0x800, 0x00); | ||
59 | cx25840_write(client, 0x801, 0x00); | ||
60 | // DL_MAP=3 DL_AUTO_INC=0 DL_ENABLE=1 | ||
61 | cx25840_write(client, 0x803, 0x0b); | ||
62 | /* AUTO_INC_DIS=1 */ | ||
63 | cx25840_write(client, 0x000, 0x20); | ||
64 | |||
65 | if (fastfw) | ||
66 | set_i2c_delay(client, 3); | ||
67 | } | ||
68 | |||
69 | static inline void end_fw_load(struct i2c_client *client) | ||
70 | { | ||
71 | if (fastfw) | ||
72 | set_i2c_delay(client, 10); | ||
73 | |||
74 | /* AUTO_INC_DIS=0 */ | ||
75 | cx25840_write(client, 0x000, 0x00); | ||
76 | /* DL_ENABLE=0 */ | ||
77 | cx25840_write(client, 0x803, 0x03); | ||
78 | } | ||
79 | |||
80 | static inline int check_fw_load(struct i2c_client *client, int size) | ||
81 | { | ||
82 | /* DL_ADDR_HB DL_ADDR_LB */ | ||
83 | int s = cx25840_read(client, 0x801) << 8; | ||
84 | s |= cx25840_read(client, 0x800); | ||
85 | |||
86 | if (size != s) { | ||
87 | cx25840_err("firmware %s load failed\n", firmware); | ||
88 | return -EINVAL; | ||
89 | } | ||
90 | |||
91 | cx25840_info("loaded %s firmware (%d bytes)\n", firmware, size); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static inline int fw_write(struct i2c_client *client, u8 * data, int size) | ||
96 | { | ||
97 | if (i2c_master_send(client, data, size) < size) { | ||
98 | |||
99 | if (fastfw) { | ||
100 | cx25840_err("333MHz i2c firmware load failed\n"); | ||
101 | fastfw = 0; | ||
102 | set_i2c_delay(client, 10); | ||
103 | |||
104 | if (i2c_master_send(client, data, size) < size) { | ||
105 | cx25840_err | ||
106 | ("100MHz i2c firmware load failed\n"); | ||
107 | return -ENOSYS; | ||
108 | } | ||
109 | |||
110 | } else { | ||
111 | cx25840_err("firmware load i2c failure\n"); | ||
112 | return -ENOSYS; | ||
113 | } | ||
114 | |||
115 | } | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | int cx25840_loadfw(struct i2c_client *client) | ||
121 | { | ||
122 | const struct firmware *fw = NULL; | ||
123 | u8 buffer[4], *ptr; | ||
124 | int size, send, retval; | ||
125 | |||
126 | if (request_firmware(&fw, firmware, FWDEV(client)) != 0) { | ||
127 | cx25840_err("unable to open firmware %s\n", firmware); | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | |||
131 | start_fw_load(client); | ||
132 | |||
133 | buffer[0] = 0x08; | ||
134 | buffer[1] = 0x02; | ||
135 | buffer[2] = fw->data[0]; | ||
136 | buffer[3] = fw->data[1]; | ||
137 | retval = fw_write(client, buffer, 4); | ||
138 | |||
139 | if (retval < 0) { | ||
140 | release_firmware(fw); | ||
141 | return retval; | ||
142 | } | ||
143 | |||
144 | size = fw->size - 2; | ||
145 | ptr = fw->data; | ||
146 | while (size > 0) { | ||
147 | ptr[0] = 0x08; | ||
148 | ptr[1] = 0x02; | ||
149 | send = size > (FWSEND - 2) ? FWSEND : size + 2; | ||
150 | retval = fw_write(client, ptr, send); | ||
151 | |||
152 | if (retval < 0) { | ||
153 | release_firmware(fw); | ||
154 | return retval; | ||
155 | } | ||
156 | |||
157 | size -= FWSEND - 2; | ||
158 | ptr += FWSEND - 2; | ||
159 | } | ||
160 | |||
161 | end_fw_load(client); | ||
162 | |||
163 | size = fw->size; | ||
164 | release_firmware(fw); | ||
165 | |||
166 | return check_fw_load(client, size); | ||
167 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c new file mode 100644 index 000000000000..13ba4e15ddea --- /dev/null +++ b/drivers/media/video/cx25840/cx25840-vbi.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* cx25840 VBI functions | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of the GNU General Public License | ||
5 | * as published by the Free Software Foundation; either version 2 | ||
6 | * of the License, or (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | |||
19 | #include <linux/videodev2.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <media/v4l2-common.h> | ||
22 | |||
23 | #include "cx25840.h" | ||
24 | |||
25 | static inline int odd_parity(u8 c) | ||
26 | { | ||
27 | c ^= (c >> 4); | ||
28 | c ^= (c >> 2); | ||
29 | c ^= (c >> 1); | ||
30 | |||
31 | return c & 1; | ||
32 | } | ||
33 | |||
34 | static inline int decode_vps(u8 * dst, u8 * p) | ||
35 | { | ||
36 | static const u8 biphase_tbl[] = { | ||
37 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
38 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
39 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
40 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
41 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
42 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
43 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
44 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
45 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
46 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
47 | 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87, | ||
48 | 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3, | ||
49 | 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85, | ||
50 | 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1, | ||
51 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
52 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
53 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
54 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
55 | 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86, | ||
56 | 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2, | ||
57 | 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84, | ||
58 | 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0, | ||
59 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
60 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
61 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
62 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
63 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
64 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
65 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
66 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
67 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
68 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
69 | }; | ||
70 | |||
71 | u8 c, err = 0; | ||
72 | int i; | ||
73 | |||
74 | for (i = 0; i < 2 * 13; i += 2) { | ||
75 | err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]]; | ||
76 | c = (biphase_tbl[p[i + 1]] & 0xf) | | ||
77 | ((biphase_tbl[p[i]] & 0xf) << 4); | ||
78 | dst[i / 2] = c; | ||
79 | } | ||
80 | |||
81 | return err & 0xf0; | ||
82 | } | ||
83 | |||
84 | void cx25840_vbi_setup(struct i2c_client *client) | ||
85 | { | ||
86 | v4l2_std_id std = cx25840_get_v4lstd(client); | ||
87 | |||
88 | if (std & ~V4L2_STD_NTSC) { | ||
89 | /* datasheet startup, step 8d */ | ||
90 | cx25840_write(client, 0x49f, 0x11); | ||
91 | |||
92 | cx25840_write(client, 0x470, 0x84); | ||
93 | cx25840_write(client, 0x471, 0x00); | ||
94 | cx25840_write(client, 0x472, 0x2d); | ||
95 | cx25840_write(client, 0x473, 0x5d); | ||
96 | |||
97 | cx25840_write(client, 0x474, 0x24); | ||
98 | cx25840_write(client, 0x475, 0x40); | ||
99 | cx25840_write(client, 0x476, 0x24); | ||
100 | cx25840_write(client, 0x477, 0x28); | ||
101 | |||
102 | cx25840_write(client, 0x478, 0x1f); | ||
103 | cx25840_write(client, 0x479, 0x02); | ||
104 | |||
105 | if (std & V4L2_STD_SECAM) { | ||
106 | cx25840_write(client, 0x47a, 0x80); | ||
107 | cx25840_write(client, 0x47b, 0x00); | ||
108 | cx25840_write(client, 0x47c, 0x5f); | ||
109 | cx25840_write(client, 0x47d, 0x42); | ||
110 | } else { | ||
111 | cx25840_write(client, 0x47a, 0x90); | ||
112 | cx25840_write(client, 0x47b, 0x20); | ||
113 | cx25840_write(client, 0x47c, 0x63); | ||
114 | cx25840_write(client, 0x47d, 0x82); | ||
115 | } | ||
116 | |||
117 | cx25840_write(client, 0x47e, 0x0a); | ||
118 | cx25840_write(client, 0x47f, 0x01); | ||
119 | } else { | ||
120 | /* datasheet startup, step 8d */ | ||
121 | cx25840_write(client, 0x49f, 0x14); | ||
122 | |||
123 | cx25840_write(client, 0x470, 0x7a); | ||
124 | cx25840_write(client, 0x471, 0x00); | ||
125 | cx25840_write(client, 0x472, 0x2d); | ||
126 | cx25840_write(client, 0x473, 0x5b); | ||
127 | |||
128 | cx25840_write(client, 0x474, 0x1a); | ||
129 | cx25840_write(client, 0x475, 0x70); | ||
130 | cx25840_write(client, 0x476, 0x1e); | ||
131 | cx25840_write(client, 0x477, 0x1e); | ||
132 | |||
133 | cx25840_write(client, 0x478, 0x1f); | ||
134 | cx25840_write(client, 0x479, 0x02); | ||
135 | cx25840_write(client, 0x47a, 0x50); | ||
136 | cx25840_write(client, 0x47b, 0x66); | ||
137 | |||
138 | cx25840_write(client, 0x47c, 0x1f); | ||
139 | cx25840_write(client, 0x47d, 0x7c); | ||
140 | cx25840_write(client, 0x47e, 0x08); | ||
141 | cx25840_write(client, 0x47f, 0x00); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | ||
146 | { | ||
147 | struct v4l2_format *fmt; | ||
148 | struct v4l2_sliced_vbi_format *svbi; | ||
149 | |||
150 | switch (cmd) { | ||
151 | case VIDIOC_G_FMT: | ||
152 | { | ||
153 | static u16 lcr2vbi[] = { | ||
154 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ | ||
155 | 0, V4L2_SLICED_WSS_625, 0, /* 4 */ | ||
156 | V4L2_SLICED_CAPTION_525, /* 6 */ | ||
157 | 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ | ||
158 | 0, 0, 0, 0 | ||
159 | }; | ||
160 | int i; | ||
161 | |||
162 | fmt = arg; | ||
163 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
164 | return -EINVAL; | ||
165 | svbi = &fmt->fmt.sliced; | ||
166 | memset(svbi, 0, sizeof(*svbi)); | ||
167 | /* we're done if raw VBI is active */ | ||
168 | if ((cx25840_read(client, 0x404) & 0x10) == 0) | ||
169 | break; | ||
170 | |||
171 | for (i = 7; i <= 23; i++) { | ||
172 | u8 v = cx25840_read(client, 0x424 + i - 7); | ||
173 | |||
174 | svbi->service_lines[0][i] = lcr2vbi[v >> 4]; | ||
175 | svbi->service_lines[1][i] = lcr2vbi[v & 0xf]; | ||
176 | svbi->service_set |= | ||
177 | svbi->service_lines[0][i] | svbi->service_lines[1][i]; | ||
178 | } | ||
179 | break; | ||
180 | } | ||
181 | |||
182 | case VIDIOC_S_FMT: | ||
183 | { | ||
184 | int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); | ||
185 | int vbi_offset = is_pal ? 1 : 0; | ||
186 | int i, x; | ||
187 | u8 lcr[24]; | ||
188 | |||
189 | fmt = arg; | ||
190 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
191 | return -EINVAL; | ||
192 | svbi = &fmt->fmt.sliced; | ||
193 | if (svbi->service_set == 0) { | ||
194 | /* raw VBI */ | ||
195 | memset(svbi, 0, sizeof(*svbi)); | ||
196 | |||
197 | /* Setup VBI */ | ||
198 | cx25840_vbi_setup(client); | ||
199 | |||
200 | /* VBI Offset */ | ||
201 | cx25840_write(client, 0x47f, vbi_offset); | ||
202 | cx25840_write(client, 0x404, 0x2e); | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | for (x = 0; x <= 23; x++) | ||
207 | lcr[x] = 0x00; | ||
208 | |||
209 | /* Setup VBI */ | ||
210 | cx25840_vbi_setup(client); | ||
211 | |||
212 | /* Sliced VBI */ | ||
213 | cx25840_write(client, 0x404, 0x36); /* Ancillery data */ | ||
214 | cx25840_write(client, 0x406, 0x13); | ||
215 | cx25840_write(client, 0x47f, vbi_offset); | ||
216 | |||
217 | if (is_pal) { | ||
218 | for (i = 0; i <= 6; i++) | ||
219 | svbi->service_lines[0][i] = | ||
220 | svbi->service_lines[1][i] = 0; | ||
221 | } else { | ||
222 | for (i = 0; i <= 9; i++) | ||
223 | svbi->service_lines[0][i] = | ||
224 | svbi->service_lines[1][i] = 0; | ||
225 | |||
226 | for (i = 22; i <= 23; i++) | ||
227 | svbi->service_lines[0][i] = | ||
228 | svbi->service_lines[1][i] = 0; | ||
229 | } | ||
230 | |||
231 | for (i = 7; i <= 23; i++) { | ||
232 | for (x = 0; x <= 1; x++) { | ||
233 | switch (svbi->service_lines[1-x][i]) { | ||
234 | case V4L2_SLICED_TELETEXT_B: | ||
235 | lcr[i] |= 1 << (4 * x); | ||
236 | break; | ||
237 | case V4L2_SLICED_WSS_625: | ||
238 | lcr[i] |= 4 << (4 * x); | ||
239 | break; | ||
240 | case V4L2_SLICED_CAPTION_525: | ||
241 | lcr[i] |= 6 << (4 * x); | ||
242 | break; | ||
243 | case V4L2_SLICED_VPS: | ||
244 | lcr[i] |= 9 << (4 * x); | ||
245 | break; | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | |||
250 | for (x = 1, i = 0x424; i <= 0x434; i++, x++) { | ||
251 | cx25840_write(client, i, lcr[6 + x]); | ||
252 | } | ||
253 | |||
254 | cx25840_write(client, 0x43c, 0x16); | ||
255 | |||
256 | if (is_pal) { | ||
257 | cx25840_write(client, 0x474, 0x2a); | ||
258 | } else { | ||
259 | cx25840_write(client, 0x474, 0x1a + 6); | ||
260 | } | ||
261 | break; | ||
262 | } | ||
263 | |||
264 | case VIDIOC_INT_DECODE_VBI_LINE: | ||
265 | { | ||
266 | struct v4l2_decode_vbi_line *vbi = arg; | ||
267 | u8 *p = vbi->p; | ||
268 | int id1, id2, l, err = 0; | ||
269 | |||
270 | if (p[0] || p[1] != 0xff || p[2] != 0xff || | ||
271 | (p[3] != 0x55 && p[3] != 0x91)) { | ||
272 | vbi->line = vbi->type = 0; | ||
273 | break; | ||
274 | } | ||
275 | |||
276 | p += 4; | ||
277 | id1 = p[-1]; | ||
278 | id2 = p[0] & 0xf; | ||
279 | l = p[2] & 0x3f; | ||
280 | l += 5; | ||
281 | p += 4; | ||
282 | |||
283 | switch (id2) { | ||
284 | case 1: | ||
285 | id2 = V4L2_SLICED_TELETEXT_B; | ||
286 | break; | ||
287 | case 4: | ||
288 | id2 = V4L2_SLICED_WSS_625; | ||
289 | break; | ||
290 | case 6: | ||
291 | id2 = V4L2_SLICED_CAPTION_525; | ||
292 | err = !odd_parity(p[0]) || !odd_parity(p[1]); | ||
293 | break; | ||
294 | case 9: | ||
295 | id2 = V4L2_SLICED_VPS; | ||
296 | if (decode_vps(p, p) != 0) { | ||
297 | err = 1; | ||
298 | } | ||
299 | break; | ||
300 | default: | ||
301 | id2 = 0; | ||
302 | err = 1; | ||
303 | break; | ||
304 | } | ||
305 | |||
306 | vbi->type = err ? 0 : id2; | ||
307 | vbi->line = err ? 0 : l; | ||
308 | vbi->is_second_field = err ? 0 : (id1 == 0x55); | ||
309 | vbi->p = p; | ||
310 | break; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | return 0; | ||
315 | } | ||
diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840.h new file mode 100644 index 000000000000..5c3f0639fb77 --- /dev/null +++ b/drivers/media/video/cx25840/cx25840.h | |||
@@ -0,0 +1,85 @@ | |||
1 | /* cx25840 API header | ||
2 | * | ||
3 | * Copyright (C) 2003-2004 Chris Kennedy | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version 2 | ||
8 | * of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef _CX25840_H_ | ||
21 | #define _CX25840_H_ | ||
22 | |||
23 | |||
24 | #include <linux/videodev2.h> | ||
25 | #include <linux/i2c.h> | ||
26 | |||
27 | extern int cx25840_debug; | ||
28 | |||
29 | #define cx25840_dbg(fmt, arg...) do { if (cx25840_debug) \ | ||
30 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
31 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
32 | |||
33 | #define cx25840_err(fmt, arg...) do { \ | ||
34 | printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ | ||
35 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
36 | |||
37 | #define cx25840_info(fmt, arg...) do { \ | ||
38 | printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ | ||
39 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
40 | |||
41 | #define CX25840_CID_CARDTYPE (V4L2_CID_PRIVATE_BASE+0) | ||
42 | |||
43 | enum cx25840_cardtype { | ||
44 | CARDTYPE_PVR150, | ||
45 | CARDTYPE_PG600 | ||
46 | }; | ||
47 | |||
48 | enum cx25840_input { | ||
49 | CX25840_TUNER, | ||
50 | CX25840_COMPOSITE0, | ||
51 | CX25840_COMPOSITE1, | ||
52 | CX25840_SVIDEO0, | ||
53 | CX25840_SVIDEO1 | ||
54 | }; | ||
55 | |||
56 | struct cx25840_state { | ||
57 | enum cx25840_cardtype cardtype; | ||
58 | enum cx25840_input input; | ||
59 | int audio_input; | ||
60 | enum v4l2_audio_clock_freq audclk_freq; | ||
61 | }; | ||
62 | |||
63 | /* ----------------------------------------------------------------------- */ | ||
64 | /* cx25850-core.c */ | ||
65 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value); | ||
66 | int cx25840_write4(struct i2c_client *client, u16 addr, u32 value); | ||
67 | u8 cx25840_read(struct i2c_client *client, u16 addr); | ||
68 | u32 cx25840_read4(struct i2c_client *client, u16 addr); | ||
69 | int cx25840_and_or(struct i2c_client *client, u16 addr, u8 mask, u8 value); | ||
70 | v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client); | ||
71 | |||
72 | /* ----------------------------------------------------------------------- */ | ||
73 | /* cx25850-firmware.c */ | ||
74 | int cx25840_loadfw(struct i2c_client *client); | ||
75 | |||
76 | /* ----------------------------------------------------------------------- */ | ||
77 | /* cx25850-audio.c */ | ||
78 | int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg); | ||
79 | |||
80 | /* ----------------------------------------------------------------------- */ | ||
81 | /* cx25850-vbi.c */ | ||
82 | void cx25840_vbi_setup(struct i2c_client *client); | ||
83 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg); | ||
84 | |||
85 | #endif | ||
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 9cce91ec334b..99ea955f5987 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -439,9 +439,6 @@ static int dvb_register(struct cx8802_dev *dev) | |||
439 | /* Put the analog decoder in standby to keep it quiet */ | 439 | /* Put the analog decoder in standby to keep it quiet */ |
440 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 440 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); |
441 | 441 | ||
442 | /* Put the analog decoder in standby to keep it quiet */ | ||
443 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
444 | |||
445 | /* register everything */ | 442 | /* register everything */ |
446 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); | 443 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); |
447 | } | 444 | } |
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 32c49df58adc..9b94f77d6fd7 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -120,9 +120,6 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
120 | if (buf[1]==0xff) | 120 | if (buf[1]==0xff) |
121 | return 0; | 121 | return 0; |
122 | 122 | ||
123 | /* avoid fast reapeating */ | ||
124 | if (buf[1]==ir->old) | ||
125 | return 0; | ||
126 | ir->old=buf[1]; | 123 | ir->old=buf[1]; |
127 | 124 | ||
128 | /* Rearranges bits to the right order */ | 125 | /* Rearranges bits to the right order */ |
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index ed81934ef3cd..5abfc0fbf6de 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c | |||
@@ -221,24 +221,99 @@ static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = { | |||
221 | [ 24 ] = KEY_MUTE // mute/unmute | 221 | [ 24 ] = KEY_MUTE // mute/unmute |
222 | }; | 222 | }; |
223 | 223 | ||
224 | static IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = { | ||
225 | [0x00] = KEY_KP0, | ||
226 | [0x01] = KEY_KP1, | ||
227 | [0x02] = KEY_KP2, | ||
228 | [0x03] = KEY_KP3, | ||
229 | [0x04] = KEY_KP4, | ||
230 | [0x05] = KEY_KP5, | ||
231 | [0x06] = KEY_KP6, | ||
232 | [0x07] = KEY_KP7, | ||
233 | [0x08] = KEY_KP8, | ||
234 | [0x09] = KEY_KP9, | ||
235 | [0x0a] = KEY_TV, | ||
236 | [0x0b] = KEY_AUX, | ||
237 | [0x0c] = KEY_DVD, | ||
238 | [0x0d] = KEY_POWER, | ||
239 | [0x0e] = KEY_MHP, /* labelled 'Picture' */ | ||
240 | [0x0f] = KEY_AUDIO, | ||
241 | [0x10] = KEY_INFO, | ||
242 | [0x11] = KEY_F13, /* 16:9 */ | ||
243 | [0x12] = KEY_F14, /* 14:9 */ | ||
244 | [0x13] = KEY_EPG, | ||
245 | [0x14] = KEY_EXIT, | ||
246 | [0x15] = KEY_MENU, | ||
247 | [0x16] = KEY_UP, | ||
248 | [0x17] = KEY_DOWN, | ||
249 | [0x18] = KEY_LEFT, | ||
250 | [0x19] = KEY_RIGHT, | ||
251 | [0x1a] = KEY_ENTER, | ||
252 | [0x1b] = KEY_CHANNELUP, | ||
253 | [0x1c] = KEY_CHANNELDOWN, | ||
254 | [0x1d] = KEY_VOLUMEUP, | ||
255 | [0x1e] = KEY_VOLUMEDOWN, | ||
256 | [0x1f] = KEY_RED, | ||
257 | [0x20] = KEY_GREEN, | ||
258 | [0x21] = KEY_YELLOW, | ||
259 | [0x22] = KEY_BLUE, | ||
260 | [0x23] = KEY_SUBTITLE, | ||
261 | [0x24] = KEY_F15, /* AD */ | ||
262 | [0x25] = KEY_TEXT, | ||
263 | [0x26] = KEY_MUTE, | ||
264 | [0x27] = KEY_REWIND, | ||
265 | [0x28] = KEY_STOP, | ||
266 | [0x29] = KEY_PLAY, | ||
267 | [0x2a] = KEY_FASTFORWARD, | ||
268 | [0x2b] = KEY_F16, /* chapter */ | ||
269 | [0x2c] = KEY_PAUSE, | ||
270 | [0x2d] = KEY_PLAY, | ||
271 | [0x2e] = KEY_RECORD, | ||
272 | [0x2f] = KEY_F17, /* picture in picture */ | ||
273 | [0x30] = KEY_KPPLUS, /* zoom in */ | ||
274 | [0x31] = KEY_KPMINUS, /* zoom out */ | ||
275 | [0x32] = KEY_F18, /* capture */ | ||
276 | [0x33] = KEY_F19, /* web */ | ||
277 | [0x34] = KEY_EMAIL, | ||
278 | [0x35] = KEY_PHONE, | ||
279 | [0x36] = KEY_PC | ||
280 | }; | ||
281 | |||
224 | struct IR { | 282 | struct IR { |
225 | struct bttv_sub_device *sub; | 283 | struct bttv_sub_device *sub; |
226 | struct input_dev *input; | 284 | struct input_dev *input; |
227 | struct ir_input_state ir; | 285 | struct ir_input_state ir; |
228 | char name[32]; | 286 | char name[32]; |
229 | char phys[32]; | 287 | char phys[32]; |
288 | |||
289 | /* Usual gpio signalling */ | ||
290 | |||
230 | u32 mask_keycode; | 291 | u32 mask_keycode; |
231 | u32 mask_keydown; | 292 | u32 mask_keydown; |
232 | u32 mask_keyup; | 293 | u32 mask_keyup; |
233 | 294 | u32 polling; | |
234 | int polling; | ||
235 | u32 last_gpio; | 295 | u32 last_gpio; |
236 | struct work_struct work; | 296 | struct work_struct work; |
237 | struct timer_list timer; | 297 | struct timer_list timer; |
298 | |||
299 | /* RC5 gpio */ | ||
300 | |||
301 | u32 rc5_gpio; | ||
302 | struct timer_list timer_end; /* timer_end for code completion */ | ||
303 | struct timer_list timer_keyup; /* timer_end for key release */ | ||
304 | u32 last_rc5; /* last good rc5 code */ | ||
305 | u32 last_bit; /* last raw bit seen */ | ||
306 | u32 code; /* raw code under construction */ | ||
307 | struct timeval base_time; /* time of last seen code */ | ||
308 | int active; /* building raw code */ | ||
238 | }; | 309 | }; |
239 | 310 | ||
240 | static int debug; | 311 | static int debug; |
241 | module_param(debug, int, 0644); /* debug level (0,1,2) */ | 312 | module_param(debug, int, 0644); /* debug level (0,1,2) */ |
313 | static int repeat_delay = 500; | ||
314 | module_param(repeat_delay, int, 0644); | ||
315 | static int repeat_period = 33; | ||
316 | module_param(repeat_period, int, 0644); | ||
242 | 317 | ||
243 | #define DEVNAME "ir-kbd-gpio" | 318 | #define DEVNAME "ir-kbd-gpio" |
244 | #define dprintk(fmt, arg...) if (debug) \ | 319 | #define dprintk(fmt, arg...) if (debug) \ |
@@ -254,7 +329,7 @@ static struct bttv_sub_driver driver = { | |||
254 | .probe = ir_probe, | 329 | .probe = ir_probe, |
255 | .remove = ir_remove, | 330 | .remove = ir_remove, |
256 | }, | 331 | }, |
257 | .gpio_irq = ir_irq, | 332 | .gpio_irq = ir_irq, |
258 | }; | 333 | }; |
259 | 334 | ||
260 | /* ---------------------------------------------------------------------- */ | 335 | /* ---------------------------------------------------------------------- */ |
@@ -327,6 +402,173 @@ static void ir_work(void *data) | |||
327 | mod_timer(&ir->timer, timeout); | 402 | mod_timer(&ir->timer, timeout); |
328 | } | 403 | } |
329 | 404 | ||
405 | /* ---------------------------------------------------------------*/ | ||
406 | |||
407 | static int rc5_remote_gap = 885; | ||
408 | module_param(rc5_remote_gap, int, 0644); | ||
409 | static int rc5_key_timeout = 200; | ||
410 | module_param(rc5_key_timeout, int, 0644); | ||
411 | |||
412 | #define RC5_START(x) (((x)>>12)&3) | ||
413 | #define RC5_TOGGLE(x) (((x)>>11)&1) | ||
414 | #define RC5_ADDR(x) (((x)>>6)&31) | ||
415 | #define RC5_INSTR(x) ((x)&63) | ||
416 | |||
417 | /* decode raw bit pattern to RC5 code */ | ||
418 | static u32 rc5_decode(unsigned int code) | ||
419 | { | ||
420 | unsigned int org_code = code; | ||
421 | unsigned int pair; | ||
422 | unsigned int rc5 = 0; | ||
423 | int i; | ||
424 | |||
425 | code = (code << 1) | 1; | ||
426 | for (i = 0; i < 14; ++i) { | ||
427 | pair = code & 0x3; | ||
428 | code >>= 2; | ||
429 | |||
430 | rc5 <<= 1; | ||
431 | switch (pair) { | ||
432 | case 0: | ||
433 | case 2: | ||
434 | break; | ||
435 | case 1: | ||
436 | rc5 |= 1; | ||
437 | break; | ||
438 | case 3: | ||
439 | dprintk("bad code: %x\n", org_code); | ||
440 | return 0; | ||
441 | } | ||
442 | } | ||
443 | dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, " | ||
444 | "instr=%x\n", rc5, org_code, RC5_START(rc5), | ||
445 | RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); | ||
446 | return rc5; | ||
447 | } | ||
448 | |||
449 | static int ir_rc5_irq(struct bttv_sub_device *sub) | ||
450 | { | ||
451 | struct IR *ir = dev_get_drvdata(&sub->dev); | ||
452 | struct timeval tv; | ||
453 | u32 gpio; | ||
454 | u32 gap; | ||
455 | unsigned long current_jiffies, timeout; | ||
456 | |||
457 | /* read gpio port */ | ||
458 | gpio = bttv_gpio_read(ir->sub->core); | ||
459 | |||
460 | /* remote IRQ? */ | ||
461 | if (!(gpio & 0x20)) | ||
462 | return 0; | ||
463 | |||
464 | /* get time of bit */ | ||
465 | current_jiffies = jiffies; | ||
466 | do_gettimeofday(&tv); | ||
467 | |||
468 | /* avoid overflow with gap >1s */ | ||
469 | if (tv.tv_sec - ir->base_time.tv_sec > 1) { | ||
470 | gap = 200000; | ||
471 | } else { | ||
472 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
473 | tv.tv_usec - ir->base_time.tv_usec; | ||
474 | } | ||
475 | |||
476 | /* active code => add bit */ | ||
477 | if (ir->active) { | ||
478 | /* only if in the code (otherwise spurious IRQ or timer | ||
479 | late) */ | ||
480 | if (ir->last_bit < 28) { | ||
481 | ir->last_bit = (gap - rc5_remote_gap / 2) / | ||
482 | rc5_remote_gap; | ||
483 | ir->code |= 1 << ir->last_bit; | ||
484 | } | ||
485 | /* starting new code */ | ||
486 | } else { | ||
487 | ir->active = 1; | ||
488 | ir->code = 0; | ||
489 | ir->base_time = tv; | ||
490 | ir->last_bit = 0; | ||
491 | |||
492 | timeout = current_jiffies + (500 + 30 * HZ) / 1000; | ||
493 | mod_timer(&ir->timer_end, timeout); | ||
494 | } | ||
495 | |||
496 | /* toggle GPIO pin 4 to reset the irq */ | ||
497 | bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4)); | ||
498 | bttv_gpio_write(ir->sub->core, gpio | (1 << 4)); | ||
499 | return 1; | ||
500 | } | ||
501 | |||
502 | static void ir_rc5_timer_end(unsigned long data) | ||
503 | { | ||
504 | struct IR *ir = (struct IR *)data; | ||
505 | struct timeval tv; | ||
506 | unsigned long current_jiffies, timeout; | ||
507 | u32 gap; | ||
508 | |||
509 | /* get time */ | ||
510 | current_jiffies = jiffies; | ||
511 | do_gettimeofday(&tv); | ||
512 | |||
513 | /* avoid overflow with gap >1s */ | ||
514 | if (tv.tv_sec - ir->base_time.tv_sec > 1) { | ||
515 | gap = 200000; | ||
516 | } else { | ||
517 | gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) + | ||
518 | tv.tv_usec - ir->base_time.tv_usec; | ||
519 | } | ||
520 | |||
521 | /* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */ | ||
522 | if (gap < 28000) { | ||
523 | dprintk("spurious timer_end\n"); | ||
524 | return; | ||
525 | } | ||
526 | |||
527 | ir->active = 0; | ||
528 | if (ir->last_bit < 20) { | ||
529 | /* ignore spurious codes (caused by light/other remotes) */ | ||
530 | dprintk("short code: %x\n", ir->code); | ||
531 | } else { | ||
532 | u32 rc5 = rc5_decode(ir->code); | ||
533 | |||
534 | /* two start bits? */ | ||
535 | if (RC5_START(rc5) != 3) { | ||
536 | dprintk("rc5 start bits invalid: %u\n", RC5_START(rc5)); | ||
537 | |||
538 | /* right address? */ | ||
539 | } else if (RC5_ADDR(rc5) == 0x0) { | ||
540 | u32 toggle = RC5_TOGGLE(rc5); | ||
541 | u32 instr = RC5_INSTR(rc5); | ||
542 | |||
543 | /* Good code, decide if repeat/repress */ | ||
544 | if (toggle != RC5_TOGGLE(ir->last_rc5) || | ||
545 | instr != RC5_INSTR(ir->last_rc5)) { | ||
546 | dprintk("instruction %x, toggle %x\n", instr, | ||
547 | toggle); | ||
548 | ir_input_nokey(ir->input, &ir->ir); | ||
549 | ir_input_keydown(ir->input, &ir->ir, instr, | ||
550 | instr); | ||
551 | } | ||
552 | |||
553 | /* Set/reset key-up timer */ | ||
554 | timeout = current_jiffies + (500 + rc5_key_timeout | ||
555 | * HZ) / 1000; | ||
556 | mod_timer(&ir->timer_keyup, timeout); | ||
557 | |||
558 | /* Save code for repeat test */ | ||
559 | ir->last_rc5 = rc5; | ||
560 | } | ||
561 | } | ||
562 | } | ||
563 | |||
564 | static void ir_rc5_timer_keyup(unsigned long data) | ||
565 | { | ||
566 | struct IR *ir = (struct IR *)data; | ||
567 | |||
568 | dprintk("key released\n"); | ||
569 | ir_input_nokey(ir->input, &ir->ir); | ||
570 | } | ||
571 | |||
330 | /* ---------------------------------------------------------------------- */ | 572 | /* ---------------------------------------------------------------------- */ |
331 | 573 | ||
332 | static int ir_probe(struct device *dev) | 574 | static int ir_probe(struct device *dev) |
@@ -400,6 +642,12 @@ static int ir_probe(struct device *dev) | |||
400 | ir->mask_keyup = 0x006000; | 642 | ir->mask_keyup = 0x006000; |
401 | ir->polling = 50; // ms | 643 | ir->polling = 50; // ms |
402 | break; | 644 | break; |
645 | case BTTV_BOARD_NEBULA_DIGITV: | ||
646 | ir_codes = ir_codes_nebula; | ||
647 | driver.any_irq = ir_rc5_irq; | ||
648 | driver.gpio_irq = NULL; | ||
649 | ir->rc5_gpio = 1; | ||
650 | break; | ||
403 | } | 651 | } |
404 | if (NULL == ir_codes) { | 652 | if (NULL == ir_codes) { |
405 | kfree(ir); | 653 | kfree(ir); |
@@ -407,9 +655,17 @@ static int ir_probe(struct device *dev) | |||
407 | return -ENODEV; | 655 | return -ENODEV; |
408 | } | 656 | } |
409 | 657 | ||
410 | /* init hardware-specific stuff */ | 658 | if (ir->rc5_gpio) { |
411 | bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0); | 659 | u32 gpio; |
412 | ir->sub = sub; | 660 | /* enable remote irq */ |
661 | bttv_gpio_inout(sub->core, (1 << 4), 1 << 4); | ||
662 | gpio = bttv_gpio_read(sub->core); | ||
663 | bttv_gpio_write(sub->core, gpio & ~(1 << 4)); | ||
664 | bttv_gpio_write(sub->core, gpio | (1 << 4)); | ||
665 | } else { | ||
666 | /* init hardware-specific stuff */ | ||
667 | bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0); | ||
668 | } | ||
413 | 669 | ||
414 | /* init input device */ | 670 | /* init input device */ |
415 | snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", | 671 | snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)", |
@@ -417,6 +673,7 @@ static int ir_probe(struct device *dev) | |||
417 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", | 673 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", |
418 | pci_name(sub->core->pci)); | 674 | pci_name(sub->core->pci)); |
419 | 675 | ||
676 | ir->sub = sub; | ||
420 | ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | 677 | ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); |
421 | input_dev->name = ir->name; | 678 | input_dev->name = ir->name; |
422 | input_dev->phys = ir->phys; | 679 | input_dev->phys = ir->phys; |
@@ -437,11 +694,25 @@ static int ir_probe(struct device *dev) | |||
437 | ir->timer.function = ir_timer; | 694 | ir->timer.function = ir_timer; |
438 | ir->timer.data = (unsigned long)ir; | 695 | ir->timer.data = (unsigned long)ir; |
439 | schedule_work(&ir->work); | 696 | schedule_work(&ir->work); |
697 | } else if (ir->rc5_gpio) { | ||
698 | /* set timer_end for code completion */ | ||
699 | init_timer(&ir->timer_end); | ||
700 | ir->timer_end.function = ir_rc5_timer_end; | ||
701 | ir->timer_end.data = (unsigned long)ir; | ||
702 | |||
703 | init_timer(&ir->timer_keyup); | ||
704 | ir->timer_keyup.function = ir_rc5_timer_keyup; | ||
705 | ir->timer_keyup.data = (unsigned long)ir; | ||
440 | } | 706 | } |
441 | 707 | ||
442 | /* all done */ | 708 | /* all done */ |
443 | dev_set_drvdata(dev, ir); | 709 | dev_set_drvdata(dev, ir); |
444 | input_register_device(ir->input); | 710 | input_register_device(ir->input); |
711 | printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys); | ||
712 | |||
713 | /* the remote isn't as bouncy as a keyboard */ | ||
714 | ir->input->rep[REP_DELAY] = repeat_delay; | ||
715 | ir->input->rep[REP_PERIOD] = repeat_period; | ||
445 | 716 | ||
446 | return 0; | 717 | return 0; |
447 | } | 718 | } |
@@ -454,6 +725,15 @@ static int ir_remove(struct device *dev) | |||
454 | del_timer(&ir->timer); | 725 | del_timer(&ir->timer); |
455 | flush_scheduled_work(); | 726 | flush_scheduled_work(); |
456 | } | 727 | } |
728 | if (ir->rc5_gpio) { | ||
729 | u32 gpio; | ||
730 | |||
731 | del_timer(&ir->timer_end); | ||
732 | flush_scheduled_work(); | ||
733 | |||
734 | gpio = bttv_gpio_read(ir->sub->core); | ||
735 | bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4)); | ||
736 | } | ||
457 | 737 | ||
458 | input_unregister_device(ir->input); | 738 | input_unregister_device(ir->input); |
459 | kfree(ir); | 739 | kfree(ir); |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 0085567a1421..801c736e9328 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -183,6 +183,58 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
183 | return 1; | 183 | return 1; |
184 | } | 184 | } |
185 | 185 | ||
186 | /* The new pinnacle PCTV remote (with the colored buttons) | ||
187 | * | ||
188 | * Ricardo Cerqueira <v4l@cerqueira.org> | ||
189 | */ | ||
190 | |||
191 | int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
192 | { | ||
193 | unsigned char b[4]; | ||
194 | unsigned int start = 0,parity = 0,code = 0; | ||
195 | |||
196 | /* poll IR chip */ | ||
197 | if (4 != i2c_master_recv(&ir->c,b,4)) { | ||
198 | dprintk(2,"read error\n"); | ||
199 | return -EIO; | ||
200 | } | ||
201 | |||
202 | for (start = 0; start<4; start++) { | ||
203 | if (b[start] == 0x80) { | ||
204 | code=b[(start+3)%4]; | ||
205 | parity=b[(start+2)%4]; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | /* Empty Request */ | ||
210 | if (parity==0) | ||
211 | return 0; | ||
212 | |||
213 | /* Repeating... */ | ||
214 | if (ir->old == parity) | ||
215 | return 0; | ||
216 | |||
217 | |||
218 | ir->old = parity; | ||
219 | |||
220 | /* Reduce code value to fit inside IR_KEYTAB_SIZE | ||
221 | * | ||
222 | * this is the only value that results in 42 unique | ||
223 | * codes < 128 | ||
224 | */ | ||
225 | |||
226 | code %= 0x88; | ||
227 | |||
228 | *ir_raw = code; | ||
229 | *ir_key = code; | ||
230 | |||
231 | dprintk(1,"Pinnacle PCTV key %02x\n", code); | ||
232 | |||
233 | return 1; | ||
234 | } | ||
235 | |||
236 | EXPORT_SYMBOL_GPL(get_key_pinnacle); | ||
237 | |||
186 | /* ----------------------------------------------------------------------- */ | 238 | /* ----------------------------------------------------------------------- */ |
187 | 239 | ||
188 | static void ir_key_poll(struct IR_i2c *ir) | 240 | static void ir_key_poll(struct IR_i2c *ir) |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c new file mode 100644 index 000000000000..0235cef07b31 --- /dev/null +++ b/drivers/media/video/saa7115.c | |||
@@ -0,0 +1,1376 @@ | |||
1 | /* saa7115 - Philips SAA7114/SAA7115 video decoder driver | ||
2 | * | ||
3 | * Based on saa7114 driver by Maxim Yevtyushkin, which is based on | ||
4 | * the saa7111 driver by Dave Perks. | ||
5 | * | ||
6 | * Copyright (C) 1998 Dave Perks <dperks@ibm.net> | ||
7 | * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com> | ||
8 | * | ||
9 | * Slight changes for video timing and attachment output by | ||
10 | * Wolfgang Scherr <scherr@net4you.net> | ||
11 | * | ||
12 | * Moved over to the linux >= 2.4.x i2c protocol (1/1/2003) | ||
13 | * by Ronald Bultje <rbultje@ronald.bitfreak.net> | ||
14 | * | ||
15 | * Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com> | ||
16 | * (2/17/2003) | ||
17 | * | ||
18 | * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl> | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or | ||
21 | * modify it under the terms of the GNU General Public License | ||
22 | * as published by the Free Software Foundation; either version 2 | ||
23 | * of the License, or (at your option) any later version. | ||
24 | * | ||
25 | * This program is distributed in the hope that it will be useful, | ||
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
28 | * GNU General Public License for more details. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License | ||
31 | * along with this program; if not, write to the Free Software | ||
32 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
33 | */ | ||
34 | |||
35 | |||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/i2c.h> | ||
40 | #include <linux/videodev2.h> | ||
41 | #include <media/v4l2-common.h> | ||
42 | |||
43 | MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver"); | ||
44 | MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil"); | ||
45 | MODULE_LICENSE("GPL"); | ||
46 | |||
47 | static int debug = 0; | ||
48 | module_param(debug, int, 0644); | ||
49 | |||
50 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | ||
51 | |||
52 | #define saa7115_dbg(fmt,arg...) \ | ||
53 | do { \ | ||
54 | if (debug) \ | ||
55 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
56 | i2c_adapter_id(client->adapter), client->addr , ## arg); \ | ||
57 | } while (0) | ||
58 | |||
59 | #define saa7115_err(fmt, arg...) do { \ | ||
60 | printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ | ||
61 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
62 | #define saa7115_info(fmt, arg...) do { \ | ||
63 | printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ | ||
64 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
65 | |||
66 | static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; | ||
67 | |||
68 | |||
69 | I2C_CLIENT_INSMOD; | ||
70 | |||
71 | struct saa7115_state { | ||
72 | v4l2_std_id std; | ||
73 | int input; | ||
74 | int enable; | ||
75 | int bright; | ||
76 | int contrast; | ||
77 | int hue; | ||
78 | int sat; | ||
79 | enum v4l2_chip_ident ident; | ||
80 | enum v4l2_audio_clock_freq audclk_freq; | ||
81 | }; | ||
82 | |||
83 | /* ----------------------------------------------------------------------- */ | ||
84 | |||
85 | static inline int saa7115_write(struct i2c_client *client, u8 reg, u8 value) | ||
86 | { | ||
87 | return i2c_smbus_write_byte_data(client, reg, value); | ||
88 | } | ||
89 | |||
90 | static int saa7115_writeregs(struct i2c_client *client, const unsigned char *regs) | ||
91 | { | ||
92 | unsigned char reg, data; | ||
93 | |||
94 | while (*regs != 0x00) { | ||
95 | reg = *(regs++); | ||
96 | data = *(regs++); | ||
97 | if (saa7115_write(client, reg, data) < 0) | ||
98 | return -1; | ||
99 | } | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static inline int saa7115_read(struct i2c_client *client, u8 reg) | ||
104 | { | ||
105 | return i2c_smbus_read_byte_data(client, reg); | ||
106 | } | ||
107 | |||
108 | /* ----------------------------------------------------------------------- */ | ||
109 | |||
110 | /* If a value differs from the Hauppauge driver values, then the comment starts with | ||
111 | 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the | ||
112 | Hauppauge driver sets. */ | ||
113 | |||
114 | static const unsigned char saa7115_init_auto_input[] = { | ||
115 | 0x01, 0x48, /* white peak control disabled */ | ||
116 | 0x03, 0x20, /* was 0x30. 0x20: long vertical blanking */ | ||
117 | 0x04, 0x90, /* analog gain set to 0 */ | ||
118 | 0x05, 0x90, /* analog gain set to 0 */ | ||
119 | 0x06, 0xeb, /* horiz sync begin = -21 */ | ||
120 | 0x07, 0xe0, /* horiz sync stop = -17 */ | ||
121 | 0x0a, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */ | ||
122 | 0x0b, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */ | ||
123 | 0x0c, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */ | ||
124 | 0x0d, 0x00, /* chrominance hue control */ | ||
125 | 0x0f, 0x00, /* chrominance gain control: use automicatic mode */ | ||
126 | 0x10, 0x06, /* chrominance/luminance control: active adaptive combfilter */ | ||
127 | 0x11, 0x00, /* delay control */ | ||
128 | 0x12, 0x9d, /* RTS0 output control: VGATE */ | ||
129 | 0x13, 0x80, /* X-port output control: ITU656 standard mode, RTCO output enable RTCE */ | ||
130 | 0x14, 0x00, /* analog/ADC/auto compatibility control */ | ||
131 | 0x18, 0x40, /* raw data gain 0x00 = nominal */ | ||
132 | 0x19, 0x80, /* raw data offset 0x80 = 0 LSB */ | ||
133 | 0x1a, 0x77, /* color killer level control 0x77 = recommended */ | ||
134 | 0x1b, 0x42, /* misc chroma control 0x42 = recommended */ | ||
135 | 0x1c, 0xa9, /* combfilter control 0xA9 = recommended */ | ||
136 | 0x1d, 0x01, /* combfilter control 0x01 = recommended */ | ||
137 | 0x88, 0xd0, /* reset device */ | ||
138 | 0x88, 0xf0, /* set device programmed, all in operational mode */ | ||
139 | 0x00, 0x00 | ||
140 | }; | ||
141 | |||
142 | static const unsigned char saa7115_cfg_reset_scaler[] = { | ||
143 | 0x87, 0x00, /* disable I-port output */ | ||
144 | 0x88, 0xd0, /* reset scaler */ | ||
145 | 0x88, 0xf0, /* activate scaler */ | ||
146 | 0x87, 0x01, /* enable I-port output */ | ||
147 | 0x00, 0x00 | ||
148 | }; | ||
149 | |||
150 | /* ============== SAA7715 VIDEO templates ============= */ | ||
151 | |||
152 | static const unsigned char saa7115_cfg_60hz_fullres_x[] = { | ||
153 | 0xcc, 0xd0, /* hsize low (output), hor. output window size = 0x2d0 = 720 */ | ||
154 | 0xcd, 0x02, /* hsize hi (output) */ | ||
155 | |||
156 | /* Why not in 60hz-Land, too? */ | ||
157 | 0xd0, 0x01, /* downscale = 1 */ | ||
158 | 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */ | ||
159 | 0xd9, 0x04, | ||
160 | 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
161 | 0xdd, 0x02, /* H-scaling incr chroma */ | ||
162 | |||
163 | 0x00, 0x00 | ||
164 | }; | ||
165 | static const unsigned char saa7115_cfg_60hz_fullres_y[] = { | ||
166 | 0xce, 0xf8, /* vsize low (output), ver. output window size = 248 (but 60hz is 240?) */ | ||
167 | 0xcf, 0x00, /* vsize hi (output) */ | ||
168 | |||
169 | /* Why not in 60hz-Land, too? */ | ||
170 | 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
171 | 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
172 | |||
173 | 0xe0, 0x00, /* V-scaling incr luma low */ | ||
174 | 0xe1, 0x04, /* " hi */ | ||
175 | 0xe2, 0x00, /* V-scaling incr chroma low */ | ||
176 | 0xe3, 0x04, /* " hi */ | ||
177 | |||
178 | 0x00, 0x00 | ||
179 | }; | ||
180 | |||
181 | static const unsigned char saa7115_cfg_60hz_video[] = { | ||
182 | 0x80, 0x00, /* reset tasks */ | ||
183 | 0x88, 0xd0, /* reset scaler */ | ||
184 | |||
185 | 0x15, 0x03, /* VGATE pulse start */ | ||
186 | 0x16, 0x11, /* VGATE pulse stop */ | ||
187 | 0x17, 0x9c, /* VGATE MSB and other values */ | ||
188 | |||
189 | 0x08, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */ | ||
190 | 0x0e, 0x07, /* lots of different stuff... video autodetection is on */ | ||
191 | |||
192 | 0x5a, 0x06, /* Vertical offset, standard 60hz value for ITU656 line counting */ | ||
193 | |||
194 | /* Task A */ | ||
195 | 0x90, 0x80, /* Task Handling Control */ | ||
196 | 0x91, 0x48, /* X-port formats/config */ | ||
197 | 0x92, 0x40, /* Input Ref. signal Def. */ | ||
198 | 0x93, 0x84, /* I-port config */ | ||
199 | 0x94, 0x01, /* hoffset low (input), 0x0002 is minimum */ | ||
200 | 0x95, 0x00, /* hoffset hi (input) */ | ||
201 | 0x96, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
202 | 0x97, 0x02, /* hsize hi (input) */ | ||
203 | 0x98, 0x05, /* voffset low (input) */ | ||
204 | 0x99, 0x00, /* voffset hi (input) */ | ||
205 | 0x9a, 0x0c, /* vsize low (input), 0x0c = 12 */ | ||
206 | 0x9b, 0x00, /* vsize hi (input) */ | ||
207 | 0x9c, 0xa0, /* hsize low (output), 0x05a0 = 1440 */ | ||
208 | 0x9d, 0x05, /* hsize hi (output) */ | ||
209 | 0x9e, 0x0c, /* vsize low (output), 0x0c = 12 */ | ||
210 | 0x9f, 0x00, /* vsize hi (output) */ | ||
211 | |||
212 | /* Task B */ | ||
213 | 0xc0, 0x00, /* Task Handling Control */ | ||
214 | 0xc1, 0x08, /* X-port formats/config */ | ||
215 | 0xc2, 0x00, /* Input Ref. signal Def. */ | ||
216 | 0xc3, 0x80, /* I-port config */ | ||
217 | 0xc4, 0x02, /* hoffset low (input), 0x0002 is minimum */ | ||
218 | 0xc5, 0x00, /* hoffset hi (input) */ | ||
219 | 0xc6, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
220 | 0xc7, 0x02, /* hsize hi (input) */ | ||
221 | 0xc8, 0x12, /* voffset low (input), 0x12 = 18 */ | ||
222 | 0xc9, 0x00, /* voffset hi (input) */ | ||
223 | 0xca, 0xf8, /* vsize low (input), 0xf8 = 248 */ | ||
224 | 0xcb, 0x00, /* vsize hi (input) */ | ||
225 | 0xcc, 0xd0, /* hsize low (output), 0x02d0 = 720 */ | ||
226 | 0xcd, 0x02, /* hsize hi (output) */ | ||
227 | |||
228 | 0xf0, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */ | ||
229 | 0xf1, 0x05, /* low bit with 0xF0 */ | ||
230 | 0xf5, 0xad, /* Set pulse generator register */ | ||
231 | 0xf6, 0x01, | ||
232 | |||
233 | 0x87, 0x00, /* Disable I-port output */ | ||
234 | 0x88, 0xd0, /* reset scaler */ | ||
235 | 0x80, 0x20, /* Activate only task "B", continuous mode (was 0xA0) */ | ||
236 | 0x88, 0xf0, /* activate scaler */ | ||
237 | 0x87, 0x01, /* Enable I-port output */ | ||
238 | 0x00, 0x00 | ||
239 | }; | ||
240 | |||
241 | static const unsigned char saa7115_cfg_50hz_fullres_x[] = { | ||
242 | 0xcc, 0xd0, /* hsize low (output), 720 same as 60hz */ | ||
243 | 0xcd, 0x02, /* hsize hi (output) */ | ||
244 | |||
245 | 0xd0, 0x01, /* down scale = 1 */ | ||
246 | 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */ | ||
247 | 0xd9, 0x04, | ||
248 | 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
249 | 0xdd, 0x02, /* H-scaling incr chroma */ | ||
250 | |||
251 | 0x00, 0x00 | ||
252 | }; | ||
253 | static const unsigned char saa7115_cfg_50hz_fullres_y[] = { | ||
254 | 0xce, 0x20, /* vsize low (output), 0x0120 = 288 */ | ||
255 | 0xcf, 0x01, /* vsize hi (output) */ | ||
256 | |||
257 | 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
258 | 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
259 | |||
260 | 0xe0, 0x00, /* V-scaling incr luma low */ | ||
261 | 0xe1, 0x04, /* " hi */ | ||
262 | 0xe2, 0x00, /* V-scaling incr chroma low */ | ||
263 | 0xe3, 0x04, /* " hi */ | ||
264 | |||
265 | 0x00, 0x00 | ||
266 | }; | ||
267 | |||
268 | static const unsigned char saa7115_cfg_50hz_video[] = { | ||
269 | 0x80, 0x00, /* reset tasks */ | ||
270 | 0x88, 0xd0, /* reset scaler */ | ||
271 | |||
272 | 0x15, 0x37, /* VGATE start */ | ||
273 | 0x16, 0x16, /* VGATE stop */ | ||
274 | 0x17, 0x99, /* VGATE MSB and other values */ | ||
275 | |||
276 | 0x08, 0x28, /* 0x28 = PAL */ | ||
277 | 0x0e, 0x07, /* chrominance control 1 */ | ||
278 | |||
279 | 0x5a, 0x03, /* Vertical offset, standard 50hz value */ | ||
280 | |||
281 | /* Task A */ | ||
282 | 0x90, 0x81, /* Task Handling Control */ | ||
283 | 0x91, 0x48, /* X-port formats/config */ | ||
284 | 0x92, 0x40, /* Input Ref. signal Def. */ | ||
285 | 0x93, 0x84, /* I-port config */ | ||
286 | /* This is weird: the datasheet says that you should use 2 as the minimum value, */ | ||
287 | /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */ | ||
288 | 0x94, 0x00, /* hoffset low (input), 0x0002 is minimum */ | ||
289 | 0x95, 0x00, /* hoffset hi (input) */ | ||
290 | 0x96, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
291 | 0x97, 0x02, /* hsize hi (input) */ | ||
292 | 0x98, 0x03, /* voffset low (input) */ | ||
293 | 0x99, 0x00, /* voffset hi (input) */ | ||
294 | 0x9a, 0x12, /* vsize low (input), 0x12 = 18 */ | ||
295 | 0x9b, 0x00, /* vsize hi (input) */ | ||
296 | 0x9c, 0xa0, /* hsize low (output), 0x05a0 = 1440 */ | ||
297 | 0x9d, 0x05, /* hsize hi (output) */ | ||
298 | 0x9e, 0x12, /* vsize low (output), 0x12 = 18 */ | ||
299 | 0x9f, 0x00, /* vsize hi (output) */ | ||
300 | |||
301 | /* Task B */ | ||
302 | 0xc0, 0x00, /* Task Handling Control */ | ||
303 | 0xc1, 0x08, /* X-port formats/config */ | ||
304 | 0xc2, 0x00, /* Input Ref. signal Def. */ | ||
305 | 0xc3, 0x80, /* I-port config */ | ||
306 | 0xc4, 0x00, /* hoffset low (input), 0x0002 is minimum. See comment at 0x94 above. */ | ||
307 | 0xc5, 0x00, /* hoffset hi (input) */ | ||
308 | 0xc6, 0xd0, /* hsize low (input), 0x02d0 = 720 */ | ||
309 | 0xc7, 0x02, /* hsize hi (input) */ | ||
310 | 0xc8, 0x16, /* voffset low (input), 0x16 = 22 */ | ||
311 | 0xc9, 0x00, /* voffset hi (input) */ | ||
312 | 0xca, 0x20, /* vsize low (input), 0x0120 = 288 */ | ||
313 | 0xcb, 0x01, /* vsize hi (input) */ | ||
314 | 0xcc, 0xd0, /* hsize low (output), 0x02d0 = 720 */ | ||
315 | 0xcd, 0x02, /* hsize hi (output) */ | ||
316 | 0xce, 0x20, /* vsize low (output), 0x0120 = 288 */ | ||
317 | 0xcf, 0x01, /* vsize hi (output) */ | ||
318 | |||
319 | 0xf0, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */ | ||
320 | 0xf1, 0x05, /* low bit with 0xF0, (was 0x05) */ | ||
321 | 0xf5, 0xb0, /* Set pulse generator register */ | ||
322 | 0xf6, 0x01, | ||
323 | |||
324 | 0x87, 0x00, /* Disable I-port output */ | ||
325 | 0x88, 0xd0, /* reset scaler (was 0xD0) */ | ||
326 | 0x80, 0x20, /* Activate only task "B" */ | ||
327 | 0x88, 0xf0, /* activate scaler */ | ||
328 | 0x87, 0x01, /* Enable I-port output */ | ||
329 | 0x00, 0x00 | ||
330 | }; | ||
331 | |||
332 | /* ============== SAA7715 VIDEO templates (end) ======= */ | ||
333 | |||
334 | static const unsigned char saa7115_cfg_vbi_on[] = { | ||
335 | 0x80, 0x00, /* reset tasks */ | ||
336 | 0x88, 0xd0, /* reset scaler */ | ||
337 | 0x80, 0x30, /* Activate both tasks */ | ||
338 | 0x88, 0xf0, /* activate scaler */ | ||
339 | 0x87, 0x01, /* Enable I-port output */ | ||
340 | 0x00, 0x00 | ||
341 | }; | ||
342 | |||
343 | static const unsigned char saa7115_cfg_vbi_off[] = { | ||
344 | 0x80, 0x00, /* reset tasks */ | ||
345 | 0x88, 0xd0, /* reset scaler */ | ||
346 | 0x80, 0x20, /* Activate only task "B" */ | ||
347 | 0x88, 0xf0, /* activate scaler */ | ||
348 | 0x87, 0x01, /* Enable I-port output */ | ||
349 | 0x00, 0x00 | ||
350 | }; | ||
351 | |||
352 | static const unsigned char saa7115_init_misc[] = { | ||
353 | 0x38, 0x03, /* audio stuff */ | ||
354 | 0x39, 0x10, | ||
355 | 0x3a, 0x08, | ||
356 | |||
357 | 0x81, 0x01, /* reg 0x15,0x16 define blanking window */ | ||
358 | 0x82, 0x00, | ||
359 | 0x83, 0x01, /* I port settings */ | ||
360 | 0x84, 0x20, | ||
361 | 0x85, 0x21, | ||
362 | 0x86, 0xc5, | ||
363 | 0x87, 0x01, | ||
364 | |||
365 | /* Task A */ | ||
366 | 0xa0, 0x01, /* down scale = 1 */ | ||
367 | 0xa1, 0x00, /* prescale accumulation length = 1 */ | ||
368 | 0xa2, 0x00, /* dc gain and fir prefilter control */ | ||
369 | 0xa4, 0x80, /* Lum Brightness, nominal value = 0x80 */ | ||
370 | 0xa5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
371 | 0xa6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
372 | 0xa8, 0x00, /* hor lum scaling 0x0200 = 2 zoom */ | ||
373 | 0xa9, 0x02, /* note: 2 x zoom ensures that VBI lines have same length as video lines. */ | ||
374 | 0xaa, 0x00, /* H-phase offset Luma = 0 */ | ||
375 | 0xac, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
376 | 0xad, 0x01, /* H-scaling incr chroma */ | ||
377 | 0xae, 0x00, /* H-phase offset chroma. must be offset luma / 2 */ | ||
378 | |||
379 | 0xb0, 0x00, /* V-scaling incr luma low */ | ||
380 | 0xb1, 0x04, /* " hi */ | ||
381 | 0xb2, 0x00, /* V-scaling incr chroma low */ | ||
382 | 0xb3, 0x04, /* " hi */ | ||
383 | 0xb4, 0x01, /* V-scaling mode control */ | ||
384 | 0xb8, 0x00, /* V-phase offset chroma 00 */ | ||
385 | 0xb9, 0x00, /* V-phase offset chroma 01 */ | ||
386 | 0xba, 0x00, /* V-phase offset chroma 10 */ | ||
387 | 0xbb, 0x00, /* V-phase offset chroma 11 */ | ||
388 | 0xbc, 0x00, /* V-phase offset luma 00 */ | ||
389 | 0xbd, 0x00, /* V-phase offset luma 01 */ | ||
390 | 0xbe, 0x00, /* V-phase offset luma 10 */ | ||
391 | 0xbf, 0x00, /* V-phase offset luma 11 */ | ||
392 | |||
393 | /* Task B */ | ||
394 | 0xd0, 0x01, /* down scale = 1 */ | ||
395 | 0xd1, 0x00, /* prescale accumulation length = 1 */ | ||
396 | 0xd2, 0x00, /* dc gain and fir prefilter control */ | ||
397 | 0xd4, 0x80, /* Lum Brightness, nominal value = 0x80 */ | ||
398 | 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */ | ||
399 | 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */ | ||
400 | 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */ | ||
401 | 0xd9, 0x04, | ||
402 | 0xda, 0x00, /* H-phase offset Luma = 0 */ | ||
403 | 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */ | ||
404 | 0xdd, 0x02, /* H-scaling incr chroma */ | ||
405 | 0xde, 0x00, /* H-phase offset chroma. must be offset luma / 2 */ | ||
406 | |||
407 | 0xe0, 0x00, /* V-scaling incr luma low */ | ||
408 | 0xe1, 0x04, /* " hi */ | ||
409 | 0xe2, 0x00, /* V-scaling incr chroma low */ | ||
410 | 0xe3, 0x04, /* " hi */ | ||
411 | 0xe4, 0x01, /* V-scaling mode control */ | ||
412 | 0xe8, 0x00, /* V-phase offset chroma 00 */ | ||
413 | 0xe9, 0x00, /* V-phase offset chroma 01 */ | ||
414 | 0xea, 0x00, /* V-phase offset chroma 10 */ | ||
415 | 0xeb, 0x00, /* V-phase offset chroma 11 */ | ||
416 | 0xec, 0x00, /* V-phase offset luma 00 */ | ||
417 | 0xed, 0x00, /* V-phase offset luma 01 */ | ||
418 | 0xee, 0x00, /* V-phase offset luma 10 */ | ||
419 | 0xef, 0x00, /* V-phase offset luma 11 */ | ||
420 | |||
421 | 0xf2, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */ | ||
422 | 0xf3, 0x46, | ||
423 | 0xf4, 0x00, | ||
424 | 0xf7, 0x4b, /* not the recommended settings! */ | ||
425 | 0xf8, 0x00, | ||
426 | 0xf9, 0x4b, | ||
427 | 0xfa, 0x00, | ||
428 | 0xfb, 0x4b, | ||
429 | 0xff, 0x88, /* PLL2 lock detection settings: 71 lines 50% phase error */ | ||
430 | |||
431 | /* Turn off VBI */ | ||
432 | 0x40, 0x20, /* No framing code errors allowed. */ | ||
433 | 0x41, 0xff, | ||
434 | 0x42, 0xff, | ||
435 | 0x43, 0xff, | ||
436 | 0x44, 0xff, | ||
437 | 0x45, 0xff, | ||
438 | 0x46, 0xff, | ||
439 | 0x47, 0xff, | ||
440 | 0x48, 0xff, | ||
441 | 0x49, 0xff, | ||
442 | 0x4a, 0xff, | ||
443 | 0x4b, 0xff, | ||
444 | 0x4c, 0xff, | ||
445 | 0x4d, 0xff, | ||
446 | 0x4e, 0xff, | ||
447 | 0x4f, 0xff, | ||
448 | 0x50, 0xff, | ||
449 | 0x51, 0xff, | ||
450 | 0x52, 0xff, | ||
451 | 0x53, 0xff, | ||
452 | 0x54, 0xff, | ||
453 | 0x55, 0xff, | ||
454 | 0x56, 0xff, | ||
455 | 0x57, 0xff, | ||
456 | 0x58, 0x40, | ||
457 | 0x59, 0x47, | ||
458 | 0x5b, 0x83, | ||
459 | 0x5d, 0xbd, | ||
460 | 0x5e, 0x35, | ||
461 | |||
462 | 0x02, 0x84, /* input tuner -> input 4, amplifier active */ | ||
463 | 0x09, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */ | ||
464 | |||
465 | 0x80, 0x20, /* enable task B */ | ||
466 | 0x88, 0xd0, | ||
467 | 0x88, 0xf0, | ||
468 | 0x00, 0x00 | ||
469 | }; | ||
470 | |||
471 | /* ============== SAA7715 AUDIO settings ============= */ | ||
472 | |||
473 | /* 48.0 kHz */ | ||
474 | static const unsigned char saa7115_cfg_48_audio[] = { | ||
475 | 0x34, 0xce, | ||
476 | 0x35, 0xfb, | ||
477 | 0x36, 0x30, | ||
478 | 0x00, 0x00 | ||
479 | }; | ||
480 | |||
481 | /* 44.1 kHz */ | ||
482 | static const unsigned char saa7115_cfg_441_audio[] = { | ||
483 | 0x34, 0xf2, | ||
484 | 0x35, 0x00, | ||
485 | 0x36, 0x2d, | ||
486 | 0x00, 0x00 | ||
487 | }; | ||
488 | |||
489 | /* 32.0 kHz */ | ||
490 | static const unsigned char saa7115_cfg_32_audio[] = { | ||
491 | 0x34, 0xdf, | ||
492 | 0x35, 0xa7, | ||
493 | 0x36, 0x20, | ||
494 | 0x00, 0x00 | ||
495 | }; | ||
496 | |||
497 | /* 48.0 kHz 60hz */ | ||
498 | static const unsigned char saa7115_cfg_60hz_48_audio[] = { | ||
499 | 0x30, 0xcd, | ||
500 | 0x31, 0x20, | ||
501 | 0x32, 0x03, | ||
502 | 0x00, 0x00 | ||
503 | }; | ||
504 | |||
505 | /* 48.0 kHz 50hz */ | ||
506 | static const unsigned char saa7115_cfg_50hz_48_audio[] = { | ||
507 | 0x30, 0x00, | ||
508 | 0x31, 0xc0, | ||
509 | 0x32, 0x03, | ||
510 | 0x00, 0x00 | ||
511 | }; | ||
512 | |||
513 | /* 44.1 kHz 60hz */ | ||
514 | static const unsigned char saa7115_cfg_60hz_441_audio[] = { | ||
515 | 0x30, 0xbc, | ||
516 | 0x31, 0xdf, | ||
517 | 0x32, 0x02, | ||
518 | 0x00, 0x00 | ||
519 | }; | ||
520 | |||
521 | /* 44.1 kHz 50hz */ | ||
522 | static const unsigned char saa7115_cfg_50hz_441_audio[] = { | ||
523 | 0x30, 0x00, | ||
524 | 0x31, 0x72, | ||
525 | 0x32, 0x03, | ||
526 | 0x00, 0x00 | ||
527 | }; | ||
528 | |||
529 | /* 32.0 kHz 60hz */ | ||
530 | static const unsigned char saa7115_cfg_60hz_32_audio[] = { | ||
531 | 0x30, 0xde, | ||
532 | 0x31, 0x15, | ||
533 | 0x32, 0x02, | ||
534 | 0x00, 0x00 | ||
535 | }; | ||
536 | |||
537 | /* 32.0 kHz 50hz */ | ||
538 | static const unsigned char saa7115_cfg_50hz_32_audio[] = { | ||
539 | 0x30, 0x00, | ||
540 | 0x31, 0x80, | ||
541 | 0x32, 0x02, | ||
542 | 0x00, 0x00 | ||
543 | }; | ||
544 | |||
545 | static int saa7115_odd_parity(u8 c) | ||
546 | { | ||
547 | c ^= (c >> 4); | ||
548 | c ^= (c >> 2); | ||
549 | c ^= (c >> 1); | ||
550 | |||
551 | return c & 1; | ||
552 | } | ||
553 | |||
554 | static int saa7115_decode_vps(u8 * dst, u8 * p) | ||
555 | { | ||
556 | static const u8 biphase_tbl[] = { | ||
557 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
558 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
559 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
560 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
561 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
562 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
563 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
564 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
565 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
566 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
567 | 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87, | ||
568 | 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3, | ||
569 | 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85, | ||
570 | 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1, | ||
571 | 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5, | ||
572 | 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1, | ||
573 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
574 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
575 | 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86, | ||
576 | 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2, | ||
577 | 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84, | ||
578 | 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0, | ||
579 | 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4, | ||
580 | 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0, | ||
581 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
582 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
583 | 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96, | ||
584 | 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2, | ||
585 | 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94, | ||
586 | 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0, | ||
587 | 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4, | ||
588 | 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0, | ||
589 | }; | ||
590 | int i; | ||
591 | u8 c, err = 0; | ||
592 | |||
593 | for (i = 0; i < 2 * 13; i += 2) { | ||
594 | err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]]; | ||
595 | c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4); | ||
596 | dst[i / 2] = c; | ||
597 | } | ||
598 | return err & 0xf0; | ||
599 | } | ||
600 | |||
601 | static int saa7115_decode_wss(u8 * p) | ||
602 | { | ||
603 | static const int wss_bits[8] = { | ||
604 | 0, 0, 0, 1, 0, 1, 1, 1 | ||
605 | }; | ||
606 | unsigned char parity; | ||
607 | int wss = 0; | ||
608 | int i; | ||
609 | |||
610 | for (i = 0; i < 16; i++) { | ||
611 | int b1 = wss_bits[p[i] & 7]; | ||
612 | int b2 = wss_bits[(p[i] >> 3) & 7]; | ||
613 | |||
614 | if (b1 == b2) | ||
615 | return -1; | ||
616 | wss |= b2 << i; | ||
617 | } | ||
618 | parity = wss & 15; | ||
619 | parity ^= parity >> 2; | ||
620 | parity ^= parity >> 1; | ||
621 | |||
622 | if (!(parity & 1)) | ||
623 | return -1; | ||
624 | |||
625 | return wss; | ||
626 | } | ||
627 | |||
628 | |||
629 | static int saa7115_set_audio_clock_freq(struct i2c_client *client, enum v4l2_audio_clock_freq freq) | ||
630 | { | ||
631 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
632 | |||
633 | saa7115_dbg("set audio clock freq: %d\n", freq); | ||
634 | switch (freq) { | ||
635 | case V4L2_AUDCLK_32_KHZ: | ||
636 | saa7115_writeregs(client, saa7115_cfg_32_audio); | ||
637 | if (state->std & V4L2_STD_525_60) { | ||
638 | saa7115_writeregs(client, saa7115_cfg_60hz_32_audio); | ||
639 | } else { | ||
640 | saa7115_writeregs(client, saa7115_cfg_50hz_32_audio); | ||
641 | } | ||
642 | break; | ||
643 | case V4L2_AUDCLK_441_KHZ: | ||
644 | saa7115_writeregs(client, saa7115_cfg_441_audio); | ||
645 | if (state->std & V4L2_STD_525_60) { | ||
646 | saa7115_writeregs(client, saa7115_cfg_60hz_441_audio); | ||
647 | } else { | ||
648 | saa7115_writeregs(client, saa7115_cfg_50hz_441_audio); | ||
649 | } | ||
650 | break; | ||
651 | case V4L2_AUDCLK_48_KHZ: | ||
652 | saa7115_writeregs(client, saa7115_cfg_48_audio); | ||
653 | if (state->std & V4L2_STD_525_60) { | ||
654 | saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); | ||
655 | } else { | ||
656 | saa7115_writeregs(client, saa7115_cfg_50hz_48_audio); | ||
657 | } | ||
658 | break; | ||
659 | default: | ||
660 | saa7115_dbg("invalid audio setting %d\n", freq); | ||
661 | return -EINVAL; | ||
662 | } | ||
663 | state->audclk_freq = freq; | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
668 | { | ||
669 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
670 | |||
671 | switch (ctrl->id) { | ||
672 | case V4L2_CID_BRIGHTNESS: | ||
673 | if (ctrl->value < 0 || ctrl->value > 255) { | ||
674 | saa7115_err("invalid brightness setting %d\n", ctrl->value); | ||
675 | return -ERANGE; | ||
676 | } | ||
677 | |||
678 | state->bright = ctrl->value; | ||
679 | saa7115_write(client, 0x0a, state->bright); | ||
680 | break; | ||
681 | |||
682 | case V4L2_CID_CONTRAST: | ||
683 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
684 | saa7115_err("invalid contrast setting %d\n", ctrl->value); | ||
685 | return -ERANGE; | ||
686 | } | ||
687 | |||
688 | state->contrast = ctrl->value; | ||
689 | saa7115_write(client, 0x0b, state->contrast); | ||
690 | break; | ||
691 | |||
692 | case V4L2_CID_SATURATION: | ||
693 | if (ctrl->value < 0 || ctrl->value > 127) { | ||
694 | saa7115_err("invalid saturation setting %d\n", ctrl->value); | ||
695 | return -ERANGE; | ||
696 | } | ||
697 | |||
698 | state->sat = ctrl->value; | ||
699 | saa7115_write(client, 0x0c, state->sat); | ||
700 | break; | ||
701 | |||
702 | case V4L2_CID_HUE: | ||
703 | if (ctrl->value < -127 || ctrl->value > 127) { | ||
704 | saa7115_err("invalid hue setting %d\n", ctrl->value); | ||
705 | return -ERANGE; | ||
706 | } | ||
707 | |||
708 | state->hue = ctrl->value; | ||
709 | saa7115_write(client, 0x0d, state->hue); | ||
710 | break; | ||
711 | } | ||
712 | |||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | static int saa7115_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) | ||
717 | { | ||
718 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
719 | |||
720 | switch (ctrl->id) { | ||
721 | case V4L2_CID_BRIGHTNESS: | ||
722 | ctrl->value = state->bright; | ||
723 | break; | ||
724 | case V4L2_CID_CONTRAST: | ||
725 | ctrl->value = state->contrast; | ||
726 | break; | ||
727 | case V4L2_CID_SATURATION: | ||
728 | ctrl->value = state->sat; | ||
729 | break; | ||
730 | case V4L2_CID_HUE: | ||
731 | ctrl->value = state->hue; | ||
732 | break; | ||
733 | default: | ||
734 | return -EINVAL; | ||
735 | } | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) | ||
741 | { | ||
742 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
743 | int taskb = saa7115_read(client, 0x80) & 0x10; | ||
744 | |||
745 | // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. | ||
746 | if (std & V4L2_STD_525_60) { | ||
747 | saa7115_dbg("decoder set standard 60 Hz\n"); | ||
748 | saa7115_writeregs(client, saa7115_cfg_60hz_video); | ||
749 | } else { | ||
750 | saa7115_dbg("decoder set standard 50 Hz\n"); | ||
751 | saa7115_writeregs(client, saa7115_cfg_50hz_video); | ||
752 | } | ||
753 | |||
754 | state->std = std; | ||
755 | |||
756 | /* restart task B if needed */ | ||
757 | if (taskb && state->ident == V4L2_IDENT_SAA7114) { | ||
758 | saa7115_writeregs(client, saa7115_cfg_vbi_on); | ||
759 | } | ||
760 | |||
761 | /* switch audio mode too! */ | ||
762 | saa7115_set_audio_clock_freq(client, state->audclk_freq); | ||
763 | } | ||
764 | |||
765 | static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client) | ||
766 | { | ||
767 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
768 | |||
769 | return state->std; | ||
770 | } | ||
771 | |||
772 | static void saa7115_log_status(struct i2c_client *client) | ||
773 | { | ||
774 | static const char * const audclk_freq_strs[] = { | ||
775 | "44.1 kHz", | ||
776 | "48 kHz", | ||
777 | "32 kHz" | ||
778 | }; | ||
779 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
780 | int reg1e, reg1f; | ||
781 | int signalOk; | ||
782 | int vcr; | ||
783 | |||
784 | saa7115_info("Audio frequency: %s\n", audclk_freq_strs[state->audclk_freq]); | ||
785 | if (client->name[6] == '4') { | ||
786 | /* status for the saa7114 */ | ||
787 | reg1f = saa7115_read(client, 0x1f); | ||
788 | signalOk = (reg1f & 0xc1) == 0x81; | ||
789 | saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad"); | ||
790 | saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); | ||
791 | return; | ||
792 | } | ||
793 | |||
794 | /* status for the saa7115 */ | ||
795 | reg1e = saa7115_read(client, 0x1e); | ||
796 | reg1f = saa7115_read(client, 0x1f); | ||
797 | |||
798 | signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80; | ||
799 | vcr = !(reg1f & 0x10); | ||
800 | |||
801 | saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); | ||
802 | saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); | ||
803 | |||
804 | switch (reg1e & 0x03) { | ||
805 | case 1: | ||
806 | saa7115_info("Detected format: NTSC\n"); | ||
807 | break; | ||
808 | case 2: | ||
809 | saa7115_info("Detected format: PAL\n"); | ||
810 | break; | ||
811 | case 3: | ||
812 | saa7115_info("Detected format: SECAM\n"); | ||
813 | break; | ||
814 | default: | ||
815 | saa7115_info("Detected format: BW/No color\n"); | ||
816 | break; | ||
817 | } | ||
818 | } | ||
819 | |||
820 | /* setup the sliced VBI lcr registers according to the sliced VBI format */ | ||
821 | static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_format *fmt) | ||
822 | { | ||
823 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
824 | int is_50hz = (state->std & V4L2_STD_625_50); | ||
825 | u8 lcr[24]; | ||
826 | int i, x; | ||
827 | |||
828 | /* saa7114 doesn't yet support VBI */ | ||
829 | if (state->ident == V4L2_IDENT_SAA7114) | ||
830 | return; | ||
831 | |||
832 | for (i = 0; i <= 23; i++) | ||
833 | lcr[i] = 0xff; | ||
834 | |||
835 | if (fmt->service_set == 0) { | ||
836 | /* raw VBI */ | ||
837 | if (is_50hz) | ||
838 | for (i = 6; i <= 23; i++) | ||
839 | lcr[i] = 0xdd; | ||
840 | else | ||
841 | for (i = 10; i <= 21; i++) | ||
842 | lcr[i] = 0xdd; | ||
843 | } else { | ||
844 | /* sliced VBI */ | ||
845 | /* first clear lines that cannot be captured */ | ||
846 | if (is_50hz) { | ||
847 | for (i = 0; i <= 5; i++) | ||
848 | fmt->service_lines[0][i] = | ||
849 | fmt->service_lines[1][i] = 0; | ||
850 | } | ||
851 | else { | ||
852 | for (i = 0; i <= 9; i++) | ||
853 | fmt->service_lines[0][i] = | ||
854 | fmt->service_lines[1][i] = 0; | ||
855 | for (i = 22; i <= 23; i++) | ||
856 | fmt->service_lines[0][i] = | ||
857 | fmt->service_lines[1][i] = 0; | ||
858 | } | ||
859 | |||
860 | /* Now set the lcr values according to the specified service */ | ||
861 | for (i = 6; i <= 23; i++) { | ||
862 | lcr[i] = 0; | ||
863 | for (x = 0; x <= 1; x++) { | ||
864 | switch (fmt->service_lines[1-x][i]) { | ||
865 | case 0: | ||
866 | lcr[i] |= 0xf << (4 * x); | ||
867 | break; | ||
868 | case V4L2_SLICED_TELETEXT_B: | ||
869 | lcr[i] |= 1 << (4 * x); | ||
870 | break; | ||
871 | case V4L2_SLICED_CAPTION_525: | ||
872 | lcr[i] |= 4 << (4 * x); | ||
873 | break; | ||
874 | case V4L2_SLICED_WSS_625: | ||
875 | lcr[i] |= 5 << (4 * x); | ||
876 | break; | ||
877 | case V4L2_SLICED_VPS: | ||
878 | lcr[i] |= 7 << (4 * x); | ||
879 | break; | ||
880 | } | ||
881 | } | ||
882 | } | ||
883 | } | ||
884 | |||
885 | /* write the lcr registers */ | ||
886 | for (i = 2; i <= 23; i++) { | ||
887 | saa7115_write(client, i - 2 + 0x41, lcr[i]); | ||
888 | } | ||
889 | |||
890 | /* enable/disable raw VBI capturing */ | ||
891 | saa7115_writeregs(client, fmt->service_set == 0 ? saa7115_cfg_vbi_on : saa7115_cfg_vbi_off); | ||
892 | } | ||
893 | |||
894 | static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
895 | { | ||
896 | static u16 lcr2vbi[] = { | ||
897 | 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ | ||
898 | 0, V4L2_SLICED_CAPTION_525, /* 4 */ | ||
899 | V4L2_SLICED_WSS_625, 0, /* 5 */ | ||
900 | V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */ | ||
901 | 0, 0, 0, 0 | ||
902 | }; | ||
903 | struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced; | ||
904 | int i; | ||
905 | |||
906 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
907 | return -EINVAL; | ||
908 | memset(sliced, 0, sizeof(*sliced)); | ||
909 | /* done if using raw VBI */ | ||
910 | if (saa7115_read(client, 0x80) & 0x10) | ||
911 | return 0; | ||
912 | for (i = 2; i <= 23; i++) { | ||
913 | u8 v = saa7115_read(client, i - 2 + 0x41); | ||
914 | |||
915 | sliced->service_lines[0][i] = lcr2vbi[v >> 4]; | ||
916 | sliced->service_lines[1][i] = lcr2vbi[v & 0xf]; | ||
917 | sliced->service_set |= | ||
918 | sliced->service_lines[0][i] | sliced->service_lines[1][i]; | ||
919 | } | ||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) | ||
924 | { | ||
925 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
926 | struct v4l2_pix_format *pix; | ||
927 | int HPSC, HFSC; | ||
928 | int VSCY, Vsrc; | ||
929 | int is_50hz = state->std & V4L2_STD_625_50; | ||
930 | |||
931 | if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
932 | saa7115_set_lcr(client, &fmt->fmt.sliced); | ||
933 | return 0; | ||
934 | } | ||
935 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
936 | return -EINVAL; | ||
937 | |||
938 | pix = &(fmt->fmt.pix); | ||
939 | |||
940 | saa7115_dbg("decoder set size\n"); | ||
941 | |||
942 | /* FIXME need better bounds checking here */ | ||
943 | if ((pix->width < 1) || (pix->width > 1440)) | ||
944 | return -EINVAL; | ||
945 | if ((pix->height < 1) || (pix->height > 960)) | ||
946 | return -EINVAL; | ||
947 | |||
948 | /* probably have a valid size, let's set it */ | ||
949 | /* Set output width/height */ | ||
950 | /* width */ | ||
951 | saa7115_write(client, 0xcc, (u8) (pix->width & 0xff)); | ||
952 | saa7115_write(client, 0xcd, (u8) ((pix->width >> 8) & 0xff)); | ||
953 | /* height */ | ||
954 | saa7115_write(client, 0xce, (u8) (pix->height & 0xff)); | ||
955 | saa7115_write(client, 0xcf, (u8) ((pix->height >> 8) & 0xff)); | ||
956 | |||
957 | /* Scaling settings */ | ||
958 | /* Hprescaler is floor(inres/outres) */ | ||
959 | /* FIXME hardcoding input res */ | ||
960 | if (pix->width != 720) { | ||
961 | HPSC = (int)(720 / pix->width); | ||
962 | /* 0 is not allowed (div. by zero) */ | ||
963 | HPSC = HPSC ? HPSC : 1; | ||
964 | HFSC = (int)((1024 * 720) / (HPSC * pix->width)); | ||
965 | |||
966 | saa7115_dbg("Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC); | ||
967 | /* FIXME hardcodes to "Task B" | ||
968 | * write H prescaler integer */ | ||
969 | saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f)); | ||
970 | |||
971 | /* write H fine-scaling (luminance) */ | ||
972 | saa7115_write(client, 0xd8, (u8) (HFSC & 0xff)); | ||
973 | saa7115_write(client, 0xd9, (u8) ((HFSC >> 8) & 0xff)); | ||
974 | /* write H fine-scaling (chrominance) | ||
975 | * must be lum/2, so i'll just bitshift :) */ | ||
976 | saa7115_write(client, 0xDC, (u8) ((HFSC >> 1) & 0xff)); | ||
977 | saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff)); | ||
978 | } else { | ||
979 | if (is_50hz) { | ||
980 | saa7115_dbg("Setting full 50hz width\n"); | ||
981 | saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x); | ||
982 | } else { | ||
983 | saa7115_dbg("Setting full 60hz width\n"); | ||
984 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); | ||
985 | } | ||
986 | } | ||
987 | |||
988 | Vsrc = is_50hz ? 576 : 480; | ||
989 | |||
990 | if (pix->height != Vsrc) { | ||
991 | VSCY = (int)((1024 * Vsrc) / pix->height); | ||
992 | saa7115_dbg("Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY); | ||
993 | |||
994 | /* Correct Contrast and Luminance */ | ||
995 | saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY)); | ||
996 | saa7115_write(client, 0xd6, (u8) (64 * 1024 / VSCY)); | ||
997 | |||
998 | /* write V fine-scaling (luminance) */ | ||
999 | saa7115_write(client, 0xe0, (u8) (VSCY & 0xff)); | ||
1000 | saa7115_write(client, 0xe1, (u8) ((VSCY >> 8) & 0xff)); | ||
1001 | /* write V fine-scaling (chrominance) */ | ||
1002 | saa7115_write(client, 0xe2, (u8) (VSCY & 0xff)); | ||
1003 | saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff)); | ||
1004 | } else { | ||
1005 | if (is_50hz) { | ||
1006 | saa7115_dbg("Setting full 50Hz height\n"); | ||
1007 | saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y); | ||
1008 | } else { | ||
1009 | saa7115_dbg("Setting full 60hz height\n"); | ||
1010 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); | ||
1015 | return 0; | ||
1016 | } | ||
1017 | |||
1018 | /* Decode the sliced VBI data stream as created by the saa7115. | ||
1019 | The format is described in the saa7115 datasheet in Tables 25 and 26 | ||
1020 | and in Figure 33. | ||
1021 | The current implementation uses SAV/EAV codes and not the ancillary data | ||
1022 | headers. The vbi->p pointer points to the SDID byte right after the SAV | ||
1023 | code. */ | ||
1024 | static void saa7115_decode_vbi_line(struct i2c_client *client, | ||
1025 | struct v4l2_decode_vbi_line *vbi) | ||
1026 | { | ||
1027 | static const char vbi_no_data_pattern[] = { | ||
1028 | 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0 | ||
1029 | }; | ||
1030 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
1031 | u8 *p = vbi->p; | ||
1032 | u32 wss; | ||
1033 | int id1, id2; /* the ID1 and ID2 bytes from the internal header */ | ||
1034 | |||
1035 | vbi->type = 0; /* mark result as a failure */ | ||
1036 | id1 = p[2]; | ||
1037 | id2 = p[3]; | ||
1038 | /* Note: the field bit is inverted for 60 Hz video */ | ||
1039 | if (state->std & V4L2_STD_525_60) | ||
1040 | id1 ^= 0x40; | ||
1041 | |||
1042 | /* Skip internal header, p now points to the start of the payload */ | ||
1043 | p += 4; | ||
1044 | vbi->p = p; | ||
1045 | |||
1046 | /* calculate field and line number of the VBI packet (1-23) */ | ||
1047 | vbi->is_second_field = ((id1 & 0x40) != 0); | ||
1048 | vbi->line = (id1 & 0x3f) << 3; | ||
1049 | vbi->line |= (id2 & 0x70) >> 4; | ||
1050 | |||
1051 | /* Obtain data type */ | ||
1052 | id2 &= 0xf; | ||
1053 | |||
1054 | /* If the VBI slicer does not detect any signal it will fill up | ||
1055 | the payload buffer with 0xa0 bytes. */ | ||
1056 | if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern))) | ||
1057 | return; | ||
1058 | |||
1059 | /* decode payloads */ | ||
1060 | switch (id2) { | ||
1061 | case 1: | ||
1062 | vbi->type = V4L2_SLICED_TELETEXT_B; | ||
1063 | break; | ||
1064 | case 4: | ||
1065 | if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1])) | ||
1066 | return; | ||
1067 | vbi->type = V4L2_SLICED_CAPTION_525; | ||
1068 | break; | ||
1069 | case 5: | ||
1070 | wss = saa7115_decode_wss(p); | ||
1071 | if (wss == -1) | ||
1072 | return; | ||
1073 | p[0] = wss & 0xff; | ||
1074 | p[1] = wss >> 8; | ||
1075 | vbi->type = V4L2_SLICED_WSS_625; | ||
1076 | break; | ||
1077 | case 7: | ||
1078 | if (saa7115_decode_vps(p, p) != 0) | ||
1079 | return; | ||
1080 | vbi->type = V4L2_SLICED_VPS; | ||
1081 | break; | ||
1082 | default: | ||
1083 | return; | ||
1084 | } | ||
1085 | } | ||
1086 | |||
1087 | /* ============ SAA7115 AUDIO settings (end) ============= */ | ||
1088 | |||
1089 | static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
1090 | { | ||
1091 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
1092 | int *iarg = arg; | ||
1093 | |||
1094 | /* ioctls to allow direct access to the saa7115 registers for testing */ | ||
1095 | switch (cmd) { | ||
1096 | case VIDIOC_S_FMT: | ||
1097 | return saa7115_set_v4lfmt(client, (struct v4l2_format *)arg); | ||
1098 | |||
1099 | case VIDIOC_G_FMT: | ||
1100 | return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg); | ||
1101 | |||
1102 | case VIDIOC_INT_AUDIO_CLOCK_FREQ: | ||
1103 | return saa7115_set_audio_clock_freq(client, *(enum v4l2_audio_clock_freq *)arg); | ||
1104 | |||
1105 | case VIDIOC_G_TUNER: | ||
1106 | { | ||
1107 | struct v4l2_tuner *vt = arg; | ||
1108 | int status; | ||
1109 | |||
1110 | status = saa7115_read(client, 0x1f); | ||
1111 | |||
1112 | saa7115_dbg("status: 0x%02x\n", status); | ||
1113 | vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0; | ||
1114 | break; | ||
1115 | } | ||
1116 | |||
1117 | case VIDIOC_LOG_STATUS: | ||
1118 | saa7115_log_status(client); | ||
1119 | break; | ||
1120 | |||
1121 | case VIDIOC_G_CTRL: | ||
1122 | return saa7115_get_v4lctrl(client, (struct v4l2_control *)arg); | ||
1123 | |||
1124 | case VIDIOC_S_CTRL: | ||
1125 | return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg); | ||
1126 | |||
1127 | case VIDIOC_G_STD: | ||
1128 | *(v4l2_std_id *)arg = saa7115_get_v4lstd(client); | ||
1129 | break; | ||
1130 | |||
1131 | case VIDIOC_S_STD: | ||
1132 | saa7115_set_v4lstd(client, *(v4l2_std_id *)arg); | ||
1133 | break; | ||
1134 | |||
1135 | case VIDIOC_G_INPUT: | ||
1136 | *(int *)arg = state->input; | ||
1137 | break; | ||
1138 | |||
1139 | case VIDIOC_S_INPUT: | ||
1140 | saa7115_dbg("decoder set input %d\n", *iarg); | ||
1141 | /* inputs from 0-9 are available */ | ||
1142 | if (*iarg < 0 || *iarg > 9) { | ||
1143 | return -EINVAL; | ||
1144 | } | ||
1145 | |||
1146 | if (state->input == *iarg) | ||
1147 | break; | ||
1148 | saa7115_dbg("now setting %s input\n", | ||
1149 | *iarg >= 6 ? "S-Video" : "Composite"); | ||
1150 | state->input = *iarg; | ||
1151 | |||
1152 | /* select mode */ | ||
1153 | saa7115_write(client, 0x02, | ||
1154 | (saa7115_read(client, 0x02) & 0xf0) | | ||
1155 | state->input); | ||
1156 | |||
1157 | /* bypass chrominance trap for modes 6..9 */ | ||
1158 | saa7115_write(client, 0x09, | ||
1159 | (saa7115_read(client, 0x09) & 0x7f) | | ||
1160 | (state->input < 6 ? 0x0 : 0x80)); | ||
1161 | break; | ||
1162 | |||
1163 | case VIDIOC_STREAMON: | ||
1164 | case VIDIOC_STREAMOFF: | ||
1165 | saa7115_dbg("%s output\n", | ||
1166 | (cmd == VIDIOC_STREAMON) ? "enable" : "disable"); | ||
1167 | |||
1168 | if (state->enable != (cmd == VIDIOC_STREAMON)) { | ||
1169 | state->enable = (cmd == VIDIOC_STREAMON); | ||
1170 | saa7115_write(client, 0x87, state->enable); | ||
1171 | } | ||
1172 | break; | ||
1173 | |||
1174 | case VIDIOC_INT_DECODE_VBI_LINE: | ||
1175 | saa7115_decode_vbi_line(client, arg); | ||
1176 | break; | ||
1177 | |||
1178 | case VIDIOC_INT_RESET: | ||
1179 | saa7115_dbg("decoder RESET\n"); | ||
1180 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); | ||
1181 | break; | ||
1182 | |||
1183 | case VIDIOC_INT_G_VBI_DATA: | ||
1184 | { | ||
1185 | struct v4l2_sliced_vbi_data *data = arg; | ||
1186 | |||
1187 | switch (data->id) { | ||
1188 | case V4L2_SLICED_WSS_625: | ||
1189 | if (saa7115_read(client, 0x6b) & 0xc0) | ||
1190 | return -EIO; | ||
1191 | data->data[0] = saa7115_read(client, 0x6c); | ||
1192 | data->data[1] = saa7115_read(client, 0x6d); | ||
1193 | return 0; | ||
1194 | case V4L2_SLICED_CAPTION_525: | ||
1195 | if (data->field == 0) { | ||
1196 | /* CC */ | ||
1197 | if (saa7115_read(client, 0x66) & 0xc0) | ||
1198 | return -EIO; | ||
1199 | data->data[0] = saa7115_read(client, 0x67); | ||
1200 | data->data[1] = saa7115_read(client, 0x68); | ||
1201 | return 0; | ||
1202 | } | ||
1203 | /* XDS */ | ||
1204 | if (saa7115_read(client, 0x66) & 0x30) | ||
1205 | return -EIO; | ||
1206 | data->data[0] = saa7115_read(client, 0x69); | ||
1207 | data->data[1] = saa7115_read(client, 0x6a); | ||
1208 | return 0; | ||
1209 | default: | ||
1210 | return -EINVAL; | ||
1211 | } | ||
1212 | break; | ||
1213 | } | ||
1214 | |||
1215 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1216 | case VIDIOC_INT_G_REGISTER: | ||
1217 | { | ||
1218 | struct v4l2_register *reg = arg; | ||
1219 | |||
1220 | if (reg->i2c_id != I2C_DRIVERID_SAA711X) | ||
1221 | return -EINVAL; | ||
1222 | reg->val = saa7115_read(client, reg->reg & 0xff); | ||
1223 | break; | ||
1224 | } | ||
1225 | |||
1226 | case VIDIOC_INT_S_REGISTER: | ||
1227 | { | ||
1228 | struct v4l2_register *reg = arg; | ||
1229 | |||
1230 | if (reg->i2c_id != I2C_DRIVERID_SAA711X) | ||
1231 | return -EINVAL; | ||
1232 | if (!capable(CAP_SYS_ADMIN)) | ||
1233 | return -EPERM; | ||
1234 | saa7115_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
1235 | break; | ||
1236 | } | ||
1237 | #endif | ||
1238 | |||
1239 | case VIDIOC_INT_G_CHIP_IDENT: | ||
1240 | *iarg = state->ident; | ||
1241 | break; | ||
1242 | |||
1243 | default: | ||
1244 | return -EINVAL; | ||
1245 | } | ||
1246 | |||
1247 | return 0; | ||
1248 | } | ||
1249 | |||
1250 | /* ----------------------------------------------------------------------- */ | ||
1251 | |||
1252 | static struct i2c_driver i2c_driver_saa7115; | ||
1253 | |||
1254 | static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) | ||
1255 | { | ||
1256 | struct i2c_client *client; | ||
1257 | struct saa7115_state *state; | ||
1258 | u8 chip_id; | ||
1259 | |||
1260 | /* Check if the adapter supports the needed features */ | ||
1261 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
1262 | return 0; | ||
1263 | |||
1264 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
1265 | if (client == 0) | ||
1266 | return -ENOMEM; | ||
1267 | memset(client, 0, sizeof(struct i2c_client)); | ||
1268 | client->addr = address; | ||
1269 | client->adapter = adapter; | ||
1270 | client->driver = &i2c_driver_saa7115; | ||
1271 | client->flags = I2C_CLIENT_ALLOW_USE; | ||
1272 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); | ||
1273 | |||
1274 | saa7115_dbg("detecting saa7115 client on address 0x%x\n", address << 1); | ||
1275 | |||
1276 | saa7115_write(client, 0, 5); | ||
1277 | chip_id = saa7115_read(client, 0) & 0x0f; | ||
1278 | if (chip_id != 4 && chip_id != 5) { | ||
1279 | saa7115_dbg("saa7115 not found\n"); | ||
1280 | kfree(client); | ||
1281 | return 0; | ||
1282 | } | ||
1283 | if (chip_id == 4) { | ||
1284 | snprintf(client->name, sizeof(client->name) - 1, "saa7114"); | ||
1285 | } | ||
1286 | saa7115_info("saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name); | ||
1287 | |||
1288 | state = kmalloc(sizeof(struct saa7115_state), GFP_KERNEL); | ||
1289 | i2c_set_clientdata(client, state); | ||
1290 | if (state == NULL) { | ||
1291 | kfree(client); | ||
1292 | return -ENOMEM; | ||
1293 | } | ||
1294 | memset(state, 0, sizeof(struct saa7115_state)); | ||
1295 | state->std = V4L2_STD_NTSC; | ||
1296 | state->input = -1; | ||
1297 | state->enable = 1; | ||
1298 | state->bright = 128; | ||
1299 | state->contrast = 64; | ||
1300 | state->hue = 0; | ||
1301 | state->sat = 64; | ||
1302 | state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115; | ||
1303 | state->audclk_freq = V4L2_AUDCLK_48_KHZ; | ||
1304 | |||
1305 | saa7115_dbg("writing init values\n"); | ||
1306 | |||
1307 | /* init to 60hz/48khz */ | ||
1308 | saa7115_writeregs(client, saa7115_init_auto_input); | ||
1309 | saa7115_writeregs(client, saa7115_init_misc); | ||
1310 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); | ||
1311 | saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); | ||
1312 | saa7115_writeregs(client, saa7115_cfg_60hz_video); | ||
1313 | saa7115_writeregs(client, saa7115_cfg_48_audio); | ||
1314 | saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); | ||
1315 | saa7115_writeregs(client, saa7115_cfg_reset_scaler); | ||
1316 | |||
1317 | i2c_attach_client(client); | ||
1318 | |||
1319 | saa7115_dbg("status: (1E) 0x%02x, (1F) 0x%02x\n", | ||
1320 | saa7115_read(client, 0x1e), saa7115_read(client, 0x1f)); | ||
1321 | |||
1322 | return 0; | ||
1323 | } | ||
1324 | |||
1325 | static int saa7115_probe(struct i2c_adapter *adapter) | ||
1326 | { | ||
1327 | #ifdef I2C_CLASS_TV_ANALOG | ||
1328 | if (adapter->class & I2C_CLASS_TV_ANALOG) | ||
1329 | #else | ||
1330 | if (adapter->id == I2C_HW_B_BT848) | ||
1331 | #endif | ||
1332 | return i2c_probe(adapter, &addr_data, &saa7115_attach); | ||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1336 | static int saa7115_detach(struct i2c_client *client) | ||
1337 | { | ||
1338 | struct saa7115_state *state = i2c_get_clientdata(client); | ||
1339 | int err; | ||
1340 | |||
1341 | err = i2c_detach_client(client); | ||
1342 | if (err) { | ||
1343 | return err; | ||
1344 | } | ||
1345 | |||
1346 | kfree(state); | ||
1347 | kfree(client); | ||
1348 | return 0; | ||
1349 | } | ||
1350 | |||
1351 | /* ----------------------------------------------------------------------- */ | ||
1352 | |||
1353 | /* i2c implementation */ | ||
1354 | static struct i2c_driver i2c_driver_saa7115 = { | ||
1355 | .name = "saa7115", | ||
1356 | .id = I2C_DRIVERID_SAA711X, | ||
1357 | .flags = I2C_DF_NOTIFY, | ||
1358 | .attach_adapter = saa7115_probe, | ||
1359 | .detach_client = saa7115_detach, | ||
1360 | .command = saa7115_command, | ||
1361 | .owner = THIS_MODULE, | ||
1362 | }; | ||
1363 | |||
1364 | |||
1365 | static int __init saa7115_init_module(void) | ||
1366 | { | ||
1367 | return i2c_add_driver(&i2c_driver_saa7115); | ||
1368 | } | ||
1369 | |||
1370 | static void __exit saa7115_cleanup_module(void) | ||
1371 | { | ||
1372 | i2c_del_driver(&i2c_driver_saa7115); | ||
1373 | } | ||
1374 | |||
1375 | module_init(saa7115_init_module); | ||
1376 | module_exit(saa7115_cleanup_module); | ||
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 9aa8827de2c3..25b30f352d84 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
37 | #include <asm/page.h> | 37 | #include <asm/page.h> |
38 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
39 | #include <asm/segment.h> | ||
40 | #include <linux/types.h> | 39 | #include <linux/types.h> |
41 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
42 | #include <linux/videodev.h> | 41 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c new file mode 100644 index 000000000000..843431f10e3b --- /dev/null +++ b/drivers/media/video/saa7127.c | |||
@@ -0,0 +1,849 @@ | |||
1 | /* | ||
2 | * saa7127 - Philips SAA7127/SAA7129 video encoder driver | ||
3 | * | ||
4 | * Copyright (C) 2003 Roy Bulter <rbulter@hetnet.nl> | ||
5 | * | ||
6 | * Based on SAA7126 video encoder driver by Gillem & Andreas Oberritter | ||
7 | * | ||
8 | * Copyright (C) 2000-2001 Gillem <htoa@gmx.net> | ||
9 | * Copyright (C) 2002 Andreas Oberritter <obi@saftware.de> | ||
10 | * | ||
11 | * Based on Stadis 4:2:2 MPEG-2 Decoder Driver by Nathan Laredo | ||
12 | * | ||
13 | * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org> | ||
14 | * | ||
15 | * This driver is designed for the Hauppauge 250/350 Linux driver | ||
16 | * from the ivtv Project | ||
17 | * | ||
18 | * Copyright (C) 2003 Kevin Thayer <nufan_wfk@yahoo.com> | ||
19 | * | ||
20 | * Dual output support: | ||
21 | * Copyright (C) 2004 Eric Varsanyi | ||
22 | * | ||
23 | * NTSC Tuning and 7.5 IRE Setup | ||
24 | * Copyright (C) 2004 Chris Kennedy <c@groovy.org> | ||
25 | * | ||
26 | * VBI additions & cleanup: | ||
27 | * Copyright (C) 2004, 2005 Hans Verkuil <hverkuil@xs4all.nl> | ||
28 | * | ||
29 | * Note: the saa7126 is identical to the saa7127, and the saa7128 is | ||
30 | * identical to the saa7129, except that the saa7126 and saa7128 have | ||
31 | * macrovision anti-taping support. This driver will almost certainly | ||
32 | * work find for those chips, except of course for the missing anti-taping | ||
33 | * support. | ||
34 | * | ||
35 | * This program is free software; you can redistribute it and/or modify | ||
36 | * it under the terms of the GNU General Public License as published by | ||
37 | * the Free Software Foundation; either version 2 of the License, or | ||
38 | * (at your option) any later version. | ||
39 | * | ||
40 | * This program is distributed in the hope that it will be useful, | ||
41 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
42 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
43 | * GNU General Public License for more details. | ||
44 | * | ||
45 | * You should have received a copy of the GNU General Public License | ||
46 | * along with this program; if not, write to the Free Software | ||
47 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
48 | */ | ||
49 | |||
50 | |||
51 | #include <linux/kernel.h> | ||
52 | #include <linux/module.h> | ||
53 | #include <linux/slab.h> | ||
54 | #include <linux/i2c.h> | ||
55 | #include <linux/videodev2.h> | ||
56 | #include <media/v4l2-common.h> | ||
57 | |||
58 | static int debug = 0; | ||
59 | static int test_image = 0; | ||
60 | |||
61 | MODULE_DESCRIPTION("Philips SAA7127/9 video encoder driver"); | ||
62 | MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); | ||
63 | MODULE_LICENSE("GPL"); | ||
64 | module_param(debug, int, 0644); | ||
65 | module_param(test_image, int, 0644); | ||
66 | MODULE_PARM_DESC(debug, "debug level (0-2)"); | ||
67 | MODULE_PARM_DESC(test_image, "test_image (0-1)"); | ||
68 | |||
69 | #define saa7127_dbg(fmt, arg...) \ | ||
70 | do { \ | ||
71 | if (debug >= 1) \ | ||
72 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
73 | i2c_adapter_id(client->adapter), client->addr , ## arg); \ | ||
74 | } while (0) | ||
75 | |||
76 | /* High volume debug. Use with care. */ | ||
77 | #define saa7127_dbg_highvol(fmt, arg...) \ | ||
78 | do { \ | ||
79 | if (debug == 2) \ | ||
80 | printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \ | ||
81 | i2c_adapter_id(client->adapter), client->addr , ## arg); \ | ||
82 | } while (0) | ||
83 | |||
84 | #define saa7127_err(fmt, arg...) do { \ | ||
85 | printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ | ||
86 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
87 | #define saa7127_info(fmt, arg...) do { \ | ||
88 | printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ | ||
89 | i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) | ||
90 | |||
91 | static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; | ||
92 | |||
93 | |||
94 | I2C_CLIENT_INSMOD; | ||
95 | |||
96 | /* | ||
97 | * SAA7127 registers | ||
98 | */ | ||
99 | |||
100 | #define SAA7127_REG_STATUS 0x00 | ||
101 | #define SAA7127_REG_WIDESCREEN_CONFIG 0x26 | ||
102 | #define SAA7127_REG_WIDESCREEN_ENABLE 0x27 | ||
103 | #define SAA7127_REG_BURST_START 0x28 | ||
104 | #define SAA7127_REG_BURST_END 0x29 | ||
105 | #define SAA7127_REG_COPYGEN_0 0x2a | ||
106 | #define SAA7127_REG_COPYGEN_1 0x2b | ||
107 | #define SAA7127_REG_COPYGEN_2 0x2c | ||
108 | #define SAA7127_REG_OUTPUT_PORT_CONTROL 0x2d | ||
109 | #define SAA7127_REG_GAIN_LUMINANCE_RGB 0x38 | ||
110 | #define SAA7127_REG_GAIN_COLORDIFF_RGB 0x39 | ||
111 | #define SAA7127_REG_INPUT_PORT_CONTROL_1 0x3a | ||
112 | #define SAA7129_REG_FADE_KEY_COL2 0x4f | ||
113 | #define SAA7127_REG_CHROMA_PHASE 0x5a | ||
114 | #define SAA7127_REG_GAINU 0x5b | ||
115 | #define SAA7127_REG_GAINV 0x5c | ||
116 | #define SAA7127_REG_BLACK_LEVEL 0x5d | ||
117 | #define SAA7127_REG_BLANKING_LEVEL 0x5e | ||
118 | #define SAA7127_REG_VBI_BLANKING 0x5f | ||
119 | #define SAA7127_REG_DAC_CONTROL 0x61 | ||
120 | #define SAA7127_REG_BURST_AMP 0x62 | ||
121 | #define SAA7127_REG_SUBC3 0x63 | ||
122 | #define SAA7127_REG_SUBC2 0x64 | ||
123 | #define SAA7127_REG_SUBC1 0x65 | ||
124 | #define SAA7127_REG_SUBC0 0x66 | ||
125 | #define SAA7127_REG_LINE_21_ODD_0 0x67 | ||
126 | #define SAA7127_REG_LINE_21_ODD_1 0x68 | ||
127 | #define SAA7127_REG_LINE_21_EVEN_0 0x69 | ||
128 | #define SAA7127_REG_LINE_21_EVEN_1 0x6a | ||
129 | #define SAA7127_REG_RCV_PORT_CONTROL 0x6b | ||
130 | #define SAA7127_REG_VTRIG 0x6c | ||
131 | #define SAA7127_REG_HTRIG_HI 0x6d | ||
132 | #define SAA7127_REG_MULTI 0x6e | ||
133 | #define SAA7127_REG_CLOSED_CAPTION 0x6f | ||
134 | #define SAA7127_REG_RCV2_OUTPUT_START 0x70 | ||
135 | #define SAA7127_REG_RCV2_OUTPUT_END 0x71 | ||
136 | #define SAA7127_REG_RCV2_OUTPUT_MSBS 0x72 | ||
137 | #define SAA7127_REG_TTX_REQUEST_H_START 0x73 | ||
138 | #define SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH 0x74 | ||
139 | #define SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT 0x75 | ||
140 | #define SAA7127_REG_TTX_ODD_REQ_VERT_START 0x76 | ||
141 | #define SAA7127_REG_TTX_ODD_REQ_VERT_END 0x77 | ||
142 | #define SAA7127_REG_TTX_EVEN_REQ_VERT_START 0x78 | ||
143 | #define SAA7127_REG_TTX_EVEN_REQ_VERT_END 0x79 | ||
144 | #define SAA7127_REG_FIRST_ACTIVE 0x7a | ||
145 | #define SAA7127_REG_LAST_ACTIVE 0x7b | ||
146 | #define SAA7127_REG_MSB_VERTICAL 0x7c | ||
147 | #define SAA7127_REG_DISABLE_TTX_LINE_LO_0 0x7e | ||
148 | #define SAA7127_REG_DISABLE_TTX_LINE_LO_1 0x7f | ||
149 | |||
150 | /* | ||
151 | ********************************************************************** | ||
152 | * | ||
153 | * Arrays with configuration parameters for the SAA7127 | ||
154 | * | ||
155 | ********************************************************************** | ||
156 | */ | ||
157 | |||
158 | struct i2c_reg_value { | ||
159 | unsigned char reg; | ||
160 | unsigned char value; | ||
161 | }; | ||
162 | |||
163 | static const struct i2c_reg_value saa7129_init_config_extra[] = { | ||
164 | { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x38 }, | ||
165 | { SAA7127_REG_VTRIG, 0xfa }, | ||
166 | }; | ||
167 | |||
168 | static const struct i2c_reg_value saa7127_init_config_common[] = { | ||
169 | { SAA7127_REG_WIDESCREEN_CONFIG, 0x0d }, | ||
170 | { SAA7127_REG_WIDESCREEN_ENABLE, 0x00 }, | ||
171 | { SAA7127_REG_COPYGEN_0, 0x77 }, | ||
172 | { SAA7127_REG_COPYGEN_1, 0x41 }, | ||
173 | { SAA7127_REG_COPYGEN_2, 0x00 }, /* Macrovision enable/disable */ | ||
174 | { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x9e }, | ||
175 | { SAA7127_REG_GAIN_LUMINANCE_RGB, 0x00 }, | ||
176 | { SAA7127_REG_GAIN_COLORDIFF_RGB, 0x00 }, | ||
177 | { SAA7127_REG_INPUT_PORT_CONTROL_1, 0x80 }, /* for color bars */ | ||
178 | { SAA7127_REG_LINE_21_ODD_0, 0x77 }, | ||
179 | { SAA7127_REG_LINE_21_ODD_1, 0x41 }, | ||
180 | { SAA7127_REG_LINE_21_EVEN_0, 0x88 }, | ||
181 | { SAA7127_REG_LINE_21_EVEN_1, 0x41 }, | ||
182 | { SAA7127_REG_RCV_PORT_CONTROL, 0x12 }, | ||
183 | { SAA7127_REG_VTRIG, 0xf9 }, | ||
184 | { SAA7127_REG_HTRIG_HI, 0x00 }, | ||
185 | { SAA7127_REG_RCV2_OUTPUT_START, 0x41 }, | ||
186 | { SAA7127_REG_RCV2_OUTPUT_END, 0xc3 }, | ||
187 | { SAA7127_REG_RCV2_OUTPUT_MSBS, 0x00 }, | ||
188 | { SAA7127_REG_TTX_REQUEST_H_START, 0x3e }, | ||
189 | { SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH, 0xb8 }, | ||
190 | { SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT, 0x03 }, | ||
191 | { SAA7127_REG_TTX_ODD_REQ_VERT_START, 0x15 }, | ||
192 | { SAA7127_REG_TTX_ODD_REQ_VERT_END, 0x16 }, | ||
193 | { SAA7127_REG_TTX_EVEN_REQ_VERT_START, 0x15 }, | ||
194 | { SAA7127_REG_TTX_EVEN_REQ_VERT_END, 0x16 }, | ||
195 | { SAA7127_REG_FIRST_ACTIVE, 0x1a }, | ||
196 | { SAA7127_REG_LAST_ACTIVE, 0x01 }, | ||
197 | { SAA7127_REG_MSB_VERTICAL, 0xc0 }, | ||
198 | { SAA7127_REG_DISABLE_TTX_LINE_LO_0, 0x00 }, | ||
199 | { SAA7127_REG_DISABLE_TTX_LINE_LO_1, 0x00 }, | ||
200 | { 0, 0 } | ||
201 | }; | ||
202 | |||
203 | #define SAA7127_60HZ_DAC_CONTROL 0x15 | ||
204 | static const struct i2c_reg_value saa7127_init_config_60hz[] = { | ||
205 | { SAA7127_REG_BURST_START, 0x19 }, | ||
206 | /* BURST_END is also used as a chip ID in saa7127_detect_client */ | ||
207 | { SAA7127_REG_BURST_END, 0x1d }, | ||
208 | { SAA7127_REG_CHROMA_PHASE, 0xa3 }, | ||
209 | { SAA7127_REG_GAINU, 0x98 }, | ||
210 | { SAA7127_REG_GAINV, 0xd3 }, | ||
211 | { SAA7127_REG_BLACK_LEVEL, 0x39 }, | ||
212 | { SAA7127_REG_BLANKING_LEVEL, 0x2e }, | ||
213 | { SAA7127_REG_VBI_BLANKING, 0x2e }, | ||
214 | { SAA7127_REG_DAC_CONTROL, 0x15 }, | ||
215 | { SAA7127_REG_BURST_AMP, 0x4d }, | ||
216 | { SAA7127_REG_SUBC3, 0x1f }, | ||
217 | { SAA7127_REG_SUBC2, 0x7c }, | ||
218 | { SAA7127_REG_SUBC1, 0xf0 }, | ||
219 | { SAA7127_REG_SUBC0, 0x21 }, | ||
220 | { SAA7127_REG_MULTI, 0x90 }, | ||
221 | { SAA7127_REG_CLOSED_CAPTION, 0x11 }, | ||
222 | { 0, 0 } | ||
223 | }; | ||
224 | |||
225 | #define SAA7127_50HZ_DAC_CONTROL 0x02 | ||
226 | struct i2c_reg_value saa7127_init_config_50hz[] = { | ||
227 | { SAA7127_REG_BURST_START, 0x21 }, | ||
228 | /* BURST_END is also used as a chip ID in saa7127_detect_client */ | ||
229 | { SAA7127_REG_BURST_END, 0x1d }, | ||
230 | { SAA7127_REG_CHROMA_PHASE, 0x3f }, | ||
231 | { SAA7127_REG_GAINU, 0x7d }, | ||
232 | { SAA7127_REG_GAINV, 0xaf }, | ||
233 | { SAA7127_REG_BLACK_LEVEL, 0x33 }, | ||
234 | { SAA7127_REG_BLANKING_LEVEL, 0x35 }, | ||
235 | { SAA7127_REG_VBI_BLANKING, 0x35 }, | ||
236 | { SAA7127_REG_DAC_CONTROL, 0x02 }, | ||
237 | { SAA7127_REG_BURST_AMP, 0x2f }, | ||
238 | { SAA7127_REG_SUBC3, 0xcb }, | ||
239 | { SAA7127_REG_SUBC2, 0x8a }, | ||
240 | { SAA7127_REG_SUBC1, 0x09 }, | ||
241 | { SAA7127_REG_SUBC0, 0x2a }, | ||
242 | { SAA7127_REG_MULTI, 0xa0 }, | ||
243 | { SAA7127_REG_CLOSED_CAPTION, 0x00 }, | ||
244 | { 0, 0 } | ||
245 | }; | ||
246 | |||
247 | /* Enumeration for the Supported input types */ | ||
248 | enum saa7127_input_type { | ||
249 | SAA7127_INPUT_TYPE_NORMAL, | ||
250 | SAA7127_INPUT_TYPE_TEST_IMAGE | ||
251 | }; | ||
252 | |||
253 | /* Enumeration for the Supported Output signal types */ | ||
254 | enum saa7127_output_type { | ||
255 | SAA7127_OUTPUT_TYPE_BOTH, | ||
256 | SAA7127_OUTPUT_TYPE_COMPOSITE, | ||
257 | SAA7127_OUTPUT_TYPE_SVIDEO, | ||
258 | SAA7127_OUTPUT_TYPE_RGB, | ||
259 | SAA7127_OUTPUT_TYPE_YUV_C, | ||
260 | SAA7127_OUTPUT_TYPE_YUV_V | ||
261 | }; | ||
262 | |||
263 | /* | ||
264 | ********************************************************************** | ||
265 | * | ||
266 | * Encoder Struct, holds the configuration state of the encoder | ||
267 | * | ||
268 | ********************************************************************** | ||
269 | */ | ||
270 | |||
271 | struct saa7127_state { | ||
272 | v4l2_std_id std; | ||
273 | enum v4l2_chip_ident ident; | ||
274 | enum saa7127_input_type input_type; | ||
275 | enum saa7127_output_type output_type; | ||
276 | int video_enable; | ||
277 | int wss_enable; | ||
278 | u16 wss_mode; | ||
279 | int cc_enable; | ||
280 | u16 cc_data; | ||
281 | int xds_enable; | ||
282 | u16 xds_data; | ||
283 | int vps_enable; | ||
284 | u8 vps_data[5]; | ||
285 | u8 reg_2d; | ||
286 | u8 reg_3a; | ||
287 | u8 reg_3a_cb; /* colorbar bit */ | ||
288 | u8 reg_61; | ||
289 | }; | ||
290 | |||
291 | static const char * const output_strs[] = | ||
292 | { | ||
293 | "S-Video + Composite", | ||
294 | "Composite", | ||
295 | "S-Video", | ||
296 | "RGB", | ||
297 | "YUV C", | ||
298 | "YUV V" | ||
299 | }; | ||
300 | |||
301 | static const char * const wss_strs[] = { | ||
302 | "invalid", | ||
303 | "letterbox 14:9 center", | ||
304 | "letterbox 14:9 top", | ||
305 | "invalid", | ||
306 | "letterbox 16:9 top", | ||
307 | "invalid", | ||
308 | "invalid", | ||
309 | "16:9 full format anamorphic" | ||
310 | "4:3 full format", | ||
311 | "invalid", | ||
312 | "invalid", | ||
313 | "letterbox 16:9 center", | ||
314 | "invalid", | ||
315 | "letterbox >16:9 center", | ||
316 | "14:9 full format center", | ||
317 | "invalid", | ||
318 | }; | ||
319 | |||
320 | /* ----------------------------------------------------------------------- */ | ||
321 | |||
322 | static int saa7127_read(struct i2c_client *client, u8 reg) | ||
323 | { | ||
324 | return i2c_smbus_read_byte_data(client, reg); | ||
325 | } | ||
326 | |||
327 | /* ----------------------------------------------------------------------- */ | ||
328 | |||
329 | static int saa7127_write(struct i2c_client *client, u8 reg, u8 val) | ||
330 | { | ||
331 | int i; | ||
332 | |||
333 | for (i = 0; i < 3; i++) { | ||
334 | if (i2c_smbus_write_byte_data(client, reg, val) == 0) | ||
335 | return 0; | ||
336 | } | ||
337 | saa7127_err("I2C Write Problem\n"); | ||
338 | return -1; | ||
339 | } | ||
340 | |||
341 | /* ----------------------------------------------------------------------- */ | ||
342 | |||
343 | static int saa7127_write_inittab(struct i2c_client *client, | ||
344 | const struct i2c_reg_value *regs) | ||
345 | { | ||
346 | while (regs->reg != 0) { | ||
347 | saa7127_write(client, regs->reg, regs->value); | ||
348 | regs++; | ||
349 | } | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | /* ----------------------------------------------------------------------- */ | ||
354 | |||
355 | static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
356 | { | ||
357 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
358 | int enable = (data->line != 0); | ||
359 | |||
360 | if (enable && (data->field != 0 || data->line != 16)) | ||
361 | return -EINVAL; | ||
362 | if (state->vps_enable != enable) { | ||
363 | saa7127_dbg("Turn VPS Signal %s\n", enable ? "on" : "off"); | ||
364 | saa7127_write(client, 0x54, enable << 7); | ||
365 | state->vps_enable = enable; | ||
366 | } | ||
367 | if (!enable) | ||
368 | return 0; | ||
369 | |||
370 | state->vps_data[0] = data->data[4]; | ||
371 | state->vps_data[1] = data->data[10]; | ||
372 | state->vps_data[2] = data->data[11]; | ||
373 | state->vps_data[3] = data->data[12]; | ||
374 | state->vps_data[4] = data->data[13]; | ||
375 | saa7127_dbg("Set VPS data %02x %02x %02x %02x %02x\n", | ||
376 | state->vps_data[0], state->vps_data[1], | ||
377 | state->vps_data[2], state->vps_data[3], | ||
378 | state->vps_data[4]); | ||
379 | saa7127_write(client, 0x55, state->vps_data[0]); | ||
380 | saa7127_write(client, 0x56, state->vps_data[1]); | ||
381 | saa7127_write(client, 0x57, state->vps_data[2]); | ||
382 | saa7127_write(client, 0x58, state->vps_data[3]); | ||
383 | saa7127_write(client, 0x59, state->vps_data[4]); | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | /* ----------------------------------------------------------------------- */ | ||
388 | |||
389 | static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
390 | { | ||
391 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
392 | u16 cc = data->data[0] << 8 | data->data[1]; | ||
393 | int enable = (data->line != 0); | ||
394 | |||
395 | if (enable && (data->field != 0 || data->line != 21)) | ||
396 | return -EINVAL; | ||
397 | if (state->cc_enable != enable) { | ||
398 | saa7127_dbg("Turn CC %s\n", enable ? "on" : "off"); | ||
399 | saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, | ||
400 | (enable << 6) | 0x11); | ||
401 | state->cc_enable = enable; | ||
402 | } | ||
403 | if (!enable) | ||
404 | return 0; | ||
405 | |||
406 | saa7127_dbg_highvol("CC data: %04x\n", cc); | ||
407 | saa7127_write(client, SAA7127_REG_LINE_21_ODD_0, cc & 0xff); | ||
408 | saa7127_write(client, SAA7127_REG_LINE_21_ODD_1, cc >> 8); | ||
409 | state->cc_data = cc; | ||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | /* ----------------------------------------------------------------------- */ | ||
414 | |||
415 | static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
416 | { | ||
417 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
418 | u16 xds = data->data[1] << 8 | data->data[0]; | ||
419 | int enable = (data->line != 0); | ||
420 | |||
421 | if (enable && (data->field != 1 || data->line != 21)) | ||
422 | return -EINVAL; | ||
423 | if (state->xds_enable != enable) { | ||
424 | saa7127_dbg("Turn XDS %s\n", enable ? "on" : "off"); | ||
425 | saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, | ||
426 | (enable << 7) | 0x11); | ||
427 | state->xds_enable = enable; | ||
428 | } | ||
429 | if (!enable) | ||
430 | return 0; | ||
431 | |||
432 | saa7127_dbg_highvol("XDS data: %04x\n", xds); | ||
433 | saa7127_write(client, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff); | ||
434 | saa7127_write(client, SAA7127_REG_LINE_21_EVEN_1, xds >> 8); | ||
435 | state->xds_data = xds; | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | /* ----------------------------------------------------------------------- */ | ||
440 | |||
441 | static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) | ||
442 | { | ||
443 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
444 | int enable = (data->line != 0); | ||
445 | |||
446 | if (enable && (data->field != 0 || data->line != 23)) | ||
447 | return -EINVAL; | ||
448 | if (state->wss_enable != enable) { | ||
449 | saa7127_dbg("Turn WSS %s\n", enable ? "on" : "off"); | ||
450 | saa7127_write(client, 0x27, enable << 7); | ||
451 | state->wss_enable = enable; | ||
452 | } | ||
453 | if (!enable) | ||
454 | return 0; | ||
455 | |||
456 | saa7127_write(client, 0x26, data->data[0]); | ||
457 | saa7127_write(client, 0x27, 0x80 | (data->data[1] & 0x3f)); | ||
458 | saa7127_dbg("WSS mode: %s\n", wss_strs[data->data[0] & 0xf]); | ||
459 | state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0]; | ||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | /* ----------------------------------------------------------------------- */ | ||
464 | |||
465 | static int saa7127_set_video_enable(struct i2c_client *client, int enable) | ||
466 | { | ||
467 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
468 | |||
469 | if (enable) { | ||
470 | saa7127_dbg("Enable Video Output\n"); | ||
471 | saa7127_write(client, 0x2d, state->reg_2d); | ||
472 | saa7127_write(client, 0x61, state->reg_61); | ||
473 | } else { | ||
474 | saa7127_dbg("Disable Video Output\n"); | ||
475 | saa7127_write(client, 0x2d, (state->reg_2d & 0xf0)); | ||
476 | saa7127_write(client, 0x61, (state->reg_61 | 0xc0)); | ||
477 | } | ||
478 | state->video_enable = enable; | ||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | /* ----------------------------------------------------------------------- */ | ||
483 | |||
484 | static int saa7127_set_std(struct i2c_client *client, v4l2_std_id std) | ||
485 | { | ||
486 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
487 | const struct i2c_reg_value *inittab; | ||
488 | |||
489 | if (std & V4L2_STD_525_60) { | ||
490 | saa7127_dbg("Selecting 60 Hz video Standard\n"); | ||
491 | inittab = saa7127_init_config_60hz; | ||
492 | state->reg_61 = SAA7127_60HZ_DAC_CONTROL; | ||
493 | } else { | ||
494 | saa7127_dbg("Selecting 50 Hz video Standard\n"); | ||
495 | inittab = saa7127_init_config_50hz; | ||
496 | state->reg_61 = SAA7127_50HZ_DAC_CONTROL; | ||
497 | } | ||
498 | |||
499 | /* Write Table */ | ||
500 | saa7127_write_inittab(client, inittab); | ||
501 | state->std = std; | ||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | /* ----------------------------------------------------------------------- */ | ||
506 | |||
507 | static int saa7127_set_output_type(struct i2c_client *client, int output) | ||
508 | { | ||
509 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
510 | |||
511 | switch (output) { | ||
512 | case SAA7127_OUTPUT_TYPE_RGB: | ||
513 | state->reg_2d = 0x0f; /* RGB + CVBS (for sync) */ | ||
514 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
515 | break; | ||
516 | |||
517 | case SAA7127_OUTPUT_TYPE_COMPOSITE: | ||
518 | state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */ | ||
519 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
520 | break; | ||
521 | |||
522 | case SAA7127_OUTPUT_TYPE_SVIDEO: | ||
523 | state->reg_2d = 0xff; /* 11111111 croma -> R, luma -> CVBS + G + B */ | ||
524 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
525 | break; | ||
526 | |||
527 | case SAA7127_OUTPUT_TYPE_YUV_V: | ||
528 | state->reg_2d = 0x4f; /* reg 2D = 01001111, all DAC's on, RGB + VBS */ | ||
529 | state->reg_3a = 0x0b; /* reg 3A = 00001011, bypass RGB-matrix */ | ||
530 | break; | ||
531 | |||
532 | case SAA7127_OUTPUT_TYPE_YUV_C: | ||
533 | state->reg_2d = 0x0f; /* reg 2D = 00001111, all DAC's on, RGB + CVBS */ | ||
534 | state->reg_3a = 0x0b; /* reg 3A = 00001011, bypass RGB-matrix */ | ||
535 | break; | ||
536 | |||
537 | case SAA7127_OUTPUT_TYPE_BOTH: | ||
538 | state->reg_2d = 0xbf; | ||
539 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | ||
540 | break; | ||
541 | |||
542 | default: | ||
543 | return -EINVAL; | ||
544 | } | ||
545 | saa7127_dbg("Selecting %s output type\n", output_strs[output]); | ||
546 | |||
547 | /* Configure Encoder */ | ||
548 | saa7127_write(client, 0x2d, state->reg_2d); | ||
549 | saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb); | ||
550 | state->output_type = output; | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | /* ----------------------------------------------------------------------- */ | ||
555 | |||
556 | static int saa7127_set_input_type(struct i2c_client *client, int input) | ||
557 | { | ||
558 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
559 | |||
560 | switch (input) { | ||
561 | case SAA7127_INPUT_TYPE_NORMAL: /* avia */ | ||
562 | saa7127_dbg("Selecting Normal Encoder Input\n"); | ||
563 | state->reg_3a_cb = 0; | ||
564 | break; | ||
565 | |||
566 | case SAA7127_INPUT_TYPE_TEST_IMAGE: /* color bar */ | ||
567 | saa7127_dbg("Selecting Color Bar generator\n"); | ||
568 | state->reg_3a_cb = 0x80; | ||
569 | break; | ||
570 | |||
571 | default: | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb); | ||
575 | state->input_type = input; | ||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | /* ----------------------------------------------------------------------- */ | ||
580 | |||
581 | static int saa7127_command(struct i2c_client *client, | ||
582 | unsigned int cmd, void *arg) | ||
583 | { | ||
584 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
585 | struct v4l2_format *fmt = arg; | ||
586 | int *iarg = arg; | ||
587 | |||
588 | switch (cmd) { | ||
589 | case VIDIOC_S_STD: | ||
590 | if (state->std == *(v4l2_std_id *)arg) | ||
591 | break; | ||
592 | return saa7127_set_std(client, *(v4l2_std_id *)arg); | ||
593 | |||
594 | case VIDIOC_G_STD: | ||
595 | *(v4l2_std_id *)arg = state->std; | ||
596 | break; | ||
597 | |||
598 | case VIDIOC_S_INPUT: | ||
599 | if (state->input_type == *iarg) | ||
600 | break; | ||
601 | return saa7127_set_input_type(client, *iarg); | ||
602 | |||
603 | case VIDIOC_S_OUTPUT: | ||
604 | if (state->output_type == *iarg) | ||
605 | break; | ||
606 | return saa7127_set_output_type(client, *iarg); | ||
607 | |||
608 | case VIDIOC_STREAMON: | ||
609 | case VIDIOC_STREAMOFF: | ||
610 | if (state->video_enable == (cmd == VIDIOC_STREAMON)) | ||
611 | break; | ||
612 | return saa7127_set_video_enable(client, cmd == VIDIOC_STREAMON); | ||
613 | |||
614 | case VIDIOC_G_FMT: | ||
615 | if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) | ||
616 | return -EINVAL; | ||
617 | |||
618 | memset(&fmt->fmt.sliced, 0, sizeof(fmt->fmt.sliced)); | ||
619 | if (state->vps_enable) | ||
620 | fmt->fmt.sliced.service_lines[0][16] = V4L2_SLICED_VPS; | ||
621 | if (state->wss_enable) | ||
622 | fmt->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625; | ||
623 | if (state->cc_enable) { | ||
624 | fmt->fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525; | ||
625 | fmt->fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525; | ||
626 | } | ||
627 | fmt->fmt.sliced.service_set = | ||
628 | (state->vps_enable ? V4L2_SLICED_VPS : 0) | | ||
629 | (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) | | ||
630 | (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0); | ||
631 | break; | ||
632 | |||
633 | case VIDIOC_LOG_STATUS: | ||
634 | saa7127_info("Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz"); | ||
635 | saa7127_info("Input: %s\n", state->input_type ? "color bars" : "normal"); | ||
636 | saa7127_info("Output: %s\n", state->video_enable ? | ||
637 | output_strs[state->output_type] : "disabled"); | ||
638 | saa7127_info("WSS: %s\n", state->wss_enable ? | ||
639 | wss_strs[state->wss_mode] : "disabled"); | ||
640 | saa7127_info("VPS: %s\n", state->vps_enable ? "enabled" : "disabled"); | ||
641 | saa7127_info("CC: %s\n", state->cc_enable ? "enabled" : "disabled"); | ||
642 | break; | ||
643 | |||
644 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
645 | case VIDIOC_INT_G_REGISTER: | ||
646 | { | ||
647 | struct v4l2_register *reg = arg; | ||
648 | |||
649 | if (reg->i2c_id != I2C_DRIVERID_SAA7127) | ||
650 | return -EINVAL; | ||
651 | reg->val = saa7127_read(client, reg->reg & 0xff); | ||
652 | break; | ||
653 | } | ||
654 | |||
655 | case VIDIOC_INT_S_REGISTER: | ||
656 | { | ||
657 | struct v4l2_register *reg = arg; | ||
658 | |||
659 | if (reg->i2c_id != I2C_DRIVERID_SAA7127) | ||
660 | return -EINVAL; | ||
661 | if (!capable(CAP_SYS_ADMIN)) | ||
662 | return -EPERM; | ||
663 | saa7127_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
664 | break; | ||
665 | } | ||
666 | #endif | ||
667 | |||
668 | case VIDIOC_INT_S_VBI_DATA: | ||
669 | { | ||
670 | struct v4l2_sliced_vbi_data *data = arg; | ||
671 | |||
672 | switch (data->id) { | ||
673 | case V4L2_SLICED_WSS_625: | ||
674 | return saa7127_set_wss(client, data); | ||
675 | case V4L2_SLICED_VPS: | ||
676 | return saa7127_set_vps(client, data); | ||
677 | case V4L2_SLICED_CAPTION_525: | ||
678 | if (data->field == 0) | ||
679 | return saa7127_set_cc(client, data); | ||
680 | return saa7127_set_xds(client, data); | ||
681 | default: | ||
682 | return -EINVAL; | ||
683 | } | ||
684 | break; | ||
685 | } | ||
686 | |||
687 | case VIDIOC_INT_G_CHIP_IDENT: | ||
688 | *(enum v4l2_chip_ident *)arg = state->ident; | ||
689 | break; | ||
690 | |||
691 | default: | ||
692 | return -EINVAL; | ||
693 | } | ||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | /* ----------------------------------------------------------------------- */ | ||
698 | |||
699 | struct i2c_driver i2c_driver_saa7127; | ||
700 | |||
701 | /* ----------------------------------------------------------------------- */ | ||
702 | |||
703 | static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind) | ||
704 | { | ||
705 | struct i2c_client *client; | ||
706 | struct saa7127_state *state; | ||
707 | struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */ | ||
708 | int read_result = 0; | ||
709 | |||
710 | /* Check if the adapter supports the needed features */ | ||
711 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
712 | return 0; | ||
713 | |||
714 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
715 | if (client == 0) | ||
716 | return -ENOMEM; | ||
717 | |||
718 | memset(client, 0, sizeof(struct i2c_client)); | ||
719 | client->addr = address; | ||
720 | client->adapter = adapter; | ||
721 | client->driver = &i2c_driver_saa7127; | ||
722 | client->flags = I2C_CLIENT_ALLOW_USE; | ||
723 | snprintf(client->name, sizeof(client->name) - 1, "saa7127"); | ||
724 | |||
725 | saa7127_dbg("detecting saa7127 client on address 0x%x\n", address << 1); | ||
726 | |||
727 | /* First test register 0: Bits 5-7 are a version ID (should be 0), | ||
728 | and bit 2 should also be 0. | ||
729 | This is rather general, so the second test is more specific and | ||
730 | looks at the 'ending point of burst in clock cycles' which is | ||
731 | 0x1d after a reset and not expected to ever change. */ | ||
732 | if ((saa7127_read(client, 0) & 0xe4) != 0 || | ||
733 | (saa7127_read(client, 0x29) & 0x3f) != 0x1d) { | ||
734 | saa7127_dbg("saa7127 not found\n"); | ||
735 | kfree(client); | ||
736 | return 0; | ||
737 | } | ||
738 | state = kmalloc(sizeof(struct saa7127_state), GFP_KERNEL); | ||
739 | |||
740 | if (state == NULL) { | ||
741 | kfree(client); | ||
742 | return (-ENOMEM); | ||
743 | } | ||
744 | |||
745 | i2c_set_clientdata(client, state); | ||
746 | memset(state, 0, sizeof(struct saa7127_state)); | ||
747 | |||
748 | /* Configure Encoder */ | ||
749 | |||
750 | saa7127_dbg("Configuring encoder\n"); | ||
751 | saa7127_write_inittab(client, saa7127_init_config_common); | ||
752 | saa7127_set_std(client, V4L2_STD_NTSC); | ||
753 | saa7127_set_output_type(client, SAA7127_OUTPUT_TYPE_BOTH); | ||
754 | saa7127_set_vps(client, &vbi); | ||
755 | saa7127_set_wss(client, &vbi); | ||
756 | saa7127_set_cc(client, &vbi); | ||
757 | saa7127_set_xds(client, &vbi); | ||
758 | if (test_image == 1) { | ||
759 | /* The Encoder has an internal Colorbar generator */ | ||
760 | /* This can be used for debugging */ | ||
761 | saa7127_set_input_type(client, SAA7127_INPUT_TYPE_TEST_IMAGE); | ||
762 | } else { | ||
763 | saa7127_set_input_type(client, SAA7127_INPUT_TYPE_NORMAL); | ||
764 | } | ||
765 | saa7127_set_video_enable(client, 1); | ||
766 | |||
767 | /* Detect if it's an saa7129 */ | ||
768 | read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2); | ||
769 | saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa); | ||
770 | if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { | ||
771 | saa7127_info("saa7129 found @ 0x%x (%s)\n", address << 1, adapter->name); | ||
772 | saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, read_result); | ||
773 | saa7127_write_inittab(client, saa7129_init_config_extra); | ||
774 | state->ident = V4L2_IDENT_SAA7129; | ||
775 | } else { | ||
776 | saa7127_info("saa7127 found @ 0x%x (%s)\n", address << 1, adapter->name); | ||
777 | state->ident = V4L2_IDENT_SAA7127; | ||
778 | } | ||
779 | |||
780 | i2c_attach_client(client); | ||
781 | |||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | /* ----------------------------------------------------------------------- */ | ||
786 | |||
787 | static int saa7127_probe(struct i2c_adapter *adapter) | ||
788 | { | ||
789 | #ifdef I2C_CLASS_TV_ANALOG | ||
790 | if (adapter->class & I2C_CLASS_TV_ANALOG) | ||
791 | #else | ||
792 | if (adapter->id == I2C_HW_B_BT848) | ||
793 | #endif | ||
794 | return i2c_probe(adapter, &addr_data, saa7127_attach); | ||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | /* ----------------------------------------------------------------------- */ | ||
799 | |||
800 | static int saa7127_detach(struct i2c_client *client) | ||
801 | { | ||
802 | struct saa7127_state *state = i2c_get_clientdata(client); | ||
803 | int err; | ||
804 | |||
805 | /* Turn off TV output */ | ||
806 | saa7127_set_video_enable(client, 0); | ||
807 | |||
808 | err = i2c_detach_client(client); | ||
809 | |||
810 | if (err) { | ||
811 | return err; | ||
812 | } | ||
813 | |||
814 | kfree(state); | ||
815 | kfree(client); | ||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | /* ----------------------------------------------------------------------- */ | ||
820 | |||
821 | struct i2c_driver i2c_driver_saa7127 = { | ||
822 | .name = "saa7127", | ||
823 | .id = I2C_DRIVERID_SAA7127, | ||
824 | .flags = I2C_DF_NOTIFY, | ||
825 | .attach_adapter = saa7127_probe, | ||
826 | .detach_client = saa7127_detach, | ||
827 | .command = saa7127_command, | ||
828 | .owner = THIS_MODULE, | ||
829 | }; | ||
830 | |||
831 | |||
832 | /* ----------------------------------------------------------------------- */ | ||
833 | |||
834 | static int __init saa7127_init_module(void) | ||
835 | { | ||
836 | return i2c_add_driver(&i2c_driver_saa7127); | ||
837 | } | ||
838 | |||
839 | /* ----------------------------------------------------------------------- */ | ||
840 | |||
841 | static void __exit saa7127_cleanup_module(void) | ||
842 | { | ||
843 | i2c_del_driver(&i2c_driver_saa7127); | ||
844 | } | ||
845 | |||
846 | /* ----------------------------------------------------------------------- */ | ||
847 | |||
848 | module_init(saa7127_init_module); | ||
849 | module_exit(saa7127_cleanup_module); | ||
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 624e8808a517..7bdeabe638ca 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig | |||
@@ -1,10 +1,11 @@ | |||
1 | config VIDEO_SAA7134 | 1 | config VIDEO_SAA7134 |
2 | tristate "Philips SAA7134 support" | 2 | tristate "Philips SAA7134 support" |
3 | depends on VIDEO_DEV && PCI && I2C && SOUND | 3 | depends on VIDEO_DEV && PCI && I2C && SOUND && SND |
4 | select VIDEO_BUF | 4 | select VIDEO_BUF |
5 | select VIDEO_IR | 5 | select VIDEO_IR |
6 | select VIDEO_TUNER | 6 | select VIDEO_TUNER |
7 | select CRC32 | 7 | select CRC32 |
8 | select SND_PCM_OSS | ||
8 | ---help--- | 9 | ---help--- |
9 | This is a video4linux driver for Philips SAA713x based | 10 | This is a video4linux driver for Philips SAA713x based |
10 | TV cards. | 11 | TV cards. |
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile index e0b28f0533af..4226b61cc613 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/video/saa7134/Makefile | |||
@@ -1,10 +1,11 @@ | |||
1 | 1 | ||
2 | saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \ | 2 | saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \ |
3 | saa7134-oss.o saa7134-ts.o saa7134-tvaudio.o \ | 3 | saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o \ |
4 | saa7134-vbi.o saa7134-video.o saa7134-input.o | 4 | saa7134-video.o saa7134-input.o |
5 | 5 | ||
6 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o \ | 6 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o \ |
7 | saa6752hs.o saa7134-alsa.o | 7 | saa6752hs.o saa7134-alsa.o \ |
8 | saa7134-oss.o | ||
8 | obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o | 9 | obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o |
9 | 10 | ||
10 | EXTRA_CFLAGS += -I$(src)/.. | 11 | EXTRA_CFLAGS += -I$(src)/.. |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 4f3c42354329..5707c666660b 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -30,7 +30,9 @@ | |||
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | #include <sound/control.h> | 31 | #include <sound/control.h> |
32 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
33 | #include <sound/pcm_params.h> | ||
33 | #include <sound/initval.h> | 34 | #include <sound/initval.h> |
35 | #include <linux/interrupt.h> | ||
34 | 36 | ||
35 | #include "saa7134.h" | 37 | #include "saa7134.h" |
36 | #include "saa7134-reg.h" | 38 | #include "saa7134-reg.h" |
@@ -56,6 +58,8 @@ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; | |||
56 | module_param_array(index, int, NULL, 0444); | 58 | module_param_array(index, int, NULL, 0444); |
57 | MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s)."); | 59 | MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s)."); |
58 | 60 | ||
61 | int position; | ||
62 | |||
59 | #define dprintk(fmt, arg...) if (debug) \ | 63 | #define dprintk(fmt, arg...) if (debug) \ |
60 | printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) | 64 | printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) |
61 | 65 | ||
@@ -68,7 +72,7 @@ typedef struct snd_card_saa7134 { | |||
68 | int mixer_volume[MIXER_ADDR_LAST+1][2]; | 72 | int mixer_volume[MIXER_ADDR_LAST+1][2]; |
69 | int capture_source[MIXER_ADDR_LAST+1][2]; | 73 | int capture_source[MIXER_ADDR_LAST+1][2]; |
70 | struct pci_dev *pci; | 74 | struct pci_dev *pci; |
71 | struct saa7134_dev *saadev; | 75 | struct saa7134_dev *dev; |
72 | 76 | ||
73 | unsigned long iobase; | 77 | unsigned long iobase; |
74 | int irq; | 78 | int irq; |
@@ -83,12 +87,10 @@ typedef struct snd_card_saa7134 { | |||
83 | */ | 87 | */ |
84 | 88 | ||
85 | typedef struct snd_card_saa7134_pcm { | 89 | typedef struct snd_card_saa7134_pcm { |
86 | struct saa7134_dev *saadev; | 90 | struct saa7134_dev *dev; |
87 | 91 | ||
88 | spinlock_t lock; | 92 | spinlock_t lock; |
89 | unsigned int pcm_size; /* buffer size */ | 93 | |
90 | unsigned int pcm_count; /* bytes per period */ | ||
91 | unsigned int pcm_bps; /* bytes per second */ | ||
92 | snd_pcm_substream_t *substream; | 94 | snd_pcm_substream_t *substream; |
93 | } snd_card_saa7134_pcm_t; | 95 | } snd_card_saa7134_pcm_t; |
94 | 96 | ||
@@ -100,13 +102,11 @@ static snd_card_t *snd_saa7134_cards[SNDRV_CARDS]; | |||
100 | * | 102 | * |
101 | * Called when the capture device is released or the buffer overflows | 103 | * Called when the capture device is released or the buffer overflows |
102 | * | 104 | * |
103 | * - Copied verbatim from saa7134-oss's dsp_dma_stop. Can be dropped | 105 | * - Copied verbatim from saa7134-oss's dsp_dma_stop. |
104 | * if we just share dsp_dma_stop and use it here | ||
105 | * | 106 | * |
106 | */ | 107 | */ |
107 | 108 | ||
108 | static void saa7134_dma_stop(struct saa7134_dev *dev) | 109 | static void saa7134_dma_stop(struct saa7134_dev *dev) |
109 | |||
110 | { | 110 | { |
111 | dev->dmasound.dma_blk = -1; | 111 | dev->dmasound.dma_blk = -1; |
112 | dev->dmasound.dma_running = 0; | 112 | dev->dmasound.dma_running = 0; |
@@ -118,8 +118,7 @@ static void saa7134_dma_stop(struct saa7134_dev *dev) | |||
118 | * | 118 | * |
119 | * Called when preparing the capture device for use | 119 | * Called when preparing the capture device for use |
120 | * | 120 | * |
121 | * - Copied verbatim from saa7134-oss's dsp_dma_start. Can be dropped | 121 | * - Copied verbatim from saa7134-oss's dsp_dma_start. |
122 | * if we just share dsp_dma_start and use it here | ||
123 | * | 122 | * |
124 | */ | 123 | */ |
125 | 124 | ||
@@ -170,9 +169,9 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) | |||
170 | if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) { | 169 | if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) { |
171 | dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count, | 170 | dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count, |
172 | dev->dmasound.bufsize, dev->dmasound.blocks); | 171 | dev->dmasound.bufsize, dev->dmasound.blocks); |
172 | spin_unlock(&dev->slock); | ||
173 | snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN); | 173 | snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN); |
174 | saa7134_dma_stop(dev); | 174 | return; |
175 | goto done; | ||
176 | } | 175 | } |
177 | 176 | ||
178 | /* next block addr */ | 177 | /* next block addr */ |
@@ -194,6 +193,7 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) | |||
194 | snd_pcm_period_elapsed(dev->dmasound.substream); | 193 | snd_pcm_period_elapsed(dev->dmasound.substream); |
195 | spin_lock(&dev->slock); | 194 | spin_lock(&dev->slock); |
196 | } | 195 | } |
196 | |||
197 | done: | 197 | done: |
198 | spin_unlock(&dev->slock); | 198 | spin_unlock(&dev->slock); |
199 | 199 | ||
@@ -209,7 +209,9 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) | |||
209 | 209 | ||
210 | static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id, struct pt_regs *regs) | 210 | static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id, struct pt_regs *regs) |
211 | { | 211 | { |
212 | struct saa7134_dev *dev = (struct saa7134_dev*) dev_id; | 212 | struct saa7134_dmasound *dmasound = dev_id; |
213 | struct saa7134_dev *dev = dmasound->priv_data; | ||
214 | |||
213 | unsigned long report, status; | 215 | unsigned long report, status; |
214 | int loop, handled = 0; | 216 | int loop, handled = 0; |
215 | 217 | ||
@@ -248,56 +250,23 @@ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, | |||
248 | int cmd) | 250 | int cmd) |
249 | { | 251 | { |
250 | snd_pcm_runtime_t *runtime = substream->runtime; | 252 | snd_pcm_runtime_t *runtime = substream->runtime; |
251 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 253 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
252 | struct saa7134_dev *dev=saapcm->saadev; | 254 | struct saa7134_dev *dev=pcm->dev; |
253 | int err = 0; | 255 | int err = 0; |
254 | 256 | ||
255 | spin_lock_irq(&dev->slock); | 257 | spin_lock(&dev->slock); |
256 | if (cmd == SNDRV_PCM_TRIGGER_START) { | 258 | if (cmd == SNDRV_PCM_TRIGGER_START) { |
257 | /* start dma */ | 259 | /* start dma */ |
258 | saa7134_dma_start(dev); | 260 | saa7134_dma_start(dev); |
259 | } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { | 261 | } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { |
260 | /* stop dma */ | 262 | /* stop dma */ |
261 | saa7134_dma_stop(dev); | 263 | saa7134_dma_stop(dev); |
262 | } else { | 264 | } else { |
263 | err = -EINVAL; | 265 | err = -EINVAL; |
264 | } | 266 | } |
265 | spin_unlock_irq(&dev->slock); | 267 | spin_unlock(&dev->slock); |
266 | |||
267 | return err; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * DMA buffer config | ||
272 | * | ||
273 | * Sets the values that will later be used as the size of the buffer, | ||
274 | * size of the fragments, and total number of fragments. | ||
275 | * Must be called during the preparation stage, before memory is | ||
276 | * allocated | ||
277 | * | ||
278 | * - Copied verbatim from saa7134-oss. Can be dropped | ||
279 | * if we just share dsp_buffer_conf from OSS. | ||
280 | */ | ||
281 | 268 | ||
282 | static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) | 269 | return err; |
283 | { | ||
284 | if (blksize < 0x100) | ||
285 | blksize = 0x100; | ||
286 | if (blksize > 0x10000) | ||
287 | blksize = 0x10000; | ||
288 | |||
289 | if (blocks < 2) | ||
290 | blocks = 2; | ||
291 | if ((blksize * blocks) > 1024*1024) | ||
292 | blocks = 1024*1024 / blksize; | ||
293 | |||
294 | dev->dmasound.blocks = blocks; | ||
295 | dev->dmasound.blksize = blksize; | ||
296 | dev->dmasound.bufsize = blksize * blocks; | ||
297 | |||
298 | dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", | ||
299 | blocks,blksize,blksize * blocks / 1024); | ||
300 | return 0; | ||
301 | } | 270 | } |
302 | 271 | ||
303 | /* | 272 | /* |
@@ -307,16 +276,16 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) | |||
307 | * ALSA, but I was unable to use ALSA's own DMA, and had to force the | 276 | * ALSA, but I was unable to use ALSA's own DMA, and had to force the |
308 | * usage of V4L's | 277 | * usage of V4L's |
309 | * | 278 | * |
310 | * - Copied verbatim from saa7134-oss. Can be dropped | 279 | * - Copied verbatim from saa7134-oss. |
311 | * if we just share dsp_buffer_init from OSS. | 280 | * |
312 | */ | 281 | */ |
313 | 282 | ||
314 | static int dsp_buffer_init(struct saa7134_dev *dev) | 283 | static int dsp_buffer_init(struct saa7134_dev *dev) |
315 | { | 284 | { |
316 | int err; | 285 | int err; |
317 | 286 | ||
318 | if (!dev->dmasound.bufsize) | 287 | BUG_ON(!dev->dmasound.bufsize); |
319 | BUG(); | 288 | |
320 | videobuf_dma_init(&dev->dmasound.dma); | 289 | videobuf_dma_init(&dev->dmasound.dma); |
321 | err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE, | 290 | err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE, |
322 | (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT); | 291 | (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT); |
@@ -326,6 +295,28 @@ static int dsp_buffer_init(struct saa7134_dev *dev) | |||
326 | } | 295 | } |
327 | 296 | ||
328 | /* | 297 | /* |
298 | * DMA buffer release | ||
299 | * | ||
300 | * Called after closing the device, during snd_card_saa7134_capture_close | ||
301 | * | ||
302 | */ | ||
303 | |||
304 | static int dsp_buffer_free(struct saa7134_dev *dev) | ||
305 | { | ||
306 | if (!dev->dmasound.blksize) | ||
307 | BUG(); | ||
308 | |||
309 | videobuf_dma_free(&dev->dmasound.dma); | ||
310 | |||
311 | dev->dmasound.blocks = 0; | ||
312 | dev->dmasound.blksize = 0; | ||
313 | dev->dmasound.bufsize = 0; | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | |||
319 | /* | ||
329 | * ALSA PCM preparation | 320 | * ALSA PCM preparation |
330 | * | 321 | * |
331 | * - One of the ALSA capture callbacks. | 322 | * - One of the ALSA capture callbacks. |
@@ -340,84 +331,30 @@ static int dsp_buffer_init(struct saa7134_dev *dev) | |||
340 | static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | 331 | static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) |
341 | { | 332 | { |
342 | snd_pcm_runtime_t *runtime = substream->runtime; | 333 | snd_pcm_runtime_t *runtime = substream->runtime; |
343 | int err, bswap, sign; | 334 | int bswap, sign; |
344 | u32 fmt, control; | 335 | u32 fmt, control; |
345 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | 336 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
346 | struct saa7134_dev *dev; | 337 | struct saa7134_dev *dev; |
347 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 338 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
348 | unsigned int bps; | ||
349 | unsigned long size; | ||
350 | unsigned count; | ||
351 | |||
352 | size = snd_pcm_lib_buffer_bytes(substream); | ||
353 | count = snd_pcm_lib_period_bytes(substream); | ||
354 | |||
355 | saapcm->saadev->dmasound.substream = substream; | ||
356 | bps = runtime->rate * runtime->channels; | ||
357 | bps *= snd_pcm_format_width(runtime->format); | ||
358 | bps /= 8; | ||
359 | if (bps <= 0) | ||
360 | return -EINVAL; | ||
361 | saapcm->pcm_bps = bps; | ||
362 | saapcm->pcm_size = snd_pcm_lib_buffer_bytes(substream); | ||
363 | saapcm->pcm_count = snd_pcm_lib_period_bytes(substream); | ||
364 | |||
365 | 339 | ||
366 | dev=saa7134->saadev; | 340 | pcm->dev->dmasound.substream = substream; |
367 | 341 | ||
368 | dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count)); | 342 | dev = saa7134->dev; |
369 | 343 | ||
370 | err = dsp_buffer_init(dev); | 344 | if (snd_pcm_format_width(runtime->format) == 8) |
371 | if (0 != err) | ||
372 | goto fail2; | ||
373 | |||
374 | /* prepare buffer */ | ||
375 | if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma))) | ||
376 | return err; | ||
377 | if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) | ||
378 | goto fail1; | ||
379 | if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt, | ||
380 | dev->dmasound.dma.sglist, | ||
381 | dev->dmasound.dma.sglen, | ||
382 | 0))) | ||
383 | goto fail2; | ||
384 | |||
385 | |||
386 | |||
387 | switch (runtime->format) { | ||
388 | case SNDRV_PCM_FORMAT_U8: | ||
389 | case SNDRV_PCM_FORMAT_S8: | ||
390 | fmt = 0x00; | 345 | fmt = 0x00; |
391 | break; | 346 | else |
392 | case SNDRV_PCM_FORMAT_U16_LE: | ||
393 | case SNDRV_PCM_FORMAT_U16_BE: | ||
394 | case SNDRV_PCM_FORMAT_S16_LE: | ||
395 | case SNDRV_PCM_FORMAT_S16_BE: | ||
396 | fmt = 0x01; | 347 | fmt = 0x01; |
397 | break; | ||
398 | default: | ||
399 | err = -EINVAL; | ||
400 | return 1; | ||
401 | } | ||
402 | 348 | ||
403 | switch (runtime->format) { | 349 | if (snd_pcm_format_signed(runtime->format)) |
404 | case SNDRV_PCM_FORMAT_S8: | ||
405 | case SNDRV_PCM_FORMAT_S16_LE: | ||
406 | case SNDRV_PCM_FORMAT_S16_BE: | ||
407 | sign = 1; | 350 | sign = 1; |
408 | break; | 351 | else |
409 | default: | ||
410 | sign = 0; | 352 | sign = 0; |
411 | break; | ||
412 | } | ||
413 | 353 | ||
414 | switch (runtime->format) { | 354 | if (snd_pcm_format_big_endian(runtime->format)) |
415 | case SNDRV_PCM_FORMAT_U16_BE: | 355 | bswap = 1; |
416 | case SNDRV_PCM_FORMAT_S16_BE: | 356 | else |
417 | bswap = 1; break; | 357 | bswap = 0; |
418 | default: | ||
419 | bswap = 0; break; | ||
420 | } | ||
421 | 358 | ||
422 | switch (dev->pci->device) { | 359 | switch (dev->pci->device) { |
423 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | 360 | case PCI_DEVICE_ID_PHILIPS_SAA7134: |
@@ -445,7 +382,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
445 | fmt |= 0x04; | 382 | fmt |= 0x04; |
446 | saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1); | 383 | saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1); |
447 | saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); | 384 | saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); |
448 | //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); | ||
449 | break; | 385 | break; |
450 | } | 386 | } |
451 | 387 | ||
@@ -459,12 +395,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
459 | if (bswap) | 395 | if (bswap) |
460 | control |= SAA7134_RS_CONTROL_BSWAP; | 396 | control |= SAA7134_RS_CONTROL_BSWAP; |
461 | 397 | ||
462 | /* I should be able to use runtime->dma_addr in the control | ||
463 | byte, but it doesn't work. So I allocate the DMA using the | ||
464 | V4L functions, and force ALSA to use that as the DMA area */ | ||
465 | |||
466 | runtime->dma_area = dev->dmasound.dma.vmalloc; | ||
467 | |||
468 | saa_writel(SAA7134_RS_BA1(6),0); | 398 | saa_writel(SAA7134_RS_BA1(6),0); |
469 | saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize); | 399 | saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize); |
470 | saa_writel(SAA7134_RS_PITCH(6),0); | 400 | saa_writel(SAA7134_RS_PITCH(6),0); |
@@ -473,12 +403,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
473 | dev->dmasound.rate = runtime->rate; | 403 | dev->dmasound.rate = runtime->rate; |
474 | 404 | ||
475 | return 0; | 405 | return 0; |
476 | fail2: | ||
477 | saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); | ||
478 | fail1: | ||
479 | videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); | ||
480 | return err; | ||
481 | |||
482 | 406 | ||
483 | } | 407 | } |
484 | 408 | ||
@@ -496,10 +420,8 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | |||
496 | static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) | 420 | static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) |
497 | { | 421 | { |
498 | snd_pcm_runtime_t *runtime = substream->runtime; | 422 | snd_pcm_runtime_t *runtime = substream->runtime; |
499 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 423 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
500 | struct saa7134_dev *dev=saapcm->saadev; | 424 | struct saa7134_dev *dev=pcm->dev; |
501 | |||
502 | |||
503 | 425 | ||
504 | if (dev->dmasound.read_count) { | 426 | if (dev->dmasound.read_count) { |
505 | dev->dmasound.read_count -= snd_pcm_lib_period_bytes(substream); | 427 | dev->dmasound.read_count -= snd_pcm_lib_period_bytes(substream); |
@@ -540,9 +462,9 @@ static snd_pcm_hardware_t snd_card_saa7134_capture = | |||
540 | 462 | ||
541 | static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) | 463 | static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) |
542 | { | 464 | { |
543 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 465 | snd_card_saa7134_pcm_t *pcm = runtime->private_data; |
544 | 466 | ||
545 | kfree(saapcm); | 467 | kfree(pcm); |
546 | } | 468 | } |
547 | 469 | ||
548 | 470 | ||
@@ -552,17 +474,76 @@ static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) | |||
552 | * - One of the ALSA capture callbacks. | 474 | * - One of the ALSA capture callbacks. |
553 | * | 475 | * |
554 | * Called on initialization, right before the PCM preparation | 476 | * Called on initialization, right before the PCM preparation |
555 | * Usually used in ALSA to allocate the DMA, but since we don't use the | ||
556 | * ALSA DMA it does nothing | ||
557 | * | 477 | * |
558 | */ | 478 | */ |
559 | 479 | ||
560 | static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, | 480 | static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, |
561 | snd_pcm_hw_params_t * hw_params) | 481 | snd_pcm_hw_params_t * hw_params) |
562 | { | 482 | { |
483 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | ||
484 | struct saa7134_dev *dev; | ||
485 | unsigned int period_size, periods; | ||
486 | int err; | ||
563 | 487 | ||
564 | return 0; | 488 | period_size = params_period_bytes(hw_params); |
489 | periods = params_periods(hw_params); | ||
490 | |||
491 | snd_assert(period_size >= 0x100 && period_size <= 0x10000, | ||
492 | return -EINVAL); | ||
493 | snd_assert(periods >= 2, return -EINVAL); | ||
494 | snd_assert(period_size * periods <= 1024 * 1024, return -EINVAL); | ||
565 | 495 | ||
496 | dev = saa7134->dev; | ||
497 | |||
498 | if (dev->dmasound.blocks == periods && | ||
499 | dev->dmasound.blksize == period_size) | ||
500 | return 0; | ||
501 | |||
502 | /* release the old buffer */ | ||
503 | if (substream->runtime->dma_area) { | ||
504 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); | ||
505 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); | ||
506 | dsp_buffer_free(dev); | ||
507 | substream->runtime->dma_area = NULL; | ||
508 | } | ||
509 | dev->dmasound.blocks = periods; | ||
510 | dev->dmasound.blksize = period_size; | ||
511 | dev->dmasound.bufsize = period_size * periods; | ||
512 | |||
513 | err = dsp_buffer_init(dev); | ||
514 | if (0 != err) { | ||
515 | dev->dmasound.blocks = 0; | ||
516 | dev->dmasound.blksize = 0; | ||
517 | dev->dmasound.bufsize = 0; | ||
518 | return err; | ||
519 | } | ||
520 | |||
521 | if (0 != (err = videobuf_dma_pci_map(dev->pci, &dev->dmasound.dma))) { | ||
522 | dsp_buffer_free(dev); | ||
523 | return err; | ||
524 | } | ||
525 | if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) { | ||
526 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); | ||
527 | dsp_buffer_free(dev); | ||
528 | return err; | ||
529 | } | ||
530 | if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt, | ||
531 | dev->dmasound.dma.sglist, | ||
532 | dev->dmasound.dma.sglen, | ||
533 | 0))) { | ||
534 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); | ||
535 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); | ||
536 | dsp_buffer_free(dev); | ||
537 | return err; | ||
538 | } | ||
539 | |||
540 | /* I should be able to use runtime->dma_addr in the control | ||
541 | byte, but it doesn't work. So I allocate the DMA using the | ||
542 | V4L functions, and force ALSA to use that as the DMA area */ | ||
543 | |||
544 | substream->runtime->dma_area = dev->dmasound.dma.vmalloc; | ||
545 | |||
546 | return 1; | ||
566 | 547 | ||
567 | } | 548 | } |
568 | 549 | ||
@@ -572,33 +553,23 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, | |||
572 | * - One of the ALSA capture callbacks. | 553 | * - One of the ALSA capture callbacks. |
573 | * | 554 | * |
574 | * Called after closing the device, but before snd_card_saa7134_capture_close | 555 | * Called after closing the device, but before snd_card_saa7134_capture_close |
575 | * Usually used in ALSA to free the DMA, but since we don't use the | 556 | * It stops the DMA audio and releases the buffers. |
576 | * ALSA DMA I'm almost sure this isn't necessary. | ||
577 | * | 557 | * |
578 | */ | 558 | */ |
579 | 559 | ||
580 | static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) | 560 | static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) |
581 | { | 561 | { |
582 | return 0; | 562 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
583 | } | 563 | struct saa7134_dev *dev; |
584 | |||
585 | /* | ||
586 | * DMA buffer release | ||
587 | * | ||
588 | * Called after closing the device, during snd_card_saa7134_capture_close | ||
589 | * | ||
590 | */ | ||
591 | |||
592 | static int dsp_buffer_free(struct saa7134_dev *dev) | ||
593 | { | ||
594 | if (!dev->dmasound.blksize) | ||
595 | BUG(); | ||
596 | 564 | ||
597 | videobuf_dma_free(&dev->dmasound.dma); | 565 | dev = saa7134->dev; |
598 | 566 | ||
599 | dev->dmasound.blocks = 0; | 567 | if (substream->runtime->dma_area) { |
600 | dev->dmasound.blksize = 0; | 568 | saa7134_pgtable_free(dev->pci, &dev->dmasound.pt); |
601 | dev->dmasound.bufsize = 0; | 569 | videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma); |
570 | dsp_buffer_free(dev); | ||
571 | substream->runtime->dma_area = NULL; | ||
572 | } | ||
602 | 573 | ||
603 | return 0; | 574 | return 0; |
604 | } | 575 | } |
@@ -608,21 +579,12 @@ static int dsp_buffer_free(struct saa7134_dev *dev) | |||
608 | * | 579 | * |
609 | * - One of the ALSA capture callbacks. | 580 | * - One of the ALSA capture callbacks. |
610 | * | 581 | * |
611 | * Called after closing the device. It stops the DMA audio and releases | 582 | * Called after closing the device. |
612 | * the buffers | ||
613 | * | 583 | * |
614 | */ | 584 | */ |
615 | 585 | ||
616 | static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) | 586 | static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) |
617 | { | 587 | { |
618 | snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); | ||
619 | struct saa7134_dev *dev = chip->saadev; | ||
620 | |||
621 | /* unlock buffer */ | ||
622 | saa7134_pgtable_free(dev->pci,&dev->dmasound.pt); | ||
623 | videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma); | ||
624 | |||
625 | dsp_buffer_free(dev); | ||
626 | return 0; | 588 | return 0; |
627 | } | 589 | } |
628 | 590 | ||
@@ -639,29 +601,28 @@ static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) | |||
639 | static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) | 601 | static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) |
640 | { | 602 | { |
641 | snd_pcm_runtime_t *runtime = substream->runtime; | 603 | snd_pcm_runtime_t *runtime = substream->runtime; |
642 | snd_card_saa7134_pcm_t *saapcm; | 604 | snd_card_saa7134_pcm_t *pcm; |
643 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | 605 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
644 | struct saa7134_dev *dev = saa7134->saadev; | 606 | struct saa7134_dev *dev = saa7134->dev; |
645 | int err; | 607 | int err; |
646 | 608 | ||
647 | down(&dev->dmasound.lock); | 609 | down(&dev->dmasound.lock); |
648 | 610 | ||
649 | dev->dmasound.afmt = SNDRV_PCM_FORMAT_U8; | ||
650 | dev->dmasound.channels = 2; | ||
651 | dev->dmasound.read_count = 0; | 611 | dev->dmasound.read_count = 0; |
652 | dev->dmasound.read_offset = 0; | 612 | dev->dmasound.read_offset = 0; |
653 | 613 | ||
654 | up(&dev->dmasound.lock); | 614 | up(&dev->dmasound.lock); |
655 | 615 | ||
656 | saapcm = kzalloc(sizeof(*saapcm), GFP_KERNEL); | 616 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
657 | if (saapcm == NULL) | 617 | if (pcm == NULL) |
658 | return -ENOMEM; | 618 | return -ENOMEM; |
659 | saapcm->saadev=saa7134->saadev; | ||
660 | 619 | ||
661 | spin_lock_init(&saapcm->lock); | 620 | pcm->dev=saa7134->dev; |
662 | 621 | ||
663 | saapcm->substream = substream; | 622 | spin_lock_init(&pcm->lock); |
664 | runtime->private_data = saapcm; | 623 | |
624 | pcm->substream = substream; | ||
625 | runtime->private_data = pcm; | ||
665 | runtime->private_free = snd_card_saa7134_runtime_free; | 626 | runtime->private_free = snd_card_saa7134_runtime_free; |
666 | runtime->hw = snd_card_saa7134_capture; | 627 | runtime->hw = snd_card_saa7134_capture; |
667 | 628 | ||
@@ -736,7 +697,6 @@ static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ | |||
736 | static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 697 | static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
737 | { | 698 | { |
738 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 699 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
739 | unsigned long flags; | ||
740 | int change, addr = kcontrol->private_value; | 700 | int change, addr = kcontrol->private_value; |
741 | int left, right; | 701 | int left, right; |
742 | 702 | ||
@@ -750,12 +710,12 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ | |||
750 | right = 0; | 710 | right = 0; |
751 | if (right > 20) | 711 | if (right > 20) |
752 | right = 20; | 712 | right = 20; |
753 | spin_lock_irqsave(&chip->mixer_lock, flags); | 713 | spin_lock_irq(&chip->mixer_lock); |
754 | change = chip->mixer_volume[addr][0] != left || | 714 | change = chip->mixer_volume[addr][0] != left || |
755 | chip->mixer_volume[addr][1] != right; | 715 | chip->mixer_volume[addr][1] != right; |
756 | chip->mixer_volume[addr][0] = left; | 716 | chip->mixer_volume[addr][0] = left; |
757 | chip->mixer_volume[addr][1] = right; | 717 | chip->mixer_volume[addr][1] = right; |
758 | spin_unlock_irqrestore(&chip->mixer_lock, flags); | 718 | spin_unlock_irq(&chip->mixer_lock); |
759 | return change; | 719 | return change; |
760 | } | 720 | } |
761 | 721 | ||
@@ -777,38 +737,37 @@ static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_ | |||
777 | static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 737 | static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
778 | { | 738 | { |
779 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 739 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
780 | unsigned long flags; | ||
781 | int addr = kcontrol->private_value; | 740 | int addr = kcontrol->private_value; |
782 | 741 | ||
783 | spin_lock_irqsave(&chip->mixer_lock, flags); | 742 | spin_lock_irq(&chip->mixer_lock); |
784 | ucontrol->value.integer.value[0] = chip->capture_source[addr][0]; | 743 | ucontrol->value.integer.value[0] = chip->capture_source[addr][0]; |
785 | ucontrol->value.integer.value[1] = chip->capture_source[addr][1]; | 744 | ucontrol->value.integer.value[1] = chip->capture_source[addr][1]; |
786 | spin_unlock_irqrestore(&chip->mixer_lock, flags); | 745 | spin_unlock_irq(&chip->mixer_lock); |
746 | |||
787 | return 0; | 747 | return 0; |
788 | } | 748 | } |
789 | 749 | ||
790 | static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 750 | static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) |
791 | { | 751 | { |
792 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); | 752 | snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol); |
793 | unsigned long flags; | ||
794 | int change, addr = kcontrol->private_value; | 753 | int change, addr = kcontrol->private_value; |
795 | int left, right; | 754 | int left, right; |
796 | u32 anabar, xbarin; | 755 | u32 anabar, xbarin; |
797 | int analog_io, rate; | 756 | int analog_io, rate; |
798 | struct saa7134_dev *dev; | 757 | struct saa7134_dev *dev; |
799 | 758 | ||
800 | dev = chip->saadev; | 759 | dev = chip->dev; |
801 | 760 | ||
802 | left = ucontrol->value.integer.value[0] & 1; | 761 | left = ucontrol->value.integer.value[0] & 1; |
803 | right = ucontrol->value.integer.value[1] & 1; | 762 | right = ucontrol->value.integer.value[1] & 1; |
804 | spin_lock_irqsave(&chip->mixer_lock, flags); | 763 | spin_lock_irq(&chip->mixer_lock); |
805 | 764 | ||
806 | change = chip->capture_source[addr][0] != left || | 765 | change = chip->capture_source[addr][0] != left || |
807 | chip->capture_source[addr][1] != right; | 766 | chip->capture_source[addr][1] != right; |
808 | chip->capture_source[addr][0] = left; | 767 | chip->capture_source[addr][0] = left; |
809 | chip->capture_source[addr][1] = right; | 768 | chip->capture_source[addr][1] = right; |
810 | dev->dmasound.input=addr; | 769 | dev->dmasound.input=addr; |
811 | spin_unlock_irqrestore(&chip->mixer_lock, flags); | 770 | spin_unlock_irq(&chip->mixer_lock); |
812 | 771 | ||
813 | 772 | ||
814 | if (change) { | 773 | if (change) { |
@@ -898,43 +857,44 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) | |||
898 | return 0; | 857 | return 0; |
899 | } | 858 | } |
900 | 859 | ||
901 | static int snd_saa7134_free(snd_card_saa7134_t *chip) | 860 | static void snd_saa7134_free(snd_card_t * card) |
902 | { | 861 | { |
903 | return 0; | 862 | snd_card_saa7134_t *chip = card->private_data; |
904 | } | 863 | |
864 | if (chip->dev->dmasound.priv_data == NULL) | ||
865 | return; | ||
866 | |||
867 | if (chip->irq >= 0) { | ||
868 | synchronize_irq(chip->irq); | ||
869 | free_irq(chip->irq, &chip->dev->dmasound); | ||
870 | } | ||
871 | |||
872 | chip->dev->dmasound.priv_data = NULL; | ||
905 | 873 | ||
906 | static int snd_saa7134_dev_free(snd_device_t *device) | ||
907 | { | ||
908 | snd_card_saa7134_t *chip = device->device_data; | ||
909 | return snd_saa7134_free(chip); | ||
910 | } | 874 | } |
911 | 875 | ||
912 | /* | 876 | /* |
913 | * ALSA initialization | 877 | * ALSA initialization |
914 | * | 878 | * |
915 | * Called by saa7134-core, it creates the basic structures and registers | 879 | * Called by the init routine, once for each saa7134 device present, |
916 | * the ALSA devices | 880 | * it creates the basic structures and registers the ALSA devices |
917 | * | 881 | * |
918 | */ | 882 | */ |
919 | 883 | ||
920 | int alsa_card_saa7134_create (struct saa7134_dev *saadev) | 884 | int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) |
921 | { | 885 | { |
922 | static int dev; | ||
923 | 886 | ||
924 | snd_card_t *card; | 887 | snd_card_t *card; |
925 | snd_card_saa7134_t *chip; | 888 | snd_card_saa7134_t *chip; |
926 | int err; | 889 | int err; |
927 | static snd_device_ops_t ops = { | ||
928 | .dev_free = snd_saa7134_dev_free, | ||
929 | }; | ||
930 | 890 | ||
931 | 891 | ||
932 | if (dev >= SNDRV_CARDS) | 892 | if (devnum >= SNDRV_CARDS) |
933 | return -ENODEV; | 893 | return -ENODEV; |
934 | if (!enable[dev]) | 894 | if (!enable[devnum]) |
935 | return -ENODEV; | 895 | return -ENODEV; |
936 | 896 | ||
937 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | 897 | card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t)); |
938 | 898 | ||
939 | if (card == NULL) | 899 | if (card == NULL) |
940 | return -ENOMEM; | 900 | return -ENOMEM; |
@@ -943,34 +903,33 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev) | |||
943 | 903 | ||
944 | /* Card "creation" */ | 904 | /* Card "creation" */ |
945 | 905 | ||
946 | chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); | 906 | card->private_free = snd_saa7134_free; |
947 | if (chip == NULL) { | 907 | chip = (snd_card_saa7134_t *) card->private_data; |
948 | return -ENOMEM; | ||
949 | } | ||
950 | 908 | ||
951 | spin_lock_init(&chip->lock); | 909 | spin_lock_init(&chip->lock); |
952 | spin_lock_init(&chip->mixer_lock); | 910 | spin_lock_init(&chip->mixer_lock); |
953 | 911 | ||
954 | chip->saadev = saadev; | 912 | chip->dev = dev; |
955 | 913 | ||
956 | chip->card = card; | 914 | chip->card = card; |
957 | 915 | ||
958 | chip->pci = saadev->pci; | 916 | chip->pci = dev->pci; |
959 | chip->irq = saadev->pci->irq; | 917 | chip->iobase = pci_resource_start(dev->pci, 0); |
960 | chip->iobase = pci_resource_start(saadev->pci, 0); | ||
961 | 918 | ||
962 | err = request_irq(saadev->pci->irq, saa7134_alsa_irq, | 919 | |
963 | SA_SHIRQ | SA_INTERRUPT, saadev->name, saadev); | 920 | err = request_irq(dev->pci->irq, saa7134_alsa_irq, |
921 | SA_SHIRQ | SA_INTERRUPT, dev->name, | ||
922 | (void*) &dev->dmasound); | ||
964 | 923 | ||
965 | if (err < 0) { | 924 | if (err < 0) { |
966 | printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n", | 925 | printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n", |
967 | saadev->name, saadev->pci->irq); | 926 | dev->name, dev->pci->irq); |
968 | goto __nodev; | 927 | goto __nodev; |
969 | } | 928 | } |
970 | 929 | ||
971 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | 930 | chip->irq = dev->pci->irq; |
972 | goto __nodev; | 931 | |
973 | } | 932 | init_MUTEX(&dev->dmasound.lock); |
974 | 933 | ||
975 | if ((err = snd_card_saa7134_new_mixer(chip)) < 0) | 934 | if ((err = snd_card_saa7134_new_mixer(chip)) < 0) |
976 | goto __nodev; | 935 | goto __nodev; |
@@ -984,16 +943,15 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev) | |||
984 | 943 | ||
985 | strcpy(card->shortname, "SAA7134"); | 944 | strcpy(card->shortname, "SAA7134"); |
986 | sprintf(card->longname, "%s at 0x%lx irq %d", | 945 | sprintf(card->longname, "%s at 0x%lx irq %d", |
987 | chip->saadev->name, chip->iobase, chip->irq); | 946 | chip->dev->name, chip->iobase, chip->irq); |
988 | 947 | ||
989 | if ((err = snd_card_register(card)) == 0) { | 948 | if ((err = snd_card_register(card)) == 0) { |
990 | snd_saa7134_cards[dev] = card; | 949 | snd_saa7134_cards[devnum] = card; |
991 | return 0; | 950 | return 0; |
992 | } | 951 | } |
993 | 952 | ||
994 | __nodev: | 953 | __nodev: |
995 | snd_card_free(card); | 954 | snd_card_free(card); |
996 | kfree(chip); | ||
997 | return err; | 955 | return err; |
998 | } | 956 | } |
999 | 957 | ||
@@ -1007,21 +965,29 @@ __nodev: | |||
1007 | 965 | ||
1008 | static int saa7134_alsa_init(void) | 966 | static int saa7134_alsa_init(void) |
1009 | { | 967 | { |
1010 | struct saa7134_dev *saadev = NULL; | 968 | struct saa7134_dev *dev = NULL; |
1011 | struct list_head *list; | 969 | struct list_head *list; |
1012 | 970 | ||
1013 | printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n"); | 971 | position = 0; |
1014 | 972 | ||
1015 | list_for_each(list,&saa7134_devlist) { | 973 | printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n"); |
1016 | saadev = list_entry(list, struct saa7134_dev, devlist); | ||
1017 | alsa_card_saa7134_create(saadev); | ||
1018 | } | ||
1019 | 974 | ||
1020 | if (saadev == NULL) | 975 | list_for_each(list,&saa7134_devlist) { |
976 | dev = list_entry(list, struct saa7134_dev, devlist); | ||
977 | if (dev->dmasound.priv_data == NULL) { | ||
978 | dev->dmasound.priv_data = dev; | ||
979 | alsa_card_saa7134_create(dev,position); | ||
980 | position++; | ||
981 | } else { | ||
982 | printk(KERN_ERR "saa7134 ALSA: DMA sound is being handled by OSS. ignoring %s\n",dev->name); | ||
983 | return -EBUSY; | ||
984 | } | ||
985 | } | ||
986 | |||
987 | if (dev == NULL) | ||
1021 | printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n"); | 988 | printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n"); |
1022 | 989 | ||
1023 | return 0; | 990 | return 0; |
1024 | |||
1025 | } | 991 | } |
1026 | 992 | ||
1027 | /* | 993 | /* |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 663d03e5bc67..75abc20b0ccd 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -2529,6 +2529,32 @@ struct saa7134_board saa7134_boards[] = { | |||
2529 | .amux = LINE1, | 2529 | .amux = LINE1, |
2530 | }}, | 2530 | }}, |
2531 | }, | 2531 | }, |
2532 | [SAA7134_BOARD_MSI_TVATANYWHERE_PLUS] = { | ||
2533 | .name = "MSI TV@Anywhere plus", | ||
2534 | .audio_clock = 0x00187de7, | ||
2535 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
2536 | .radio_type = UNSET, | ||
2537 | .tuner_addr = ADDR_UNSET, | ||
2538 | .radio_addr = ADDR_UNSET, | ||
2539 | .inputs = {{ | ||
2540 | .name = name_tv, | ||
2541 | .vmux = 1, | ||
2542 | .amux = TV, | ||
2543 | .tv = 1, | ||
2544 | },{ | ||
2545 | .name = name_comp1, | ||
2546 | .vmux = 3, | ||
2547 | .amux = LINE1, | ||
2548 | },{ | ||
2549 | .name = name_svideo, | ||
2550 | .vmux = 0, | ||
2551 | .amux = LINE1, | ||
2552 | }}, | ||
2553 | .radio = { | ||
2554 | .name = name_radio, | ||
2555 | .amux = LINE1, | ||
2556 | }, | ||
2557 | }, | ||
2532 | }; | 2558 | }; |
2533 | 2559 | ||
2534 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); | 2560 | const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); |
@@ -2970,6 +2996,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
2970 | .subdevice = 0x2018, | 2996 | .subdevice = 0x2018, |
2971 | .driver_data = SAA7134_BOARD_PHILIPS_TIGER, | 2997 | .driver_data = SAA7134_BOARD_PHILIPS_TIGER, |
2972 | },{ | 2998 | },{ |
2999 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
3000 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
3001 | .subvendor = 0x1462, | ||
3002 | .subdevice = 0x6231, | ||
3003 | .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS, | ||
3004 | },{ | ||
2973 | /* --- boards without eeprom + subsystem ID --- */ | 3005 | /* --- boards without eeprom + subsystem ID --- */ |
2974 | .vendor = PCI_VENDOR_ID_PHILIPS, | 3006 | .vendor = PCI_VENDOR_ID_PHILIPS, |
2975 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 3007 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 19b88744fb31..4275d2ddb864 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -53,13 +53,13 @@ static unsigned int gpio_tracking = 0; | |||
53 | module_param(gpio_tracking, int, 0644); | 53 | module_param(gpio_tracking, int, 0644); |
54 | MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); | 54 | MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); |
55 | 55 | ||
56 | static unsigned int oss = 0; | ||
57 | module_param(oss, int, 0444); | ||
58 | MODULE_PARM_DESC(oss,"register oss devices (default: no)"); | ||
59 | |||
60 | static unsigned int alsa = 0; | 56 | static unsigned int alsa = 0; |
61 | module_param(alsa, int, 0444); | 57 | module_param(alsa, int, 0644); |
62 | MODULE_PARM_DESC(alsa,"register alsa devices (default: no)"); | 58 | MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]"); |
59 | |||
60 | static unsigned int oss = 0; | ||
61 | module_param(oss, int, 0644); | ||
62 | MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]"); | ||
63 | 63 | ||
64 | static unsigned int latency = UNSET; | 64 | static unsigned int latency = UNSET; |
65 | module_param(latency, int, 0444); | 65 | module_param(latency, int, 0444); |
@@ -68,24 +68,18 @@ MODULE_PARM_DESC(latency,"pci latency timer"); | |||
68 | static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 68 | static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
69 | static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 69 | static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
70 | static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 70 | static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
71 | static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | ||
72 | static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | ||
73 | static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 71 | static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
74 | static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | 72 | static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
75 | 73 | ||
76 | module_param_array(video_nr, int, NULL, 0444); | 74 | module_param_array(video_nr, int, NULL, 0444); |
77 | module_param_array(vbi_nr, int, NULL, 0444); | 75 | module_param_array(vbi_nr, int, NULL, 0444); |
78 | module_param_array(radio_nr, int, NULL, 0444); | 76 | module_param_array(radio_nr, int, NULL, 0444); |
79 | module_param_array(dsp_nr, int, NULL, 0444); | ||
80 | module_param_array(mixer_nr, int, NULL, 0444); | ||
81 | module_param_array(tuner, int, NULL, 0444); | 77 | module_param_array(tuner, int, NULL, 0444); |
82 | module_param_array(card, int, NULL, 0444); | 78 | module_param_array(card, int, NULL, 0444); |
83 | 79 | ||
84 | MODULE_PARM_DESC(video_nr, "video device number"); | 80 | MODULE_PARM_DESC(video_nr, "video device number"); |
85 | MODULE_PARM_DESC(vbi_nr, "vbi device number"); | 81 | MODULE_PARM_DESC(vbi_nr, "vbi device number"); |
86 | MODULE_PARM_DESC(radio_nr, "radio device number"); | 82 | MODULE_PARM_DESC(radio_nr, "radio device number"); |
87 | MODULE_PARM_DESC(dsp_nr, "oss dsp device number"); | ||
88 | MODULE_PARM_DESC(mixer_nr, "oss mixer device number"); | ||
89 | MODULE_PARM_DESC(tuner, "tuner type"); | 83 | MODULE_PARM_DESC(tuner, "tuner type"); |
90 | MODULE_PARM_DESC(card, "card type"); | 84 | MODULE_PARM_DESC(card, "card type"); |
91 | 85 | ||
@@ -195,6 +189,7 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg) | |||
195 | static int need_empress; | 189 | static int need_empress; |
196 | static int need_dvb; | 190 | static int need_dvb; |
197 | static int need_alsa; | 191 | static int need_alsa; |
192 | static int need_oss; | ||
198 | 193 | ||
199 | static int pending_call(struct notifier_block *self, unsigned long state, | 194 | static int pending_call(struct notifier_block *self, unsigned long state, |
200 | void *module) | 195 | void *module) |
@@ -208,6 +203,8 @@ static int pending_call(struct notifier_block *self, unsigned long state, | |||
208 | request_module("saa7134-dvb"); | 203 | request_module("saa7134-dvb"); |
209 | if (need_alsa) | 204 | if (need_alsa) |
210 | request_module("saa7134-alsa"); | 205 | request_module("saa7134-alsa"); |
206 | if (need_oss) | ||
207 | request_module("saa7134-oss"); | ||
211 | return NOTIFY_DONE; | 208 | return NOTIFY_DONE; |
212 | } | 209 | } |
213 | 210 | ||
@@ -218,10 +215,11 @@ static struct notifier_block pending_notifier = { | |||
218 | 215 | ||
219 | static void request_module_depend(char *name, int *flag) | 216 | static void request_module_depend(char *name, int *flag) |
220 | { | 217 | { |
218 | int err; | ||
221 | switch (THIS_MODULE->state) { | 219 | switch (THIS_MODULE->state) { |
222 | case MODULE_STATE_COMING: | 220 | case MODULE_STATE_COMING: |
223 | if (!pending_registered) { | 221 | if (!pending_registered) { |
224 | register_module_notifier(&pending_notifier); | 222 | err = register_module_notifier(&pending_notifier); |
225 | pending_registered = 1; | 223 | pending_registered = 1; |
226 | } | 224 | } |
227 | *flag = 1; | 225 | *flag = 1; |
@@ -578,12 +576,14 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
578 | goto out; | 576 | goto out; |
579 | } | 577 | } |
580 | 578 | ||
581 | /* If alsa support is active and we get a sound report, exit | 579 | /* If dmasound support is active and we get a sound report, exit |
582 | and let the saa7134-alsa module deal with it */ | 580 | and let the saa7134-alsa/oss module deal with it */ |
583 | 581 | ||
584 | if ((report & SAA7134_IRQ_REPORT_DONE_RA3) && alsa) { | 582 | if ((report & SAA7134_IRQ_REPORT_DONE_RA3) && |
583 | (dev->dmasound.priv_data != NULL) ) | ||
584 | { | ||
585 | if (irq_debug > 1) | 585 | if (irq_debug > 1) |
586 | printk(KERN_DEBUG "%s/irq: ignoring interrupt for ALSA\n", | 586 | printk(KERN_DEBUG "%s/irq: ignoring interrupt for DMA sound\n", |
587 | dev->name); | 587 | dev->name); |
588 | goto out; | 588 | goto out; |
589 | } | 589 | } |
@@ -609,12 +609,6 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
609 | card_has_mpeg(dev)) | 609 | card_has_mpeg(dev)) |
610 | saa7134_irq_ts_done(dev,status); | 610 | saa7134_irq_ts_done(dev,status); |
611 | 611 | ||
612 | if ((report & SAA7134_IRQ_REPORT_DONE_RA3)) { | ||
613 | if (oss) { | ||
614 | saa7134_irq_oss_done(dev,status); | ||
615 | } | ||
616 | } | ||
617 | |||
618 | if ((report & (SAA7134_IRQ_REPORT_GPIO16 | | 612 | if ((report & (SAA7134_IRQ_REPORT_GPIO16 | |
619 | SAA7134_IRQ_REPORT_GPIO18)) && | 613 | SAA7134_IRQ_REPORT_GPIO18)) && |
620 | dev->remote) | 614 | dev->remote) |
@@ -689,14 +683,6 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) | |||
689 | * audio will not work. | 683 | * audio will not work. |
690 | */ | 684 | */ |
691 | 685 | ||
692 | switch (dev->pci->device) { | ||
693 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
694 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
695 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
696 | saa7134_oss_init1(dev); | ||
697 | break; | ||
698 | } | ||
699 | |||
700 | /* enable peripheral devices */ | 686 | /* enable peripheral devices */ |
701 | saa_writeb(SAA7134_SPECIAL_MODE, 0x01); | 687 | saa_writeb(SAA7134_SPECIAL_MODE, 0x01); |
702 | 688 | ||
@@ -728,8 +714,6 @@ static int saa7134_hwinit2(struct saa7134_dev *dev) | |||
728 | irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 | | 714 | irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 | |
729 | SAA7134_IRQ2_INTE_GPIO18A | | 715 | SAA7134_IRQ2_INTE_GPIO18A | |
730 | SAA7134_IRQ2_INTE_GPIO16 ); | 716 | SAA7134_IRQ2_INTE_GPIO16 ); |
731 | else if (dev->has_remote == SAA7134_REMOTE_I2C) | ||
732 | request_module("ir-kbd-i2c"); | ||
733 | 717 | ||
734 | saa_writel(SAA7134_IRQ1, 0); | 718 | saa_writel(SAA7134_IRQ1, 0); |
735 | saa_writel(SAA7134_IRQ2, irq2_mask); | 719 | saa_writel(SAA7134_IRQ2, irq2_mask); |
@@ -742,13 +726,6 @@ static int saa7134_hwfini(struct saa7134_dev *dev) | |||
742 | { | 726 | { |
743 | dprintk("hwfini\n"); | 727 | dprintk("hwfini\n"); |
744 | 728 | ||
745 | switch (dev->pci->device) { | ||
746 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
747 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
748 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
749 | saa7134_oss_fini(dev); | ||
750 | break; | ||
751 | } | ||
752 | if (card_has_mpeg(dev)) | 729 | if (card_has_mpeg(dev)) |
753 | saa7134_ts_fini(dev); | 730 | saa7134_ts_fini(dev); |
754 | saa7134_input_fini(dev); | 731 | saa7134_input_fini(dev); |
@@ -986,11 +963,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
986 | if (card_is_dvb(dev)) | 963 | if (card_is_dvb(dev)) |
987 | request_module_depend("saa7134-dvb",&need_dvb); | 964 | request_module_depend("saa7134-dvb",&need_dvb); |
988 | 965 | ||
989 | if (!oss && alsa) { | 966 | |
990 | dprintk("Requesting ALSA module\n"); | 967 | if (alsa) |
991 | request_module_depend("saa7134-alsa",&need_alsa); | 968 | request_module_depend("saa7134-alsa",&need_alsa); |
992 | } | ||
993 | 969 | ||
970 | if (oss) | ||
971 | request_module_depend("saa7134-oss",&need_oss); | ||
994 | 972 | ||
995 | v4l2_prio_init(&dev->prio); | 973 | v4l2_prio_init(&dev->prio); |
996 | 974 | ||
@@ -1024,32 +1002,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1024 | dev->name,dev->radio_dev->minor & 0x1f); | 1002 | dev->name,dev->radio_dev->minor & 0x1f); |
1025 | } | 1003 | } |
1026 | 1004 | ||
1027 | /* register oss devices */ | ||
1028 | switch (dev->pci->device) { | ||
1029 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
1030 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
1031 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
1032 | if (oss) { | ||
1033 | err = dev->dmasound.minor_dsp = | ||
1034 | register_sound_dsp(&saa7134_dsp_fops, | ||
1035 | dsp_nr[dev->nr]); | ||
1036 | if (err < 0) { | ||
1037 | goto fail4; | ||
1038 | } | ||
1039 | printk(KERN_INFO "%s: registered device dsp%d\n", | ||
1040 | dev->name,dev->dmasound.minor_dsp >> 4); | ||
1041 | |||
1042 | err = dev->dmasound.minor_mixer = | ||
1043 | register_sound_mixer(&saa7134_mixer_fops, | ||
1044 | mixer_nr[dev->nr]); | ||
1045 | if (err < 0) | ||
1046 | goto fail5; | ||
1047 | printk(KERN_INFO "%s: registered device mixer%d\n", | ||
1048 | dev->name,dev->dmasound.minor_mixer >> 4); | ||
1049 | } | ||
1050 | break; | ||
1051 | } | ||
1052 | |||
1053 | /* everything worked */ | 1005 | /* everything worked */ |
1054 | pci_set_drvdata(pci_dev,dev); | 1006 | pci_set_drvdata(pci_dev,dev); |
1055 | saa7134_devcount++; | 1007 | saa7134_devcount++; |
@@ -1064,17 +1016,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1064 | 1016 | ||
1065 | /* check for signal */ | 1017 | /* check for signal */ |
1066 | saa7134_irq_video_intl(dev); | 1018 | saa7134_irq_video_intl(dev); |
1019 | |||
1067 | return 0; | 1020 | return 0; |
1068 | 1021 | ||
1069 | fail5: | ||
1070 | switch (dev->pci->device) { | ||
1071 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
1072 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
1073 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
1074 | if (oss) | ||
1075 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
1076 | break; | ||
1077 | } | ||
1078 | fail4: | 1022 | fail4: |
1079 | saa7134_unregister_video(dev); | 1023 | saa7134_unregister_video(dev); |
1080 | saa7134_i2c_unregister(dev); | 1024 | saa7134_i2c_unregister(dev); |
@@ -1125,19 +1069,16 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) | |||
1125 | saa7134_devcount--; | 1069 | saa7134_devcount--; |
1126 | 1070 | ||
1127 | saa7134_i2c_unregister(dev); | 1071 | saa7134_i2c_unregister(dev); |
1128 | switch (dev->pci->device) { | ||
1129 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
1130 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
1131 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
1132 | if (oss) { | ||
1133 | unregister_sound_mixer(dev->dmasound.minor_mixer); | ||
1134 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
1135 | } | ||
1136 | break; | ||
1137 | } | ||
1138 | saa7134_unregister_video(dev); | 1072 | saa7134_unregister_video(dev); |
1139 | 1073 | ||
1140 | /* release ressources */ | 1074 | /* the DMA sound modules should be unloaded before reaching |
1075 | this, but just in case they are still present... */ | ||
1076 | if (dev->dmasound.priv_data != NULL) { | ||
1077 | free_irq(pci_dev->irq, &dev->dmasound); | ||
1078 | dev->dmasound.priv_data = NULL; | ||
1079 | } | ||
1080 | |||
1081 | /* release resources */ | ||
1141 | free_irq(pci_dev->irq, dev); | 1082 | free_irq(pci_dev->irq, dev); |
1142 | iounmap(dev->lmmio); | 1083 | iounmap(dev->lmmio); |
1143 | release_mem_region(pci_resource_start(pci_dev,0), | 1084 | release_mem_region(pci_resource_start(pci_dev,0), |
@@ -1225,7 +1166,7 @@ EXPORT_SYMBOL(saa7134_i2c_call_clients); | |||
1225 | EXPORT_SYMBOL(saa7134_devlist); | 1166 | EXPORT_SYMBOL(saa7134_devlist); |
1226 | EXPORT_SYMBOL(saa7134_boards); | 1167 | EXPORT_SYMBOL(saa7134_boards); |
1227 | 1168 | ||
1228 | /* ----------------- For ALSA -------------------------------- */ | 1169 | /* ----------------- for the DMA sound modules --------------- */ |
1229 | 1170 | ||
1230 | EXPORT_SYMBOL(saa7134_pgtable_free); | 1171 | EXPORT_SYMBOL(saa7134_pgtable_free); |
1231 | EXPORT_SYMBOL(saa7134_pgtable_build); | 1172 | EXPORT_SYMBOL(saa7134_pgtable_build); |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 329accda6d45..e648cc3bc96d 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -485,64 +485,6 @@ static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = { | |||
485 | 485 | ||
486 | }; | 486 | }; |
487 | 487 | ||
488 | static IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = { | ||
489 | [ 0x59 ] = KEY_MUTE, | ||
490 | [ 0x4a ] = KEY_POWER, | ||
491 | |||
492 | [ 0x18 ] = KEY_TEXT, | ||
493 | [ 0x26 ] = KEY_TV, | ||
494 | [ 0x3d ] = KEY_PRINT, | ||
495 | |||
496 | [ 0x48 ] = KEY_RED, | ||
497 | [ 0x04 ] = KEY_GREEN, | ||
498 | [ 0x11 ] = KEY_YELLOW, | ||
499 | [ 0x00 ] = KEY_BLUE, | ||
500 | |||
501 | [ 0x2d ] = KEY_VOLUMEUP, | ||
502 | [ 0x1e ] = KEY_VOLUMEDOWN, | ||
503 | |||
504 | [ 0x49 ] = KEY_MENU, | ||
505 | |||
506 | [ 0x16 ] = KEY_CHANNELUP, | ||
507 | [ 0x17 ] = KEY_CHANNELDOWN, | ||
508 | |||
509 | [ 0x20 ] = KEY_UP, | ||
510 | [ 0x21 ] = KEY_DOWN, | ||
511 | [ 0x22 ] = KEY_LEFT, | ||
512 | [ 0x23 ] = KEY_RIGHT, | ||
513 | [ 0x0d ] = KEY_SELECT, | ||
514 | |||
515 | |||
516 | |||
517 | [ 0x08 ] = KEY_BACK, | ||
518 | [ 0x07 ] = KEY_REFRESH, | ||
519 | |||
520 | [ 0x2f ] = KEY_ZOOM, | ||
521 | [ 0x29 ] = KEY_RECORD, | ||
522 | |||
523 | [ 0x4b ] = KEY_PAUSE, | ||
524 | [ 0x4d ] = KEY_REWIND, | ||
525 | [ 0x2e ] = KEY_PLAY, | ||
526 | [ 0x4e ] = KEY_FORWARD, | ||
527 | [ 0x53 ] = KEY_PREVIOUS, | ||
528 | [ 0x4c ] = KEY_STOP, | ||
529 | [ 0x54 ] = KEY_NEXT, | ||
530 | |||
531 | [ 0x69 ] = KEY_KP0, | ||
532 | [ 0x6a ] = KEY_KP1, | ||
533 | [ 0x6b ] = KEY_KP2, | ||
534 | [ 0x6c ] = KEY_KP3, | ||
535 | [ 0x6d ] = KEY_KP4, | ||
536 | [ 0x6e ] = KEY_KP5, | ||
537 | [ 0x6f ] = KEY_KP6, | ||
538 | [ 0x70 ] = KEY_KP7, | ||
539 | [ 0x71 ] = KEY_KP8, | ||
540 | [ 0x72 ] = KEY_KP9, | ||
541 | |||
542 | [ 0x74 ] = KEY_CHANNEL, | ||
543 | [ 0x0a ] = KEY_BACKSPACE, | ||
544 | }; | ||
545 | |||
546 | /* Mapping for the 28 key remote control as seen at | 488 | /* Mapping for the 28 key remote control as seen at |
547 | http://www.sednacomputer.com/photo/cardbus-tv.jpg | 489 | http://www.sednacomputer.com/photo/cardbus-tv.jpg |
548 | Pavel Mihaylov <bin@bash.info> */ | 490 | Pavel Mihaylov <bin@bash.info> */ |
@@ -635,57 +577,6 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
635 | return 1; | 577 | return 1; |
636 | } | 578 | } |
637 | 579 | ||
638 | /* The new pinnacle PCTV remote (with the colored buttons) | ||
639 | * | ||
640 | * Ricardo Cerqueira <v4l@cerqueira.org> | ||
641 | */ | ||
642 | |||
643 | static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
644 | { | ||
645 | unsigned char b[4]; | ||
646 | unsigned int start = 0,parity = 0,code = 0; | ||
647 | |||
648 | /* poll IR chip */ | ||
649 | if (4 != i2c_master_recv(&ir->c,b,4)) { | ||
650 | i2cdprintk("read error\n"); | ||
651 | return -EIO; | ||
652 | } | ||
653 | |||
654 | for (start = 0; start<4; start++) { | ||
655 | if (b[start] == 0x80) { | ||
656 | code=b[(start+3)%4]; | ||
657 | parity=b[(start+2)%4]; | ||
658 | } | ||
659 | } | ||
660 | |||
661 | /* Empty Request */ | ||
662 | if (parity==0) | ||
663 | return 0; | ||
664 | |||
665 | /* Repeating... */ | ||
666 | if (ir->old == parity) | ||
667 | return 0; | ||
668 | |||
669 | |||
670 | ir->old = parity; | ||
671 | |||
672 | /* Reduce code value to fit inside IR_KEYTAB_SIZE | ||
673 | * | ||
674 | * this is the only value that results in 42 unique | ||
675 | * codes < 128 | ||
676 | */ | ||
677 | |||
678 | code %= 0x88; | ||
679 | |||
680 | *ir_raw = code; | ||
681 | *ir_key = code; | ||
682 | |||
683 | i2cdprintk("Pinnacle PCTV key %02x\n", code); | ||
684 | |||
685 | return 1; | ||
686 | } | ||
687 | |||
688 | |||
689 | void saa7134_input_irq(struct saa7134_dev *dev) | 580 | void saa7134_input_irq(struct saa7134_dev *dev) |
690 | { | 581 | { |
691 | struct saa7134_ir *ir = dev->remote; | 582 | struct saa7134_ir *ir = dev->remote; |
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index fd53dfcc1644..fd9ed11ab1e2 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c | |||
@@ -4,6 +4,8 @@ | |||
4 | * oss dsp interface | 4 | * oss dsp interface |
5 | * | 5 | * |
6 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | 6 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] |
7 | * 2005 conversion to standalone module: | ||
8 | * Ricardo Cerqueira <v4l@cerqueira.org> | ||
7 | * | 9 | * |
8 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
@@ -25,7 +27,9 @@ | |||
25 | #include <linux/module.h> | 27 | #include <linux/module.h> |
26 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
27 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/interrupt.h> | ||
28 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/sound.h> | ||
29 | #include <linux/soundcard.h> | 33 | #include <linux/soundcard.h> |
30 | 34 | ||
31 | #include "saa7134-reg.h" | 35 | #include "saa7134-reg.h" |
@@ -33,15 +37,23 @@ | |||
33 | 37 | ||
34 | /* ------------------------------------------------------------------ */ | 38 | /* ------------------------------------------------------------------ */ |
35 | 39 | ||
36 | static unsigned int oss_debug = 0; | 40 | static unsigned int debug = 0; |
37 | module_param(oss_debug, int, 0644); | 41 | module_param(debug, int, 0644); |
38 | MODULE_PARM_DESC(oss_debug,"enable debug messages [oss]"); | 42 | MODULE_PARM_DESC(debug,"enable debug messages [oss]"); |
39 | 43 | ||
40 | static unsigned int oss_rate = 0; | 44 | static unsigned int rate = 0; |
41 | module_param(oss_rate, int, 0444); | 45 | module_param(rate, int, 0444); |
42 | MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)"); | 46 | MODULE_PARM_DESC(rate,"sample rate (valid are: 32000,48000)"); |
43 | 47 | ||
44 | #define dprintk(fmt, arg...) if (oss_debug) \ | 48 | static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; |
49 | MODULE_PARM_DESC(dsp_nr, "device numbers for SAA7134 capture interface(s)."); | ||
50 | module_param_array(dsp_nr, int, NULL, 0444); | ||
51 | |||
52 | static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET }; | ||
53 | MODULE_PARM_DESC(mixer_nr, "mixer numbers for SAA7134 capture interface(s)."); | ||
54 | module_param_array(mixer_nr, int, NULL, 0444); | ||
55 | |||
56 | #define dprintk(fmt, arg...) if (debug) \ | ||
45 | printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg) | 57 | printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg) |
46 | 58 | ||
47 | 59 | ||
@@ -369,7 +381,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, | |||
369 | int __user *p = argp; | 381 | int __user *p = argp; |
370 | int val = 0; | 382 | int val = 0; |
371 | 383 | ||
372 | if (oss_debug > 1) | 384 | if (debug > 1) |
373 | saa7134_print_ioctl(dev->name,cmd); | 385 | saa7134_print_ioctl(dev->name,cmd); |
374 | switch (cmd) { | 386 | switch (cmd) { |
375 | case OSS_GETVERSION: | 387 | case OSS_GETVERSION: |
@@ -665,7 +677,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file, | |||
665 | void __user *argp = (void __user *) arg; | 677 | void __user *argp = (void __user *) arg; |
666 | int __user *p = argp; | 678 | int __user *p = argp; |
667 | 679 | ||
668 | if (oss_debug > 1) | 680 | if (debug > 1) |
669 | saa7134_print_ioctl(dev->name,cmd); | 681 | saa7134_print_ioctl(dev->name,cmd); |
670 | switch (cmd) { | 682 | switch (cmd) { |
671 | case OSS_GETVERSION: | 683 | case OSS_GETVERSION: |
@@ -768,8 +780,41 @@ struct file_operations saa7134_mixer_fops = { | |||
768 | 780 | ||
769 | /* ------------------------------------------------------------------ */ | 781 | /* ------------------------------------------------------------------ */ |
770 | 782 | ||
783 | static irqreturn_t saa7134_oss_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
784 | { | ||
785 | struct saa7134_dmasound *dmasound = dev_id; | ||
786 | struct saa7134_dev *dev = dmasound->priv_data; | ||
787 | unsigned long report, status; | ||
788 | int loop, handled = 0; | ||
789 | |||
790 | for (loop = 0; loop < 10; loop++) { | ||
791 | report = saa_readl(SAA7134_IRQ_REPORT); | ||
792 | status = saa_readl(SAA7134_IRQ_STATUS); | ||
793 | |||
794 | if (report & SAA7134_IRQ_REPORT_DONE_RA3) { | ||
795 | handled = 1; | ||
796 | saa_writel(SAA7134_IRQ_REPORT,report); | ||
797 | saa7134_irq_oss_done(dev, status); | ||
798 | } else { | ||
799 | goto out; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | if (loop == 10) { | ||
804 | dprintk("error! looping IRQ!"); | ||
805 | } | ||
806 | out: | ||
807 | return IRQ_RETVAL(handled); | ||
808 | } | ||
809 | |||
771 | int saa7134_oss_init1(struct saa7134_dev *dev) | 810 | int saa7134_oss_init1(struct saa7134_dev *dev) |
772 | { | 811 | { |
812 | |||
813 | if ((request_irq(dev->pci->irq, saa7134_oss_irq, | ||
814 | SA_SHIRQ | SA_INTERRUPT, dev->name, | ||
815 | (void*) &dev->dmasound)) < 0) | ||
816 | return -1; | ||
817 | |||
773 | /* general */ | 818 | /* general */ |
774 | init_MUTEX(&dev->dmasound.lock); | 819 | init_MUTEX(&dev->dmasound.lock); |
775 | init_waitqueue_head(&dev->dmasound.wq); | 820 | init_waitqueue_head(&dev->dmasound.wq); |
@@ -785,8 +830,8 @@ int saa7134_oss_init1(struct saa7134_dev *dev) | |||
785 | 830 | ||
786 | /* dsp */ | 831 | /* dsp */ |
787 | dev->dmasound.rate = 32000; | 832 | dev->dmasound.rate = 32000; |
788 | if (oss_rate) | 833 | if (rate) |
789 | dev->dmasound.rate = oss_rate; | 834 | dev->dmasound.rate = rate; |
790 | dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000; | 835 | dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000; |
791 | 836 | ||
792 | /* mixer */ | 837 | /* mixer */ |
@@ -840,7 +885,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) | |||
840 | /* next block addr */ | 885 | /* next block addr */ |
841 | next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks; | 886 | next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks; |
842 | saa_writel(reg,next_blk * dev->dmasound.blksize); | 887 | saa_writel(reg,next_blk * dev->dmasound.blksize); |
843 | if (oss_debug > 2) | 888 | if (debug > 2) |
844 | dprintk("irq: ok, %s, next_blk=%d, addr=%x\n", | 889 | dprintk("irq: ok, %s, next_blk=%d, addr=%x\n", |
845 | (status & 0x10000000) ? "even" : "odd ", next_blk, | 890 | (status & 0x10000000) ? "even" : "odd ", next_blk, |
846 | next_blk * dev->dmasound.blksize); | 891 | next_blk * dev->dmasound.blksize); |
@@ -854,6 +899,98 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status) | |||
854 | spin_unlock(&dev->slock); | 899 | spin_unlock(&dev->slock); |
855 | } | 900 | } |
856 | 901 | ||
902 | int saa7134_dsp_create(struct saa7134_dev *dev) | ||
903 | { | ||
904 | int err; | ||
905 | |||
906 | err = dev->dmasound.minor_dsp = | ||
907 | register_sound_dsp(&saa7134_dsp_fops, | ||
908 | dsp_nr[dev->nr]); | ||
909 | if (err < 0) { | ||
910 | goto fail; | ||
911 | } | ||
912 | printk(KERN_INFO "%s: registered device dsp%d\n", | ||
913 | dev->name,dev->dmasound.minor_dsp >> 4); | ||
914 | |||
915 | err = dev->dmasound.minor_mixer = | ||
916 | register_sound_mixer(&saa7134_mixer_fops, | ||
917 | mixer_nr[dev->nr]); | ||
918 | if (err < 0) | ||
919 | goto fail; | ||
920 | printk(KERN_INFO "%s: registered device mixer%d\n", | ||
921 | dev->name,dev->dmasound.minor_mixer >> 4); | ||
922 | |||
923 | return 0; | ||
924 | |||
925 | fail: | ||
926 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
927 | return 0; | ||
928 | |||
929 | |||
930 | } | ||
931 | |||
932 | static int saa7134_oss_init(void) | ||
933 | { | ||
934 | struct saa7134_dev *dev = NULL; | ||
935 | struct list_head *list; | ||
936 | |||
937 | printk(KERN_INFO "saa7134 OSS driver for DMA sound loaded\n"); | ||
938 | |||
939 | list_for_each(list,&saa7134_devlist) { | ||
940 | dev = list_entry(list, struct saa7134_dev, devlist); | ||
941 | if (dev->dmasound.priv_data == NULL) { | ||
942 | dev->dmasound.priv_data = dev; | ||
943 | saa7134_oss_init1(dev); | ||
944 | saa7134_dsp_create(dev); | ||
945 | } else { | ||
946 | printk(KERN_ERR "saa7134 OSS: DMA sound is being handled by ALSA, ignoring %s\n",dev->name); | ||
947 | return -EBUSY; | ||
948 | } | ||
949 | } | ||
950 | |||
951 | if (dev == NULL) | ||
952 | printk(KERN_INFO "saa7134 OSS: no saa7134 cards found\n"); | ||
953 | |||
954 | return 0; | ||
955 | |||
956 | } | ||
957 | |||
958 | void saa7134_oss_exit(void) | ||
959 | { | ||
960 | struct saa7134_dev *dev = NULL; | ||
961 | struct list_head *list; | ||
962 | |||
963 | list_for_each(list,&saa7134_devlist) { | ||
964 | dev = list_entry(list, struct saa7134_dev, devlist); | ||
965 | |||
966 | /* Device isn't registered by OSS, probably ALSA's */ | ||
967 | if (!dev->dmasound.minor_dsp) | ||
968 | continue; | ||
969 | |||
970 | unregister_sound_mixer(dev->dmasound.minor_mixer); | ||
971 | unregister_sound_dsp(dev->dmasound.minor_dsp); | ||
972 | |||
973 | saa7134_oss_fini(dev); | ||
974 | |||
975 | if (dev->pci->irq > 0) { | ||
976 | synchronize_irq(dev->pci->irq); | ||
977 | free_irq(dev->pci->irq,&dev->dmasound); | ||
978 | } | ||
979 | |||
980 | dev->dmasound.priv_data = NULL; | ||
981 | |||
982 | } | ||
983 | |||
984 | printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n"); | ||
985 | |||
986 | return; | ||
987 | } | ||
988 | |||
989 | module_init(saa7134_oss_init); | ||
990 | module_exit(saa7134_oss_exit); | ||
991 | MODULE_LICENSE("GPL"); | ||
992 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | ||
993 | |||
857 | /* ----------------------------------------------------------- */ | 994 | /* ----------------------------------------------------------- */ |
858 | /* | 995 | /* |
859 | * Local variables: | 996 | * Local variables: |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index fb9727471661..244e1973081c 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -208,6 +208,7 @@ struct saa7134_format { | |||
208 | #define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS 79 | 208 | #define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS 79 |
209 | #define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80 | 209 | #define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80 |
210 | #define SAA7134_BOARD_PHILIPS_TIGER 81 | 210 | #define SAA7134_BOARD_PHILIPS_TIGER 81 |
211 | #define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS 82 | ||
211 | 212 | ||
212 | #define SAA7134_MAXBOARDS 8 | 213 | #define SAA7134_MAXBOARDS 8 |
213 | #define SAA7134_INPUT_MAX 8 | 214 | #define SAA7134_INPUT_MAX 8 |
@@ -383,6 +384,7 @@ struct saa7134_dmasound { | |||
383 | unsigned int dma_blk; | 384 | unsigned int dma_blk; |
384 | unsigned int read_offset; | 385 | unsigned int read_offset; |
385 | unsigned int read_count; | 386 | unsigned int read_count; |
387 | void * priv_data; | ||
386 | snd_pcm_substream_t *substream; | 388 | snd_pcm_substream_t *substream; |
387 | }; | 389 | }; |
388 | 390 | ||
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index b2dfe07e9f9d..61d94ddaff41 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c | |||
@@ -437,6 +437,10 @@ static void set_audio(struct tuner *t) | |||
437 | t->sgIF = 124; | 437 | t->sgIF = 124; |
438 | t->tda8290_easy_mode = 0x20; | 438 | t->tda8290_easy_mode = 0x20; |
439 | mode = "L"; | 439 | mode = "L"; |
440 | } else if (t->std & V4L2_STD_SECAM_LC) { | ||
441 | t->sgIF = 20; | ||
442 | t->tda8290_easy_mode = 0x40; | ||
443 | mode = "LC"; | ||
440 | } | 444 | } |
441 | tuner_dbg("setting tda8290 to system %s\n", mode); | 445 | tuner_dbg("setting tda8290 to system %s\n", mode); |
442 | } | 446 | } |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 73c4041c35d7..e58abdfcaab8 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -251,7 +251,7 @@ static inline int check_mode(struct tuner *t, char *cmd) | |||
251 | 251 | ||
252 | static char pal[] = "-"; | 252 | static char pal[] = "-"; |
253 | module_param_string(pal, pal, sizeof(pal), 0644); | 253 | module_param_string(pal, pal, sizeof(pal), 0644); |
254 | static char secam[] = "-"; | 254 | static char secam[] = "--"; |
255 | module_param_string(secam, secam, sizeof(secam), 0644); | 255 | module_param_string(secam, secam, sizeof(secam), 0644); |
256 | 256 | ||
257 | /* get more precise norm info from insmod option */ | 257 | /* get more precise norm info from insmod option */ |
@@ -307,8 +307,13 @@ static int tuner_fixup_std(struct tuner *t) | |||
307 | break; | 307 | break; |
308 | case 'l': | 308 | case 'l': |
309 | case 'L': | 309 | case 'L': |
310 | tuner_dbg ("insmod fixup: SECAM => SECAM-L\n"); | 310 | if ((secam[1]=='C')||(secam[1]=='c')) { |
311 | t->std = V4L2_STD_SECAM_L; | 311 | tuner_dbg ("insmod fixup: SECAM => SECAM-L'\n"); |
312 | t->std = V4L2_STD_SECAM_LC; | ||
313 | } else { | ||
314 | tuner_dbg ("insmod fixup: SECAM => SECAM-L\n"); | ||
315 | t->std = V4L2_STD_SECAM_L; | ||
316 | } | ||
312 | break; | 317 | break; |
313 | case '-': | 318 | case '-': |
314 | /* default parameter, do nothing */ | 319 | /* default parameter, do nothing */ |
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index d832205818f2..e0c9fdb9914a 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c | |||
@@ -233,7 +233,7 @@ static struct tunertype tuners[] = { | |||
233 | { "Ymec TVision TVF-5533MF", Philips, NTSC, | 233 | { "Ymec TVision TVF-5533MF", Philips, NTSC, |
234 | 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, | 234 | 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732}, |
235 | 235 | ||
236 | /* 60-68 */ | 236 | /* 60-69 */ |
237 | { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, | 237 | { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, |
238 | 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, | 238 | 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, |
239 | { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, | 239 | { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, |
@@ -252,6 +252,8 @@ static struct tunertype tuners[] = { | |||
252 | 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, | 252 | 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, |
253 | { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC, | 253 | { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC, |
254 | 16*157.25,16*454.00,0x01,0x02,0x04,0xce,732 }, | 254 | 16*157.25,16*454.00,0x01,0x02,0x04,0xce,732 }, |
255 | { "Tena TNF 5335 MF", Philips, NTSC, | ||
256 | 16*157.25,16*454.00,0x01,0x02,0x04,0x8e,732 }, | ||
255 | }; | 257 | }; |
256 | 258 | ||
257 | unsigned const int tuner_count = ARRAY_SIZE(tuners); | 259 | unsigned const int tuner_count = ARRAY_SIZE(tuners); |
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 22f286222004..a6936ad74fcf 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c | |||
@@ -5,6 +5,11 @@ | |||
5 | * | 5 | * |
6 | * Based on saa7115 driver | 6 | * Based on saa7115 driver |
7 | * | 7 | * |
8 | * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> | ||
9 | * - Cleanup | ||
10 | * - V4L2 API update | ||
11 | * - sound fixes | ||
12 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 14 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 15 | * the Free Software Foundation; either version 2 of the License, or |
@@ -31,7 +36,7 @@ | |||
31 | #include <media/audiochip.h> | 36 | #include <media/audiochip.h> |
32 | 37 | ||
33 | MODULE_DESCRIPTION("wm8775 driver"); | 38 | MODULE_DESCRIPTION("wm8775 driver"); |
34 | MODULE_AUTHOR("Ulf Eklund"); | 39 | MODULE_AUTHOR("Ulf Eklund, Hans Verkuil"); |
35 | MODULE_LICENSE("GPL"); | 40 | MODULE_LICENSE("GPL"); |
36 | 41 | ||
37 | #define wm8775_err(fmt, arg...) do { \ | 42 | #define wm8775_err(fmt, arg...) do { \ |
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 1e6bdba26756..166c9b0ad04e 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include <asm/div64.h> | 23 | #include <asm/div64.h> |
24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
25 | #include <asm/irq.h> | ||
26 | #include <asm/scatterlist.h> | 25 | #include <asm/scatterlist.h> |
27 | #include <asm/sizes.h> | 26 | #include <asm/sizes.h> |
28 | #include <asm/hardware/amba.h> | 27 | #include <asm/hardware/amba.h> |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 48638c8097a5..846a533323a8 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -94,7 +94,7 @@ config MTD_NETSC520 | |||
94 | 94 | ||
95 | config MTD_TS5500 | 95 | config MTD_TS5500 |
96 | tristate "JEDEC Flash device mapped on Technologic Systems TS-5500" | 96 | tristate "JEDEC Flash device mapped on Technologic Systems TS-5500" |
97 | depends on ELAN | 97 | depends on X86 |
98 | select MTD_PARTITIONS | 98 | select MTD_PARTITIONS |
99 | select MTD_JEDECPROBE | 99 | select MTD_JEDECPROBE |
100 | select MTD_CFI_AMDSTD | 100 | select MTD_CFI_AMDSTD |
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 977935a3d898..824e430486c2 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c | |||
@@ -84,6 +84,7 @@ static int max_interrupt_work = 10; | |||
84 | #include <linux/netdevice.h> | 84 | #include <linux/netdevice.h> |
85 | #include <linux/etherdevice.h> | 85 | #include <linux/etherdevice.h> |
86 | #include <linux/pm.h> | 86 | #include <linux/pm.h> |
87 | #include <linux/pm_legacy.h> | ||
87 | #include <linux/skbuff.h> | 88 | #include <linux/skbuff.h> |
88 | #include <linux/delay.h> /* for udelay() */ | 89 | #include <linux/delay.h> /* for udelay() */ |
89 | #include <linux/spinlock.h> | 90 | #include <linux/spinlock.h> |
@@ -173,7 +174,7 @@ struct el3_private { | |||
173 | /* skb send-queue */ | 174 | /* skb send-queue */ |
174 | int head, size; | 175 | int head, size; |
175 | struct sk_buff *queue[SKB_QUEUE_SIZE]; | 176 | struct sk_buff *queue[SKB_QUEUE_SIZE]; |
176 | #ifdef CONFIG_PM | 177 | #ifdef CONFIG_PM_LEGACY |
177 | struct pm_dev *pmdev; | 178 | struct pm_dev *pmdev; |
178 | #endif | 179 | #endif |
179 | enum { | 180 | enum { |
@@ -200,7 +201,7 @@ static void el3_tx_timeout (struct net_device *dev); | |||
200 | static void el3_down(struct net_device *dev); | 201 | static void el3_down(struct net_device *dev); |
201 | static void el3_up(struct net_device *dev); | 202 | static void el3_up(struct net_device *dev); |
202 | static struct ethtool_ops ethtool_ops; | 203 | static struct ethtool_ops ethtool_ops; |
203 | #ifdef CONFIG_PM | 204 | #ifdef CONFIG_PM_LEGACY |
204 | static int el3_suspend(struct pm_dev *pdev); | 205 | static int el3_suspend(struct pm_dev *pdev); |
205 | static int el3_resume(struct pm_dev *pdev); | 206 | static int el3_resume(struct pm_dev *pdev); |
206 | static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data); | 207 | static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data); |
@@ -361,7 +362,7 @@ static void el3_common_remove (struct net_device *dev) | |||
361 | struct el3_private *lp = netdev_priv(dev); | 362 | struct el3_private *lp = netdev_priv(dev); |
362 | 363 | ||
363 | (void) lp; /* Keep gcc quiet... */ | 364 | (void) lp; /* Keep gcc quiet... */ |
364 | #ifdef CONFIG_PM | 365 | #ifdef CONFIG_PM_LEGACY |
365 | if (lp->pmdev) | 366 | if (lp->pmdev) |
366 | pm_unregister(lp->pmdev); | 367 | pm_unregister(lp->pmdev); |
367 | #endif | 368 | #endif |
@@ -571,7 +572,7 @@ no_pnp: | |||
571 | if (err) | 572 | if (err) |
572 | goto out1; | 573 | goto out1; |
573 | 574 | ||
574 | #ifdef CONFIG_PM | 575 | #ifdef CONFIG_PM_LEGACY |
575 | /* register power management */ | 576 | /* register power management */ |
576 | lp->pmdev = pm_register(PM_ISA_DEV, card_idx, el3_pm_callback); | 577 | lp->pmdev = pm_register(PM_ISA_DEV, card_idx, el3_pm_callback); |
577 | if (lp->pmdev) { | 578 | if (lp->pmdev) { |
@@ -1479,7 +1480,7 @@ el3_up(struct net_device *dev) | |||
1479 | } | 1480 | } |
1480 | 1481 | ||
1481 | /* Power Management support functions */ | 1482 | /* Power Management support functions */ |
1482 | #ifdef CONFIG_PM | 1483 | #ifdef CONFIG_PM_LEGACY |
1483 | 1484 | ||
1484 | static int | 1485 | static int |
1485 | el3_suspend(struct pm_dev *pdev) | 1486 | el3_suspend(struct pm_dev *pdev) |
@@ -1548,7 +1549,7 @@ el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data) | |||
1548 | return 0; | 1549 | return 0; |
1549 | } | 1550 | } |
1550 | 1551 | ||
1551 | #endif /* CONFIG_PM */ | 1552 | #endif /* CONFIG_PM_LEGACY */ |
1552 | 1553 | ||
1553 | /* Parameters that may be passed into the module. */ | 1554 | /* Parameters that may be passed into the module. */ |
1554 | static int debug = -1; | 1555 | static int debug = -1; |
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 30bee11c48bd..d2102a27d307 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c | |||
@@ -586,16 +586,16 @@ struct rtl8139_private { | |||
586 | dma_addr_t tx_bufs_dma; | 586 | dma_addr_t tx_bufs_dma; |
587 | signed char phys[4]; /* MII device addresses. */ | 587 | signed char phys[4]; /* MII device addresses. */ |
588 | char twistie, twist_row, twist_col; /* Twister tune state. */ | 588 | char twistie, twist_row, twist_col; /* Twister tune state. */ |
589 | unsigned int default_port:4; /* Last dev->if_port value. */ | 589 | unsigned int default_port : 4; /* Last dev->if_port value. */ |
590 | unsigned int have_thread : 1; | ||
590 | spinlock_t lock; | 591 | spinlock_t lock; |
591 | spinlock_t rx_lock; | 592 | spinlock_t rx_lock; |
592 | chip_t chipset; | 593 | chip_t chipset; |
593 | pid_t thr_pid; | ||
594 | wait_queue_head_t thr_wait; | ||
595 | struct completion thr_exited; | ||
596 | u32 rx_config; | 594 | u32 rx_config; |
597 | struct rtl_extra_stats xstats; | 595 | struct rtl_extra_stats xstats; |
598 | int time_to_die; | 596 | |
597 | struct work_struct thread; | ||
598 | |||
599 | struct mii_if_info mii; | 599 | struct mii_if_info mii; |
600 | unsigned int regs_len; | 600 | unsigned int regs_len; |
601 | unsigned long fifo_copy_timeout; | 601 | unsigned long fifo_copy_timeout; |
@@ -620,7 +620,7 @@ static int rtl8139_open (struct net_device *dev); | |||
620 | static int mdio_read (struct net_device *dev, int phy_id, int location); | 620 | static int mdio_read (struct net_device *dev, int phy_id, int location); |
621 | static void mdio_write (struct net_device *dev, int phy_id, int location, | 621 | static void mdio_write (struct net_device *dev, int phy_id, int location, |
622 | int val); | 622 | int val); |
623 | static void rtl8139_start_thread(struct net_device *dev); | 623 | static void rtl8139_start_thread(struct rtl8139_private *tp); |
624 | static void rtl8139_tx_timeout (struct net_device *dev); | 624 | static void rtl8139_tx_timeout (struct net_device *dev); |
625 | static void rtl8139_init_ring (struct net_device *dev); | 625 | static void rtl8139_init_ring (struct net_device *dev); |
626 | static int rtl8139_start_xmit (struct sk_buff *skb, | 626 | static int rtl8139_start_xmit (struct sk_buff *skb, |
@@ -637,6 +637,7 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); | |||
637 | static void rtl8139_set_rx_mode (struct net_device *dev); | 637 | static void rtl8139_set_rx_mode (struct net_device *dev); |
638 | static void __set_rx_mode (struct net_device *dev); | 638 | static void __set_rx_mode (struct net_device *dev); |
639 | static void rtl8139_hw_start (struct net_device *dev); | 639 | static void rtl8139_hw_start (struct net_device *dev); |
640 | static void rtl8139_thread (void *_data); | ||
640 | static struct ethtool_ops rtl8139_ethtool_ops; | 641 | static struct ethtool_ops rtl8139_ethtool_ops; |
641 | 642 | ||
642 | /* write MMIO register, with flush */ | 643 | /* write MMIO register, with flush */ |
@@ -1007,8 +1008,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, | |||
1007 | (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); | 1008 | (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); |
1008 | spin_lock_init (&tp->lock); | 1009 | spin_lock_init (&tp->lock); |
1009 | spin_lock_init (&tp->rx_lock); | 1010 | spin_lock_init (&tp->rx_lock); |
1010 | init_waitqueue_head (&tp->thr_wait); | 1011 | INIT_WORK(&tp->thread, rtl8139_thread, dev); |
1011 | init_completion (&tp->thr_exited); | ||
1012 | tp->mii.dev = dev; | 1012 | tp->mii.dev = dev; |
1013 | tp->mii.mdio_read = mdio_read; | 1013 | tp->mii.mdio_read = mdio_read; |
1014 | tp->mii.mdio_write = mdio_write; | 1014 | tp->mii.mdio_write = mdio_write; |
@@ -1345,7 +1345,7 @@ static int rtl8139_open (struct net_device *dev) | |||
1345 | dev->irq, RTL_R8 (MediaStatus), | 1345 | dev->irq, RTL_R8 (MediaStatus), |
1346 | tp->mii.full_duplex ? "full" : "half"); | 1346 | tp->mii.full_duplex ? "full" : "half"); |
1347 | 1347 | ||
1348 | rtl8139_start_thread(dev); | 1348 | rtl8139_start_thread(tp); |
1349 | 1349 | ||
1350 | return 0; | 1350 | return 0; |
1351 | } | 1351 | } |
@@ -1594,55 +1594,43 @@ static inline void rtl8139_thread_iter (struct net_device *dev, | |||
1594 | RTL_R8 (Config1)); | 1594 | RTL_R8 (Config1)); |
1595 | } | 1595 | } |
1596 | 1596 | ||
1597 | static int rtl8139_thread (void *data) | 1597 | static void rtl8139_thread (void *_data) |
1598 | { | 1598 | { |
1599 | struct net_device *dev = data; | 1599 | struct net_device *dev = _data; |
1600 | struct rtl8139_private *tp = netdev_priv(dev); | 1600 | struct rtl8139_private *tp = netdev_priv(dev); |
1601 | unsigned long timeout; | 1601 | unsigned long thr_delay; |
1602 | |||
1603 | daemonize("%s", dev->name); | ||
1604 | allow_signal(SIGTERM); | ||
1605 | |||
1606 | while (1) { | ||
1607 | timeout = next_tick; | ||
1608 | do { | ||
1609 | timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout); | ||
1610 | /* make swsusp happy with our thread */ | ||
1611 | try_to_freeze(); | ||
1612 | } while (!signal_pending (current) && (timeout > 0)); | ||
1613 | |||
1614 | if (signal_pending (current)) { | ||
1615 | flush_signals(current); | ||
1616 | } | ||
1617 | 1602 | ||
1618 | if (tp->time_to_die) | 1603 | if (rtnl_shlock_nowait() == 0) { |
1619 | break; | ||
1620 | |||
1621 | if (rtnl_lock_interruptible ()) | ||
1622 | break; | ||
1623 | rtl8139_thread_iter (dev, tp, tp->mmio_addr); | 1604 | rtl8139_thread_iter (dev, tp, tp->mmio_addr); |
1624 | rtnl_unlock (); | 1605 | rtnl_unlock (); |
1606 | |||
1607 | thr_delay = next_tick; | ||
1608 | } else { | ||
1609 | /* unlikely race. mitigate with fast poll. */ | ||
1610 | thr_delay = HZ / 2; | ||
1625 | } | 1611 | } |
1626 | 1612 | ||
1627 | complete_and_exit (&tp->thr_exited, 0); | 1613 | schedule_delayed_work(&tp->thread, thr_delay); |
1628 | } | 1614 | } |
1629 | 1615 | ||
1630 | static void rtl8139_start_thread(struct net_device *dev) | 1616 | static void rtl8139_start_thread(struct rtl8139_private *tp) |
1631 | { | 1617 | { |
1632 | struct rtl8139_private *tp = netdev_priv(dev); | ||
1633 | |||
1634 | tp->thr_pid = -1; | ||
1635 | tp->twistie = 0; | 1618 | tp->twistie = 0; |
1636 | tp->time_to_die = 0; | ||
1637 | if (tp->chipset == CH_8139_K) | 1619 | if (tp->chipset == CH_8139_K) |
1638 | tp->twistie = 1; | 1620 | tp->twistie = 1; |
1639 | else if (tp->drv_flags & HAS_LNK_CHNG) | 1621 | else if (tp->drv_flags & HAS_LNK_CHNG) |
1640 | return; | 1622 | return; |
1641 | 1623 | ||
1642 | tp->thr_pid = kernel_thread(rtl8139_thread, dev, CLONE_FS|CLONE_FILES); | 1624 | tp->have_thread = 1; |
1643 | if (tp->thr_pid < 0) { | 1625 | |
1644 | printk (KERN_WARNING "%s: unable to start kernel thread\n", | 1626 | schedule_delayed_work(&tp->thread, next_tick); |
1645 | dev->name); | 1627 | } |
1628 | |||
1629 | static void rtl8139_stop_thread(struct rtl8139_private *tp) | ||
1630 | { | ||
1631 | if (tp->have_thread) { | ||
1632 | cancel_rearming_delayed_work(&tp->thread); | ||
1633 | tp->have_thread = 0; | ||
1646 | } | 1634 | } |
1647 | } | 1635 | } |
1648 | 1636 | ||
@@ -2224,22 +2212,12 @@ static int rtl8139_close (struct net_device *dev) | |||
2224 | { | 2212 | { |
2225 | struct rtl8139_private *tp = netdev_priv(dev); | 2213 | struct rtl8139_private *tp = netdev_priv(dev); |
2226 | void __iomem *ioaddr = tp->mmio_addr; | 2214 | void __iomem *ioaddr = tp->mmio_addr; |
2227 | int ret = 0; | ||
2228 | unsigned long flags; | 2215 | unsigned long flags; |
2229 | 2216 | ||
2230 | netif_stop_queue (dev); | 2217 | netif_stop_queue (dev); |
2231 | 2218 | ||
2232 | if (tp->thr_pid >= 0) { | 2219 | rtl8139_stop_thread(tp); |
2233 | tp->time_to_die = 1; | 2220 | |
2234 | wmb(); | ||
2235 | ret = kill_proc (tp->thr_pid, SIGTERM, 1); | ||
2236 | if (ret) { | ||
2237 | printk (KERN_ERR "%s: unable to signal thread\n", dev->name); | ||
2238 | return ret; | ||
2239 | } | ||
2240 | wait_for_completion (&tp->thr_exited); | ||
2241 | } | ||
2242 | |||
2243 | if (netif_msg_ifdown(tp)) | 2221 | if (netif_msg_ifdown(tp)) |
2244 | printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", | 2222 | printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", |
2245 | dev->name, RTL_R16 (IntrStatus)); | 2223 | dev->name, RTL_R16 (IntrStatus)); |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ebd7313d7fc1..39415b5c4569 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -2008,7 +2008,25 @@ config SKGE | |||
2008 | 2008 | ||
2009 | It does not support the link failover and network management | 2009 | It does not support the link failover and network management |
2010 | features that "portable" vendor supplied sk98lin driver does. | 2010 | features that "portable" vendor supplied sk98lin driver does. |
2011 | 2011 | ||
2012 | |||
2013 | config SKY2 | ||
2014 | tristate "SysKonnect Yukon2 support (EXPERIMENTAL)" | ||
2015 | depends on PCI && EXPERIMENTAL | ||
2016 | select CRC32 | ||
2017 | ---help--- | ||
2018 | This driver support the Marvell Yukon 2 Gigabit Ethernet adapter. | ||
2019 | |||
2020 | To compile this driver as a module, choose M here: the module | ||
2021 | will be called sky2. This is recommended. | ||
2022 | |||
2023 | config SKY2_EC_A1 | ||
2024 | bool "Support old Yukon-EC A1 chipset" | ||
2025 | depends on SKY2 | ||
2026 | ---help--- | ||
2027 | Include support for early revisions of the Yukon EC chipset | ||
2028 | that required extra workarounds. If in doubt, say N. | ||
2029 | |||
2012 | config SK98LIN | 2030 | config SK98LIN |
2013 | tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" | 2031 | tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" |
2014 | depends on PCI | 2032 | depends on PCI |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 4cffd34442aa..27822a2f0683 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
@@ -59,6 +59,7 @@ spidernet-y += spider_net.o spider_net_ethtool.o sungem_phy.o | |||
59 | obj-$(CONFIG_SPIDER_NET) += spidernet.o | 59 | obj-$(CONFIG_SPIDER_NET) += spidernet.o |
60 | obj-$(CONFIG_TC35815) += tc35815.o | 60 | obj-$(CONFIG_TC35815) += tc35815.o |
61 | obj-$(CONFIG_SKGE) += skge.o | 61 | obj-$(CONFIG_SKGE) += skge.o |
62 | obj-$(CONFIG_SKY2) += sky2.o | ||
62 | obj-$(CONFIG_SK98LIN) += sk98lin/ | 63 | obj-$(CONFIG_SK98LIN) += sk98lin/ |
63 | obj-$(CONFIG_SKFP) += skfp/ | 64 | obj-$(CONFIG_SKFP) += skfp/ |
64 | obj-$(CONFIG_VIA_RHINE) += via-rhine.o | 65 | obj-$(CONFIG_VIA_RHINE) += via-rhine.o |
diff --git a/drivers/net/bonding/Makefile b/drivers/net/bonding/Makefile index cf50384b469e..5cdae2bc055a 100644 --- a/drivers/net/bonding/Makefile +++ b/drivers/net/bonding/Makefile | |||
@@ -4,5 +4,5 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_BONDING) += bonding.o | 5 | obj-$(CONFIG_BONDING) += bonding.o |
6 | 6 | ||
7 | bonding-objs := bond_main.o bond_3ad.o bond_alb.o | 7 | bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o |
8 | 8 | ||
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index d2f34d5a8083..04705233ca0b 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c | |||
@@ -1198,10 +1198,10 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
1198 | // detect loopback situation | 1198 | // detect loopback situation |
1199 | if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) { | 1199 | if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) { |
1200 | // INFO_RECEIVED_LOOPBACK_FRAMES | 1200 | // INFO_RECEIVED_LOOPBACK_FRAMES |
1201 | printk(KERN_ERR DRV_NAME ": An illegal loopback occurred on adapter (%s)\n", | 1201 | printk(KERN_ERR DRV_NAME ": %s: An illegal loopback occurred on " |
1202 | port->slave->dev->name); | 1202 | "adapter (%s). Check the configuration to verify that all " |
1203 | printk(KERN_ERR "Check the configuration to verify that all Adapters " | 1203 | "Adapters are connected to 802.3ad compliant switch ports\n", |
1204 | "are connected to 802.3ad compliant switch ports\n"); | 1204 | port->slave->dev->master->name, port->slave->dev->name); |
1205 | __release_rx_machine_lock(port); | 1205 | __release_rx_machine_lock(port); |
1206 | return; | 1206 | return; |
1207 | } | 1207 | } |
@@ -1378,8 +1378,9 @@ static void ad_port_selection_logic(struct port *port) | |||
1378 | } | 1378 | } |
1379 | } | 1379 | } |
1380 | if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list | 1380 | if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list |
1381 | printk(KERN_WARNING DRV_NAME ": Warning: Port %d (on %s) was " | 1381 | printk(KERN_WARNING DRV_NAME ": %s: Warning: Port %d (on %s) was " |
1382 | "related to aggregator %d but was not on its port list\n", | 1382 | "related to aggregator %d but was not on its port list\n", |
1383 | port->slave->dev->master->name, | ||
1383 | port->actor_port_number, port->slave->dev->name, | 1384 | port->actor_port_number, port->slave->dev->name, |
1384 | port->aggregator->aggregator_identifier); | 1385 | port->aggregator->aggregator_identifier); |
1385 | } | 1386 | } |
@@ -1450,7 +1451,8 @@ static void ad_port_selection_logic(struct port *port) | |||
1450 | 1451 | ||
1451 | dprintk("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier); | 1452 | dprintk("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier); |
1452 | } else { | 1453 | } else { |
1453 | printk(KERN_ERR DRV_NAME ": Port %d (on %s) did not find a suitable aggregator\n", | 1454 | printk(KERN_ERR DRV_NAME ": %s: Port %d (on %s) did not find a suitable aggregator\n", |
1455 | port->slave->dev->master->name, | ||
1454 | port->actor_port_number, port->slave->dev->name); | 1456 | port->actor_port_number, port->slave->dev->name); |
1455 | } | 1457 | } |
1456 | } | 1458 | } |
@@ -1582,8 +1584,9 @@ static void ad_agg_selection_logic(struct aggregator *aggregator) | |||
1582 | 1584 | ||
1583 | // check if any partner replys | 1585 | // check if any partner replys |
1584 | if (best_aggregator->is_individual) { | 1586 | if (best_aggregator->is_individual) { |
1585 | printk(KERN_WARNING DRV_NAME ": Warning: No 802.3ad response from the link partner " | 1587 | printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad response from " |
1586 | "for any adapters in the bond\n"); | 1588 | "the link partner for any adapters in the bond\n", |
1589 | best_aggregator->slave->dev->master->name); | ||
1587 | } | 1590 | } |
1588 | 1591 | ||
1589 | // check if there are more than one aggregator | 1592 | // check if there are more than one aggregator |
@@ -1915,7 +1918,8 @@ int bond_3ad_bind_slave(struct slave *slave) | |||
1915 | struct aggregator *aggregator; | 1918 | struct aggregator *aggregator; |
1916 | 1919 | ||
1917 | if (bond == NULL) { | 1920 | if (bond == NULL) { |
1918 | printk(KERN_ERR "The slave %s is not attached to its bond\n", slave->dev->name); | 1921 | printk(KERN_ERR DRV_NAME ": %s: The slave %s is not attached to its bond\n", |
1922 | slave->dev->master->name, slave->dev->name); | ||
1919 | return -1; | 1923 | return -1; |
1920 | } | 1924 | } |
1921 | 1925 | ||
@@ -1990,7 +1994,9 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
1990 | 1994 | ||
1991 | // if slave is null, the whole port is not initialized | 1995 | // if slave is null, the whole port is not initialized |
1992 | if (!port->slave) { | 1996 | if (!port->slave) { |
1993 | printk(KERN_WARNING DRV_NAME ": Trying to unbind an uninitialized port on %s\n", slave->dev->name); | 1997 | printk(KERN_WARNING DRV_NAME ": Warning: %s: Trying to " |
1998 | "unbind an uninitialized port on %s\n", | ||
1999 | slave->dev->master->name, slave->dev->name); | ||
1994 | return; | 2000 | return; |
1995 | } | 2001 | } |
1996 | 2002 | ||
@@ -2021,7 +2027,8 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
2021 | dprintk("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier); | 2027 | dprintk("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier); |
2022 | 2028 | ||
2023 | if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) { | 2029 | if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) { |
2024 | printk(KERN_INFO DRV_NAME ": Removing an active aggregator\n"); | 2030 | printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n", |
2031 | aggregator->slave->dev->master->name); | ||
2025 | // select new active aggregator | 2032 | // select new active aggregator |
2026 | select_new_active_agg = 1; | 2033 | select_new_active_agg = 1; |
2027 | } | 2034 | } |
@@ -2051,15 +2058,17 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
2051 | ad_agg_selection_logic(__get_first_agg(port)); | 2058 | ad_agg_selection_logic(__get_first_agg(port)); |
2052 | } | 2059 | } |
2053 | } else { | 2060 | } else { |
2054 | printk(KERN_WARNING DRV_NAME ": Warning: unbinding aggregator, " | 2061 | printk(KERN_WARNING DRV_NAME ": %s: Warning: unbinding aggregator, " |
2055 | "and could not find a new aggregator for its ports\n"); | 2062 | "and could not find a new aggregator for its ports\n", |
2063 | slave->dev->master->name); | ||
2056 | } | 2064 | } |
2057 | } else { // in case that the only port related to this aggregator is the one we want to remove | 2065 | } else { // in case that the only port related to this aggregator is the one we want to remove |
2058 | select_new_active_agg = aggregator->is_active; | 2066 | select_new_active_agg = aggregator->is_active; |
2059 | // clear the aggregator | 2067 | // clear the aggregator |
2060 | ad_clear_agg(aggregator); | 2068 | ad_clear_agg(aggregator); |
2061 | if (select_new_active_agg) { | 2069 | if (select_new_active_agg) { |
2062 | printk(KERN_INFO "Removing an active aggregator\n"); | 2070 | printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n", |
2071 | slave->dev->master->name); | ||
2063 | // select new active aggregator | 2072 | // select new active aggregator |
2064 | ad_agg_selection_logic(__get_first_agg(port)); | 2073 | ad_agg_selection_logic(__get_first_agg(port)); |
2065 | } | 2074 | } |
@@ -2085,7 +2094,8 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
2085 | // clear the aggregator | 2094 | // clear the aggregator |
2086 | ad_clear_agg(temp_aggregator); | 2095 | ad_clear_agg(temp_aggregator); |
2087 | if (select_new_active_agg) { | 2096 | if (select_new_active_agg) { |
2088 | printk(KERN_INFO "Removing an active aggregator\n"); | 2097 | printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n", |
2098 | slave->dev->master->name); | ||
2089 | // select new active aggregator | 2099 | // select new active aggregator |
2090 | ad_agg_selection_logic(__get_first_agg(port)); | 2100 | ad_agg_selection_logic(__get_first_agg(port)); |
2091 | } | 2101 | } |
@@ -2131,7 +2141,8 @@ void bond_3ad_state_machine_handler(struct bonding *bond) | |||
2131 | // select the active aggregator for the bond | 2141 | // select the active aggregator for the bond |
2132 | if ((port = __get_first_port(bond))) { | 2142 | if ((port = __get_first_port(bond))) { |
2133 | if (!port->slave) { | 2143 | if (!port->slave) { |
2134 | printk(KERN_WARNING DRV_NAME ": Warning: bond's first port is uninitialized\n"); | 2144 | printk(KERN_WARNING DRV_NAME ": %s: Warning: bond's first port is " |
2145 | "uninitialized\n", bond->dev->name); | ||
2135 | goto re_arm; | 2146 | goto re_arm; |
2136 | } | 2147 | } |
2137 | 2148 | ||
@@ -2143,7 +2154,8 @@ void bond_3ad_state_machine_handler(struct bonding *bond) | |||
2143 | // for each port run the state machines | 2154 | // for each port run the state machines |
2144 | for (port = __get_first_port(bond); port; port = __get_next_port(port)) { | 2155 | for (port = __get_first_port(bond); port; port = __get_next_port(port)) { |
2145 | if (!port->slave) { | 2156 | if (!port->slave) { |
2146 | printk(KERN_WARNING DRV_NAME ": Warning: Found an uninitialized port\n"); | 2157 | printk(KERN_WARNING DRV_NAME ": %s: Warning: Found an uninitialized " |
2158 | "port\n", bond->dev->name); | ||
2147 | goto re_arm; | 2159 | goto re_arm; |
2148 | } | 2160 | } |
2149 | 2161 | ||
@@ -2184,7 +2196,8 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u | |||
2184 | port = &(SLAVE_AD_INFO(slave).port); | 2196 | port = &(SLAVE_AD_INFO(slave).port); |
2185 | 2197 | ||
2186 | if (!port->slave) { | 2198 | if (!port->slave) { |
2187 | printk(KERN_WARNING DRV_NAME ": Warning: port of slave %s is uninitialized\n", slave->dev->name); | 2199 | printk(KERN_WARNING DRV_NAME ": %s: Warning: port of slave %s is " |
2200 | "uninitialized\n", slave->dev->name, slave->dev->master->name); | ||
2188 | return; | 2201 | return; |
2189 | } | 2202 | } |
2190 | 2203 | ||
@@ -2230,8 +2243,9 @@ void bond_3ad_adapter_speed_changed(struct slave *slave) | |||
2230 | 2243 | ||
2231 | // if slave is null, the whole port is not initialized | 2244 | // if slave is null, the whole port is not initialized |
2232 | if (!port->slave) { | 2245 | if (!port->slave) { |
2233 | printk(KERN_WARNING DRV_NAME ": Warning: speed changed for uninitialized port on %s\n", | 2246 | printk(KERN_WARNING DRV_NAME ": Warning: %s: speed " |
2234 | slave->dev->name); | 2247 | "changed for uninitialized port on %s\n", |
2248 | slave->dev->master->name, slave->dev->name); | ||
2235 | return; | 2249 | return; |
2236 | } | 2250 | } |
2237 | 2251 | ||
@@ -2257,8 +2271,9 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) | |||
2257 | 2271 | ||
2258 | // if slave is null, the whole port is not initialized | 2272 | // if slave is null, the whole port is not initialized |
2259 | if (!port->slave) { | 2273 | if (!port->slave) { |
2260 | printk(KERN_WARNING DRV_NAME ": Warning: duplex changed for uninitialized port on %s\n", | 2274 | printk(KERN_WARNING DRV_NAME ": %s: Warning: duplex changed " |
2261 | slave->dev->name); | 2275 | "for uninitialized port on %s\n", |
2276 | slave->dev->master->name, slave->dev->name); | ||
2262 | return; | 2277 | return; |
2263 | } | 2278 | } |
2264 | 2279 | ||
@@ -2285,8 +2300,9 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) | |||
2285 | 2300 | ||
2286 | // if slave is null, the whole port is not initialized | 2301 | // if slave is null, the whole port is not initialized |
2287 | if (!port->slave) { | 2302 | if (!port->slave) { |
2288 | printk(KERN_WARNING DRV_NAME ": Warning: link status changed for uninitialized port on %s\n", | 2303 | printk(KERN_WARNING DRV_NAME ": Warning: %s: link status changed for " |
2289 | slave->dev->name); | 2304 | "uninitialized port on %s\n", |
2305 | slave->dev->master->name, slave->dev->name); | ||
2290 | return; | 2306 | return; |
2291 | } | 2307 | } |
2292 | 2308 | ||
@@ -2363,7 +2379,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) | |||
2363 | } | 2379 | } |
2364 | 2380 | ||
2365 | if (bond_3ad_get_active_agg_info(bond, &ad_info)) { | 2381 | if (bond_3ad_get_active_agg_info(bond, &ad_info)) { |
2366 | printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n"); | 2382 | printk(KERN_DEBUG DRV_NAME ": %s: Error: " |
2383 | "bond_3ad_get_active_agg_info failed\n", dev->name); | ||
2367 | goto out; | 2384 | goto out; |
2368 | } | 2385 | } |
2369 | 2386 | ||
@@ -2372,7 +2389,9 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) | |||
2372 | 2389 | ||
2373 | if (slaves_in_agg == 0) { | 2390 | if (slaves_in_agg == 0) { |
2374 | /*the aggregator is empty*/ | 2391 | /*the aggregator is empty*/ |
2375 | printk(KERN_DEBUG "ERROR: active aggregator is empty\n"); | 2392 | printk(KERN_DEBUG DRV_NAME ": %s: Error: active " |
2393 | "aggregator is empty\n", | ||
2394 | dev->name); | ||
2376 | goto out; | 2395 | goto out; |
2377 | } | 2396 | } |
2378 | 2397 | ||
@@ -2390,7 +2409,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) | |||
2390 | } | 2409 | } |
2391 | 2410 | ||
2392 | if (slave_agg_no >= 0) { | 2411 | if (slave_agg_no >= 0) { |
2393 | printk(KERN_ERR DRV_NAME ": Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id); | 2412 | printk(KERN_ERR DRV_NAME ": %s: Error: Couldn't find a slave to tx on " |
2413 | "for aggregator ID %d\n", dev->name, agg_id); | ||
2394 | goto out; | 2414 | goto out; |
2395 | } | 2415 | } |
2396 | 2416 | ||
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index f8fce3961197..9bd1e104554a 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c | |||
@@ -198,20 +198,21 @@ static int tlb_initialize(struct bonding *bond) | |||
198 | { | 198 | { |
199 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); | 199 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); |
200 | int size = TLB_HASH_TABLE_SIZE * sizeof(struct tlb_client_info); | 200 | int size = TLB_HASH_TABLE_SIZE * sizeof(struct tlb_client_info); |
201 | struct tlb_client_info *new_hashtbl; | ||
201 | int i; | 202 | int i; |
202 | 203 | ||
203 | spin_lock_init(&(bond_info->tx_hashtbl_lock)); | 204 | spin_lock_init(&(bond_info->tx_hashtbl_lock)); |
204 | 205 | ||
205 | _lock_tx_hashtbl(bond); | 206 | new_hashtbl = kmalloc(size, GFP_KERNEL); |
206 | 207 | if (!new_hashtbl) { | |
207 | bond_info->tx_hashtbl = kmalloc(size, GFP_KERNEL); | ||
208 | if (!bond_info->tx_hashtbl) { | ||
209 | printk(KERN_ERR DRV_NAME | 208 | printk(KERN_ERR DRV_NAME |
210 | ": Error: %s: Failed to allocate TLB hash table\n", | 209 | ": %s: Error: Failed to allocate TLB hash table\n", |
211 | bond->dev->name); | 210 | bond->dev->name); |
212 | _unlock_tx_hashtbl(bond); | ||
213 | return -1; | 211 | return -1; |
214 | } | 212 | } |
213 | _lock_tx_hashtbl(bond); | ||
214 | |||
215 | bond_info->tx_hashtbl = new_hashtbl; | ||
215 | 216 | ||
216 | memset(bond_info->tx_hashtbl, 0, size); | 217 | memset(bond_info->tx_hashtbl, 0, size); |
217 | 218 | ||
@@ -513,7 +514,8 @@ static void rlb_update_client(struct rlb_client_info *client_info) | |||
513 | client_info->mac_dst); | 514 | client_info->mac_dst); |
514 | if (!skb) { | 515 | if (!skb) { |
515 | printk(KERN_ERR DRV_NAME | 516 | printk(KERN_ERR DRV_NAME |
516 | ": Error: failed to create an ARP packet\n"); | 517 | ": %s: Error: failed to create an ARP packet\n", |
518 | client_info->slave->dev->master->name); | ||
517 | continue; | 519 | continue; |
518 | } | 520 | } |
519 | 521 | ||
@@ -523,7 +525,8 @@ static void rlb_update_client(struct rlb_client_info *client_info) | |||
523 | skb = vlan_put_tag(skb, client_info->vlan_id); | 525 | skb = vlan_put_tag(skb, client_info->vlan_id); |
524 | if (!skb) { | 526 | if (!skb) { |
525 | printk(KERN_ERR DRV_NAME | 527 | printk(KERN_ERR DRV_NAME |
526 | ": Error: failed to insert VLAN tag\n"); | 528 | ": %s: Error: failed to insert VLAN tag\n", |
529 | client_info->slave->dev->master->name); | ||
527 | continue; | 530 | continue; |
528 | } | 531 | } |
529 | } | 532 | } |
@@ -606,8 +609,9 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, u32 src_ip) | |||
606 | 609 | ||
607 | if (!client_info->slave) { | 610 | if (!client_info->slave) { |
608 | printk(KERN_ERR DRV_NAME | 611 | printk(KERN_ERR DRV_NAME |
609 | ": Error: found a client with no channel in " | 612 | ": %s: Error: found a client with no channel in " |
610 | "the client's hash table\n"); | 613 | "the client's hash table\n", |
614 | bond->dev->name); | ||
611 | continue; | 615 | continue; |
612 | } | 616 | } |
613 | /*update all clients using this src_ip, that are not assigned | 617 | /*update all clients using this src_ip, that are not assigned |
@@ -797,21 +801,22 @@ static int rlb_initialize(struct bonding *bond) | |||
797 | { | 801 | { |
798 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); | 802 | struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); |
799 | struct packet_type *pk_type = &(BOND_ALB_INFO(bond).rlb_pkt_type); | 803 | struct packet_type *pk_type = &(BOND_ALB_INFO(bond).rlb_pkt_type); |
804 | struct rlb_client_info *new_hashtbl; | ||
800 | int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info); | 805 | int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info); |
801 | int i; | 806 | int i; |
802 | 807 | ||
803 | spin_lock_init(&(bond_info->rx_hashtbl_lock)); | 808 | spin_lock_init(&(bond_info->rx_hashtbl_lock)); |
804 | 809 | ||
805 | _lock_rx_hashtbl(bond); | 810 | new_hashtbl = kmalloc(size, GFP_KERNEL); |
806 | 811 | if (!new_hashtbl) { | |
807 | bond_info->rx_hashtbl = kmalloc(size, GFP_KERNEL); | ||
808 | if (!bond_info->rx_hashtbl) { | ||
809 | printk(KERN_ERR DRV_NAME | 812 | printk(KERN_ERR DRV_NAME |
810 | ": Error: %s: Failed to allocate RLB hash table\n", | 813 | ": %s: Error: Failed to allocate RLB hash table\n", |
811 | bond->dev->name); | 814 | bond->dev->name); |
812 | _unlock_rx_hashtbl(bond); | ||
813 | return -1; | 815 | return -1; |
814 | } | 816 | } |
817 | _lock_rx_hashtbl(bond); | ||
818 | |||
819 | bond_info->rx_hashtbl = new_hashtbl; | ||
815 | 820 | ||
816 | bond_info->rx_hashtbl_head = RLB_NULL_INDEX; | 821 | bond_info->rx_hashtbl_head = RLB_NULL_INDEX; |
817 | 822 | ||
@@ -927,7 +932,8 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]) | |||
927 | skb = vlan_put_tag(skb, vlan->vlan_id); | 932 | skb = vlan_put_tag(skb, vlan->vlan_id); |
928 | if (!skb) { | 933 | if (!skb) { |
929 | printk(KERN_ERR DRV_NAME | 934 | printk(KERN_ERR DRV_NAME |
930 | ": Error: failed to insert VLAN tag\n"); | 935 | ": %s: Error: failed to insert VLAN tag\n", |
936 | bond->dev->name); | ||
931 | continue; | 937 | continue; |
932 | } | 938 | } |
933 | } | 939 | } |
@@ -956,11 +962,11 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw) | |||
956 | s_addr.sa_family = dev->type; | 962 | s_addr.sa_family = dev->type; |
957 | if (dev_set_mac_address(dev, &s_addr)) { | 963 | if (dev_set_mac_address(dev, &s_addr)) { |
958 | printk(KERN_ERR DRV_NAME | 964 | printk(KERN_ERR DRV_NAME |
959 | ": Error: dev_set_mac_address of dev %s failed! ALB " | 965 | ": %s: Error: dev_set_mac_address of dev %s failed! ALB " |
960 | "mode requires that the base driver support setting " | 966 | "mode requires that the base driver support setting " |
961 | "the hw address also when the network device's " | 967 | "the hw address also when the network device's " |
962 | "interface is open\n", | 968 | "interface is open\n", |
963 | dev->name); | 969 | dev->master->name, dev->name); |
964 | return -EOPNOTSUPP; | 970 | return -EOPNOTSUPP; |
965 | } | 971 | } |
966 | return 0; | 972 | return 0; |
@@ -1153,16 +1159,16 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav | |||
1153 | bond->alb_info.rlb_enabled); | 1159 | bond->alb_info.rlb_enabled); |
1154 | 1160 | ||
1155 | printk(KERN_WARNING DRV_NAME | 1161 | printk(KERN_WARNING DRV_NAME |
1156 | ": Warning: the hw address of slave %s is in use by " | 1162 | ": %s: Warning: the hw address of slave %s is in use by " |
1157 | "the bond; giving it the hw address of %s\n", | 1163 | "the bond; giving it the hw address of %s\n", |
1158 | slave->dev->name, free_mac_slave->dev->name); | 1164 | bond->dev->name, slave->dev->name, free_mac_slave->dev->name); |
1159 | 1165 | ||
1160 | } else if (has_bond_addr) { | 1166 | } else if (has_bond_addr) { |
1161 | printk(KERN_ERR DRV_NAME | 1167 | printk(KERN_ERR DRV_NAME |
1162 | ": Error: the hw address of slave %s is in use by the " | 1168 | ": %s: Error: the hw address of slave %s is in use by the " |
1163 | "bond; couldn't find a slave with a free hw address to " | 1169 | "bond; couldn't find a slave with a free hw address to " |
1164 | "give it (this should not have happened)\n", | 1170 | "give it (this should not have happened)\n", |
1165 | slave->dev->name); | 1171 | bond->dev->name, slave->dev->name); |
1166 | return -EFAULT; | 1172 | return -EFAULT; |
1167 | } | 1173 | } |
1168 | 1174 | ||
@@ -1250,6 +1256,8 @@ int bond_alb_initialize(struct bonding *bond, int rlb_enabled) | |||
1250 | tlb_deinitialize(bond); | 1256 | tlb_deinitialize(bond); |
1251 | return res; | 1257 | return res; |
1252 | } | 1258 | } |
1259 | } else { | ||
1260 | bond->alb_info.rlb_enabled = 0; | ||
1253 | } | 1261 | } |
1254 | 1262 | ||
1255 | return 0; | 1263 | return 0; |
@@ -1409,7 +1417,7 @@ void bond_alb_monitor(struct bonding *bond) | |||
1409 | read_lock(&bond->curr_slave_lock); | 1417 | read_lock(&bond->curr_slave_lock); |
1410 | 1418 | ||
1411 | bond_for_each_slave(bond, slave, i) { | 1419 | bond_for_each_slave(bond, slave, i) { |
1412 | alb_send_learning_packets(slave,slave->dev->dev_addr); | 1420 | alb_send_learning_packets(slave, slave->dev->dev_addr); |
1413 | } | 1421 | } |
1414 | 1422 | ||
1415 | read_unlock(&bond->curr_slave_lock); | 1423 | read_unlock(&bond->curr_slave_lock); |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 94cec3cf2a13..40ff79175c4a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -489,6 +489,28 @@ | |||
489 | * Set version to 2.6.3. | 489 | * Set version to 2.6.3. |
490 | * 2005/09/26 - Jay Vosburgh <fubar@us.ibm.com> | 490 | * 2005/09/26 - Jay Vosburgh <fubar@us.ibm.com> |
491 | * - Removed backwards compatibility for old ifenslaves. Version 2.6.4. | 491 | * - Removed backwards compatibility for old ifenslaves. Version 2.6.4. |
492 | * 2005/09/27 - Mitch Williams <mitch.a.williams at intel dot com> | ||
493 | * - Radheka Godse <radheka.godse at intel dot com> | ||
494 | * - Split out bond creation code to allow for sysfs interface. | ||
495 | * - Removed static declaration on some functions and data items. | ||
496 | * - Added sysfs support, including capability to add/remove/change | ||
497 | * any bond at runtime. | ||
498 | * | ||
499 | * - Miscellaneous: | ||
500 | * - Added bonding: <bondname>: prefix to sysfs log messages | ||
501 | * - Added arp_ip_targets to /proc entry | ||
502 | * - Allow ARP target table to have empty entries | ||
503 | * - trivial fix: added missing modes description to modinfo | ||
504 | * - Corrected bug in ALB init where kmalloc is called inside | ||
505 | * a held lock | ||
506 | * - Corrected behavior to maintain bond link when changing | ||
507 | * from arp monitor to miimon and vice versa | ||
508 | * - Added missing bonding: <bondname>: prefix to alb, ad log messages | ||
509 | * - Fixed stack dump warnings seen if changing between miimon | ||
510 | * and arp monitoring when the bond interface is down. | ||
511 | * - Fixed stack dump warnings seen when enslaving an e100 | ||
512 | * driver | ||
513 | * - Set version to 3.0.0 | ||
492 | */ | 514 | */ |
493 | 515 | ||
494 | //#define BONDING_DEBUG 1 | 516 | //#define BONDING_DEBUG 1 |
@@ -557,6 +579,7 @@ static char *lacp_rate = NULL; | |||
557 | static char *xmit_hash_policy = NULL; | 579 | static char *xmit_hash_policy = NULL; |
558 | static int arp_interval = BOND_LINK_ARP_INTERV; | 580 | static int arp_interval = BOND_LINK_ARP_INTERV; |
559 | static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; | 581 | static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; |
582 | struct bond_params bonding_defaults; | ||
560 | 583 | ||
561 | module_param(max_bonds, int, 0); | 584 | module_param(max_bonds, int, 0); |
562 | MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); | 585 | MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); |
@@ -565,17 +588,24 @@ MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); | |||
565 | module_param(updelay, int, 0); | 588 | module_param(updelay, int, 0); |
566 | MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds"); | 589 | MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds"); |
567 | module_param(downdelay, int, 0); | 590 | module_param(downdelay, int, 0); |
568 | MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds"); | 591 | MODULE_PARM_DESC(downdelay, "Delay before considering link down, " |
592 | "in milliseconds"); | ||
569 | module_param(use_carrier, int, 0); | 593 | module_param(use_carrier, int, 0); |
570 | MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 0 for off, 1 for on (default)"); | 594 | MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; " |
595 | "0 for off, 1 for on (default)"); | ||
571 | module_param(mode, charp, 0); | 596 | module_param(mode, charp, 0); |
572 | MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor"); | 597 | MODULE_PARM_DESC(mode, "Mode of operation : 0 for balance-rr, " |
598 | "1 for active-backup, 2 for balance-xor, " | ||
599 | "3 for broadcast, 4 for 802.3ad, 5 for balance-tlb, " | ||
600 | "6 for balance-alb"); | ||
573 | module_param(primary, charp, 0); | 601 | module_param(primary, charp, 0); |
574 | MODULE_PARM_DESC(primary, "Primary network device to use"); | 602 | MODULE_PARM_DESC(primary, "Primary network device to use"); |
575 | module_param(lacp_rate, charp, 0); | 603 | module_param(lacp_rate, charp, 0); |
576 | MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)"); | 604 | MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner " |
605 | "(slow/fast)"); | ||
577 | module_param(xmit_hash_policy, charp, 0); | 606 | module_param(xmit_hash_policy, charp, 0); |
578 | MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method : 0 for layer 2 (default), 1 for layer 3+4"); | 607 | MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)" |
608 | ", 1 for layer 3+4"); | ||
579 | module_param(arp_interval, int, 0); | 609 | module_param(arp_interval, int, 0); |
580 | MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); | 610 | MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); |
581 | module_param_array(arp_ip_target, charp, NULL, 0); | 611 | module_param_array(arp_ip_target, charp, NULL, 0); |
@@ -586,30 +616,27 @@ MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); | |||
586 | static const char *version = | 616 | static const char *version = |
587 | DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"; | 617 | DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"; |
588 | 618 | ||
589 | static LIST_HEAD(bond_dev_list); | 619 | LIST_HEAD(bond_dev_list); |
590 | 620 | ||
591 | #ifdef CONFIG_PROC_FS | 621 | #ifdef CONFIG_PROC_FS |
592 | static struct proc_dir_entry *bond_proc_dir = NULL; | 622 | static struct proc_dir_entry *bond_proc_dir = NULL; |
593 | #endif | 623 | #endif |
594 | 624 | ||
625 | extern struct rw_semaphore bonding_rwsem; | ||
595 | static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ; | 626 | static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ; |
596 | static int arp_ip_count = 0; | 627 | static int arp_ip_count = 0; |
597 | static int bond_mode = BOND_MODE_ROUNDROBIN; | 628 | static int bond_mode = BOND_MODE_ROUNDROBIN; |
598 | static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2; | 629 | static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2; |
599 | static int lacp_fast = 0; | 630 | static int lacp_fast = 0; |
600 | 631 | ||
601 | struct bond_parm_tbl { | ||
602 | char *modename; | ||
603 | int mode; | ||
604 | }; | ||
605 | 632 | ||
606 | static struct bond_parm_tbl bond_lacp_tbl[] = { | 633 | struct bond_parm_tbl bond_lacp_tbl[] = { |
607 | { "slow", AD_LACP_SLOW}, | 634 | { "slow", AD_LACP_SLOW}, |
608 | { "fast", AD_LACP_FAST}, | 635 | { "fast", AD_LACP_FAST}, |
609 | { NULL, -1}, | 636 | { NULL, -1}, |
610 | }; | 637 | }; |
611 | 638 | ||
612 | static struct bond_parm_tbl bond_mode_tbl[] = { | 639 | struct bond_parm_tbl bond_mode_tbl[] = { |
613 | { "balance-rr", BOND_MODE_ROUNDROBIN}, | 640 | { "balance-rr", BOND_MODE_ROUNDROBIN}, |
614 | { "active-backup", BOND_MODE_ACTIVEBACKUP}, | 641 | { "active-backup", BOND_MODE_ACTIVEBACKUP}, |
615 | { "balance-xor", BOND_MODE_XOR}, | 642 | { "balance-xor", BOND_MODE_XOR}, |
@@ -620,7 +647,7 @@ static struct bond_parm_tbl bond_mode_tbl[] = { | |||
620 | { NULL, -1}, | 647 | { NULL, -1}, |
621 | }; | 648 | }; |
622 | 649 | ||
623 | static struct bond_parm_tbl xmit_hashtype_tbl[] = { | 650 | struct bond_parm_tbl xmit_hashtype_tbl[] = { |
624 | { "layer2", BOND_XMIT_POLICY_LAYER2}, | 651 | { "layer2", BOND_XMIT_POLICY_LAYER2}, |
625 | { "layer3+4", BOND_XMIT_POLICY_LAYER34}, | 652 | { "layer3+4", BOND_XMIT_POLICY_LAYER34}, |
626 | { NULL, -1}, | 653 | { NULL, -1}, |
@@ -628,12 +655,11 @@ static struct bond_parm_tbl xmit_hashtype_tbl[] = { | |||
628 | 655 | ||
629 | /*-------------------------- Forward declarations ---------------------------*/ | 656 | /*-------------------------- Forward declarations ---------------------------*/ |
630 | 657 | ||
631 | static inline void bond_set_mode_ops(struct bonding *bond, int mode); | ||
632 | static void bond_send_gratuitous_arp(struct bonding *bond); | 658 | static void bond_send_gratuitous_arp(struct bonding *bond); |
633 | 659 | ||
634 | /*---------------------------- General routines -----------------------------*/ | 660 | /*---------------------------- General routines -----------------------------*/ |
635 | 661 | ||
636 | static const char *bond_mode_name(int mode) | 662 | const char *bond_mode_name(int mode) |
637 | { | 663 | { |
638 | switch (mode) { | 664 | switch (mode) { |
639 | case BOND_MODE_ROUNDROBIN : | 665 | case BOND_MODE_ROUNDROBIN : |
@@ -910,7 +936,7 @@ static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) | |||
910 | res = bond_add_vlan(bond, vid); | 936 | res = bond_add_vlan(bond, vid); |
911 | if (res) { | 937 | if (res) { |
912 | printk(KERN_ERR DRV_NAME | 938 | printk(KERN_ERR DRV_NAME |
913 | ": %s: Failed to add vlan id %d\n", | 939 | ": %s: Error: Failed to add vlan id %d\n", |
914 | bond_dev->name, vid); | 940 | bond_dev->name, vid); |
915 | } | 941 | } |
916 | } | 942 | } |
@@ -944,7 +970,7 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) | |||
944 | res = bond_del_vlan(bond, vid); | 970 | res = bond_del_vlan(bond, vid); |
945 | if (res) { | 971 | if (res) { |
946 | printk(KERN_ERR DRV_NAME | 972 | printk(KERN_ERR DRV_NAME |
947 | ": %s: Failed to remove vlan id %d\n", | 973 | ": %s: Error: Failed to remove vlan id %d\n", |
948 | bond_dev->name, vid); | 974 | bond_dev->name, vid); |
949 | } | 975 | } |
950 | } | 976 | } |
@@ -1449,7 +1475,7 @@ static struct slave *bond_find_best_slave(struct bonding *bond) | |||
1449 | * | 1475 | * |
1450 | * Warning: Caller must hold curr_slave_lock for writing. | 1476 | * Warning: Caller must hold curr_slave_lock for writing. |
1451 | */ | 1477 | */ |
1452 | static void bond_change_active_slave(struct bonding *bond, struct slave *new_active) | 1478 | void bond_change_active_slave(struct bonding *bond, struct slave *new_active) |
1453 | { | 1479 | { |
1454 | struct slave *old_active = bond->curr_active_slave; | 1480 | struct slave *old_active = bond->curr_active_slave; |
1455 | 1481 | ||
@@ -1523,7 +1549,7 @@ static void bond_change_active_slave(struct bonding *bond, struct slave *new_act | |||
1523 | * | 1549 | * |
1524 | * Warning: Caller must hold curr_slave_lock for writing. | 1550 | * Warning: Caller must hold curr_slave_lock for writing. |
1525 | */ | 1551 | */ |
1526 | static void bond_select_active_slave(struct bonding *bond) | 1552 | void bond_select_active_slave(struct bonding *bond) |
1527 | { | 1553 | { |
1528 | struct slave *best_slave; | 1554 | struct slave *best_slave; |
1529 | 1555 | ||
@@ -1591,7 +1617,7 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave) | |||
1591 | 1617 | ||
1592 | /*---------------------------------- IOCTL ----------------------------------*/ | 1618 | /*---------------------------------- IOCTL ----------------------------------*/ |
1593 | 1619 | ||
1594 | static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev) | 1620 | int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev) |
1595 | { | 1621 | { |
1596 | dprintk("bond_dev=%p\n", bond_dev); | 1622 | dprintk("bond_dev=%p\n", bond_dev); |
1597 | dprintk("slave_dev=%p\n", slave_dev); | 1623 | dprintk("slave_dev=%p\n", slave_dev); |
@@ -1631,7 +1657,7 @@ static int bond_compute_features(struct bonding *bond) | |||
1631 | } | 1657 | } |
1632 | 1658 | ||
1633 | /* enslave device <slave> to bond device <master> */ | 1659 | /* enslave device <slave> to bond device <master> */ |
1634 | static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | 1660 | int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) |
1635 | { | 1661 | { |
1636 | struct bonding *bond = bond_dev->priv; | 1662 | struct bonding *bond = bond_dev->priv; |
1637 | struct slave *new_slave = NULL; | 1663 | struct slave *new_slave = NULL; |
@@ -1644,8 +1670,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de | |||
1644 | if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL && | 1670 | if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL && |
1645 | slave_dev->do_ioctl == NULL) { | 1671 | slave_dev->do_ioctl == NULL) { |
1646 | printk(KERN_WARNING DRV_NAME | 1672 | printk(KERN_WARNING DRV_NAME |
1647 | ": Warning : no link monitoring support for %s\n", | 1673 | ": %s: Warning: no link monitoring support for %s\n", |
1648 | slave_dev->name); | 1674 | bond_dev->name, slave_dev->name); |
1649 | } | 1675 | } |
1650 | 1676 | ||
1651 | /* bond must be initialized by bond_open() before enslaving */ | 1677 | /* bond must be initialized by bond_open() before enslaving */ |
@@ -1666,17 +1692,17 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de | |||
1666 | dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); | 1692 | dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); |
1667 | if (!list_empty(&bond->vlan_list)) { | 1693 | if (!list_empty(&bond->vlan_list)) { |
1668 | printk(KERN_ERR DRV_NAME | 1694 | printk(KERN_ERR DRV_NAME |
1669 | ": Error: cannot enslave VLAN " | 1695 | ": %s: Error: cannot enslave VLAN " |
1670 | "challenged slave %s on VLAN enabled " | 1696 | "challenged slave %s on VLAN enabled " |
1671 | "bond %s\n", slave_dev->name, | 1697 | "bond %s\n", bond_dev->name, slave_dev->name, |
1672 | bond_dev->name); | 1698 | bond_dev->name); |
1673 | return -EPERM; | 1699 | return -EPERM; |
1674 | } else { | 1700 | } else { |
1675 | printk(KERN_WARNING DRV_NAME | 1701 | printk(KERN_WARNING DRV_NAME |
1676 | ": Warning: enslaved VLAN challenged " | 1702 | ": %s: Warning: enslaved VLAN challenged " |
1677 | "slave %s. Adding VLANs will be blocked as " | 1703 | "slave %s. Adding VLANs will be blocked as " |
1678 | "long as %s is part of bond %s\n", | 1704 | "long as %s is part of bond %s\n", |
1679 | slave_dev->name, slave_dev->name, | 1705 | bond_dev->name, slave_dev->name, slave_dev->name, |
1680 | bond_dev->name); | 1706 | bond_dev->name); |
1681 | bond_dev->features |= NETIF_F_VLAN_CHALLENGED; | 1707 | bond_dev->features |= NETIF_F_VLAN_CHALLENGED; |
1682 | } | 1708 | } |
@@ -1706,12 +1732,11 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de | |||
1706 | 1732 | ||
1707 | if (slave_dev->set_mac_address == NULL) { | 1733 | if (slave_dev->set_mac_address == NULL) { |
1708 | printk(KERN_ERR DRV_NAME | 1734 | printk(KERN_ERR DRV_NAME |
1709 | ": Error: The slave device you specified does " | 1735 | ": %s: Error: The slave device you specified does " |
1710 | "not support setting the MAC address.\n"); | 1736 | "not support setting the MAC address. " |
1711 | printk(KERN_ERR | 1737 | "Your kernel likely does not support slave " |
1712 | "Your kernel likely does not support slave devices.\n"); | 1738 | "devices.\n", bond_dev->name); |
1713 | 1739 | res = -EOPNOTSUPP; | |
1714 | res = -EOPNOTSUPP; | ||
1715 | goto err_undo_flags; | 1740 | goto err_undo_flags; |
1716 | } | 1741 | } |
1717 | 1742 | ||
@@ -1827,21 +1852,21 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de | |||
1827 | * the messages for netif_carrier. | 1852 | * the messages for netif_carrier. |
1828 | */ | 1853 | */ |
1829 | printk(KERN_WARNING DRV_NAME | 1854 | printk(KERN_WARNING DRV_NAME |
1830 | ": Warning: MII and ETHTOOL support not " | 1855 | ": %s: Warning: MII and ETHTOOL support not " |
1831 | "available for interface %s, and " | 1856 | "available for interface %s, and " |
1832 | "arp_interval/arp_ip_target module parameters " | 1857 | "arp_interval/arp_ip_target module parameters " |
1833 | "not specified, thus bonding will not detect " | 1858 | "not specified, thus bonding will not detect " |
1834 | "link failures! see bonding.txt for details.\n", | 1859 | "link failures! see bonding.txt for details.\n", |
1835 | slave_dev->name); | 1860 | bond_dev->name, slave_dev->name); |
1836 | } else if (link_reporting == -1) { | 1861 | } else if (link_reporting == -1) { |
1837 | /* unable get link status using mii/ethtool */ | 1862 | /* unable get link status using mii/ethtool */ |
1838 | printk(KERN_WARNING DRV_NAME | 1863 | printk(KERN_WARNING DRV_NAME |
1839 | ": Warning: can't get link status from " | 1864 | ": %s: Warning: can't get link status from " |
1840 | "interface %s; the network driver associated " | 1865 | "interface %s; the network driver associated " |
1841 | "with this interface does not support MII or " | 1866 | "with this interface does not support MII or " |
1842 | "ETHTOOL link status reporting, thus miimon " | 1867 | "ETHTOOL link status reporting, thus miimon " |
1843 | "has no effect on this interface.\n", | 1868 | "has no effect on this interface.\n", |
1844 | slave_dev->name); | 1869 | bond_dev->name, slave_dev->name); |
1845 | } | 1870 | } |
1846 | } | 1871 | } |
1847 | 1872 | ||
@@ -1868,15 +1893,15 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de | |||
1868 | if (bond_update_speed_duplex(new_slave) && | 1893 | if (bond_update_speed_duplex(new_slave) && |
1869 | (new_slave->link != BOND_LINK_DOWN)) { | 1894 | (new_slave->link != BOND_LINK_DOWN)) { |
1870 | printk(KERN_WARNING DRV_NAME | 1895 | printk(KERN_WARNING DRV_NAME |
1871 | ": Warning: failed to get speed and duplex from %s, " | 1896 | ": %s: Warning: failed to get speed and duplex from %s, " |
1872 | "assumed to be 100Mb/sec and Full.\n", | 1897 | "assumed to be 100Mb/sec and Full.\n", |
1873 | new_slave->dev->name); | 1898 | bond_dev->name, new_slave->dev->name); |
1874 | 1899 | ||
1875 | if (bond->params.mode == BOND_MODE_8023AD) { | 1900 | if (bond->params.mode == BOND_MODE_8023AD) { |
1876 | printk(KERN_WARNING | 1901 | printk(KERN_WARNING DRV_NAME |
1877 | "Operation of 802.3ad mode requires ETHTOOL " | 1902 | ": %s: Warning: Operation of 802.3ad mode requires ETHTOOL " |
1878 | "support in base driver for proper aggregator " | 1903 | "support in base driver for proper aggregator " |
1879 | "selection.\n"); | 1904 | "selection.\n", bond_dev->name); |
1880 | } | 1905 | } |
1881 | } | 1906 | } |
1882 | 1907 | ||
@@ -1958,6 +1983,10 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de | |||
1958 | 1983 | ||
1959 | write_unlock_bh(&bond->lock); | 1984 | write_unlock_bh(&bond->lock); |
1960 | 1985 | ||
1986 | res = bond_create_slave_symlinks(bond_dev, slave_dev); | ||
1987 | if (res) | ||
1988 | goto err_unset_master; | ||
1989 | |||
1961 | printk(KERN_INFO DRV_NAME | 1990 | printk(KERN_INFO DRV_NAME |
1962 | ": %s: enslaving %s as a%s interface with a%s link.\n", | 1991 | ": %s: enslaving %s as a%s interface with a%s link.\n", |
1963 | bond_dev->name, slave_dev->name, | 1992 | bond_dev->name, slave_dev->name, |
@@ -1999,7 +2028,7 @@ err_undo_flags: | |||
1999 | * for Bonded connections: | 2028 | * for Bonded connections: |
2000 | * The first up interface should be left on and all others downed. | 2029 | * The first up interface should be left on and all others downed. |
2001 | */ | 2030 | */ |
2002 | static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | 2031 | int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) |
2003 | { | 2032 | { |
2004 | struct bonding *bond = bond_dev->priv; | 2033 | struct bonding *bond = bond_dev->priv; |
2005 | struct slave *slave, *oldcurrent; | 2034 | struct slave *slave, *oldcurrent; |
@@ -2010,7 +2039,7 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de | |||
2010 | if (!(slave_dev->flags & IFF_SLAVE) || | 2039 | if (!(slave_dev->flags & IFF_SLAVE) || |
2011 | (slave_dev->master != bond_dev)) { | 2040 | (slave_dev->master != bond_dev)) { |
2012 | printk(KERN_ERR DRV_NAME | 2041 | printk(KERN_ERR DRV_NAME |
2013 | ": Error: %s: cannot release %s.\n", | 2042 | ": %s: Error: cannot release %s.\n", |
2014 | bond_dev->name, slave_dev->name); | 2043 | bond_dev->name, slave_dev->name); |
2015 | return -EINVAL; | 2044 | return -EINVAL; |
2016 | } | 2045 | } |
@@ -2031,11 +2060,12 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de | |||
2031 | ETH_ALEN); | 2060 | ETH_ALEN); |
2032 | if (!mac_addr_differ && (bond->slave_cnt > 1)) { | 2061 | if (!mac_addr_differ && (bond->slave_cnt > 1)) { |
2033 | printk(KERN_WARNING DRV_NAME | 2062 | printk(KERN_WARNING DRV_NAME |
2034 | ": Warning: the permanent HWaddr of %s " | 2063 | ": %s: Warning: the permanent HWaddr of %s " |
2035 | "- %02X:%02X:%02X:%02X:%02X:%02X - is " | 2064 | "- %02X:%02X:%02X:%02X:%02X:%02X - is " |
2036 | "still in use by %s. Set the HWaddr of " | 2065 | "still in use by %s. Set the HWaddr of " |
2037 | "%s to a different address to avoid " | 2066 | "%s to a different address to avoid " |
2038 | "conflicts.\n", | 2067 | "conflicts.\n", |
2068 | bond_dev->name, | ||
2039 | slave_dev->name, | 2069 | slave_dev->name, |
2040 | slave->perm_hwaddr[0], | 2070 | slave->perm_hwaddr[0], |
2041 | slave->perm_hwaddr[1], | 2071 | slave->perm_hwaddr[1], |
@@ -2111,24 +2141,28 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de | |||
2111 | bond_dev->features |= NETIF_F_VLAN_CHALLENGED; | 2141 | bond_dev->features |= NETIF_F_VLAN_CHALLENGED; |
2112 | } else { | 2142 | } else { |
2113 | printk(KERN_WARNING DRV_NAME | 2143 | printk(KERN_WARNING DRV_NAME |
2114 | ": Warning: clearing HW address of %s while it " | 2144 | ": %s: Warning: clearing HW address of %s while it " |
2115 | "still has VLANs.\n", | 2145 | "still has VLANs.\n", |
2116 | bond_dev->name); | 2146 | bond_dev->name, bond_dev->name); |
2117 | printk(KERN_WARNING DRV_NAME | 2147 | printk(KERN_WARNING DRV_NAME |
2118 | ": When re-adding slaves, make sure the bond's " | 2148 | ": %s: When re-adding slaves, make sure the bond's " |
2119 | "HW address matches its VLANs'.\n"); | 2149 | "HW address matches its VLANs'.\n", |
2150 | bond_dev->name); | ||
2120 | } | 2151 | } |
2121 | } else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) && | 2152 | } else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) && |
2122 | !bond_has_challenged_slaves(bond)) { | 2153 | !bond_has_challenged_slaves(bond)) { |
2123 | printk(KERN_INFO DRV_NAME | 2154 | printk(KERN_INFO DRV_NAME |
2124 | ": last VLAN challenged slave %s " | 2155 | ": %s: last VLAN challenged slave %s " |
2125 | "left bond %s. VLAN blocking is removed\n", | 2156 | "left bond %s. VLAN blocking is removed\n", |
2126 | slave_dev->name, bond_dev->name); | 2157 | bond_dev->name, slave_dev->name, bond_dev->name); |
2127 | bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED; | 2158 | bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED; |
2128 | } | 2159 | } |
2129 | 2160 | ||
2130 | write_unlock_bh(&bond->lock); | 2161 | write_unlock_bh(&bond->lock); |
2131 | 2162 | ||
2163 | /* must do this from outside any spinlocks */ | ||
2164 | bond_destroy_slave_symlinks(bond_dev, slave_dev); | ||
2165 | |||
2132 | bond_del_vlans_from_slave(bond, slave_dev); | 2166 | bond_del_vlans_from_slave(bond, slave_dev); |
2133 | 2167 | ||
2134 | /* If the mode USES_PRIMARY, then we should only remove its | 2168 | /* If the mode USES_PRIMARY, then we should only remove its |
@@ -2220,6 +2254,7 @@ static int bond_release_all(struct net_device *bond_dev) | |||
2220 | */ | 2254 | */ |
2221 | write_unlock_bh(&bond->lock); | 2255 | write_unlock_bh(&bond->lock); |
2222 | 2256 | ||
2257 | bond_destroy_slave_symlinks(bond_dev, slave_dev); | ||
2223 | bond_del_vlans_from_slave(bond, slave_dev); | 2258 | bond_del_vlans_from_slave(bond, slave_dev); |
2224 | 2259 | ||
2225 | /* If the mode USES_PRIMARY, then we should only remove its | 2260 | /* If the mode USES_PRIMARY, then we should only remove its |
@@ -2274,12 +2309,13 @@ static int bond_release_all(struct net_device *bond_dev) | |||
2274 | bond_dev->features |= NETIF_F_VLAN_CHALLENGED; | 2309 | bond_dev->features |= NETIF_F_VLAN_CHALLENGED; |
2275 | } else { | 2310 | } else { |
2276 | printk(KERN_WARNING DRV_NAME | 2311 | printk(KERN_WARNING DRV_NAME |
2277 | ": Warning: clearing HW address of %s while it " | 2312 | ": %s: Warning: clearing HW address of %s while it " |
2278 | "still has VLANs.\n", | 2313 | "still has VLANs.\n", |
2279 | bond_dev->name); | 2314 | bond_dev->name, bond_dev->name); |
2280 | printk(KERN_WARNING DRV_NAME | 2315 | printk(KERN_WARNING DRV_NAME |
2281 | ": When re-adding slaves, make sure the bond's " | 2316 | ": %s: When re-adding slaves, make sure the bond's " |
2282 | "HW address matches its VLANs'.\n"); | 2317 | "HW address matches its VLANs'.\n", |
2318 | bond_dev->name); | ||
2283 | } | 2319 | } |
2284 | 2320 | ||
2285 | printk(KERN_INFO DRV_NAME | 2321 | printk(KERN_INFO DRV_NAME |
@@ -2397,7 +2433,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in | |||
2397 | /*-------------------------------- Monitoring -------------------------------*/ | 2433 | /*-------------------------------- Monitoring -------------------------------*/ |
2398 | 2434 | ||
2399 | /* this function is called regularly to monitor each slave's link. */ | 2435 | /* this function is called regularly to monitor each slave's link. */ |
2400 | static void bond_mii_monitor(struct net_device *bond_dev) | 2436 | void bond_mii_monitor(struct net_device *bond_dev) |
2401 | { | 2437 | { |
2402 | struct bonding *bond = bond_dev->priv; | 2438 | struct bonding *bond = bond_dev->priv; |
2403 | struct slave *slave, *oldcurrent; | 2439 | struct slave *slave, *oldcurrent; |
@@ -2596,8 +2632,11 @@ static void bond_mii_monitor(struct net_device *bond_dev) | |||
2596 | break; | 2632 | break; |
2597 | default: | 2633 | default: |
2598 | /* Should not happen */ | 2634 | /* Should not happen */ |
2599 | printk(KERN_ERR "bonding: Error: %s Illegal value (link=%d)\n", | 2635 | printk(KERN_ERR DRV_NAME |
2600 | slave->dev->name, slave->link); | 2636 | ": %s: Error: %s Illegal value (link=%d)\n", |
2637 | bond_dev->name, | ||
2638 | slave->dev->name, | ||
2639 | slave->link); | ||
2601 | goto out; | 2640 | goto out; |
2602 | } /* end of switch (slave->link) */ | 2641 | } /* end of switch (slave->link) */ |
2603 | 2642 | ||
@@ -2721,7 +2760,9 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | |||
2721 | struct flowi fl; | 2760 | struct flowi fl; |
2722 | struct rtable *rt; | 2761 | struct rtable *rt; |
2723 | 2762 | ||
2724 | for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) { | 2763 | for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) { |
2764 | if (!targets[i]) | ||
2765 | continue; | ||
2725 | dprintk("basa: target %x\n", targets[i]); | 2766 | dprintk("basa: target %x\n", targets[i]); |
2726 | if (list_empty(&bond->vlan_list)) { | 2767 | if (list_empty(&bond->vlan_list)) { |
2727 | dprintk("basa: empty vlan: arp_send\n"); | 2768 | dprintk("basa: empty vlan: arp_send\n"); |
@@ -2825,7 +2866,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond) | |||
2825 | * arp is transmitted to generate traffic. see activebackup_arp_monitor for | 2866 | * arp is transmitted to generate traffic. see activebackup_arp_monitor for |
2826 | * arp monitoring in active backup mode. | 2867 | * arp monitoring in active backup mode. |
2827 | */ | 2868 | */ |
2828 | static void bond_loadbalance_arp_mon(struct net_device *bond_dev) | 2869 | void bond_loadbalance_arp_mon(struct net_device *bond_dev) |
2829 | { | 2870 | { |
2830 | struct bonding *bond = bond_dev->priv; | 2871 | struct bonding *bond = bond_dev->priv; |
2831 | struct slave *slave, *oldcurrent; | 2872 | struct slave *slave, *oldcurrent; |
@@ -2963,7 +3004,7 @@ out: | |||
2963 | * may have received. | 3004 | * may have received. |
2964 | * see loadbalance_arp_monitor for arp monitoring in load balancing mode | 3005 | * see loadbalance_arp_monitor for arp monitoring in load balancing mode |
2965 | */ | 3006 | */ |
2966 | static void bond_activebackup_arp_mon(struct net_device *bond_dev) | 3007 | void bond_activebackup_arp_mon(struct net_device *bond_dev) |
2967 | { | 3008 | { |
2968 | struct bonding *bond = bond_dev->priv; | 3009 | struct bonding *bond = bond_dev->priv; |
2969 | struct slave *slave; | 3010 | struct slave *slave; |
@@ -3249,6 +3290,8 @@ static void bond_info_show_master(struct seq_file *seq) | |||
3249 | { | 3290 | { |
3250 | struct bonding *bond = seq->private; | 3291 | struct bonding *bond = seq->private; |
3251 | struct slave *curr; | 3292 | struct slave *curr; |
3293 | int i; | ||
3294 | u32 target; | ||
3252 | 3295 | ||
3253 | read_lock(&bond->curr_slave_lock); | 3296 | read_lock(&bond->curr_slave_lock); |
3254 | curr = bond->curr_active_slave; | 3297 | curr = bond->curr_active_slave; |
@@ -3257,10 +3300,17 @@ static void bond_info_show_master(struct seq_file *seq) | |||
3257 | seq_printf(seq, "Bonding Mode: %s\n", | 3300 | seq_printf(seq, "Bonding Mode: %s\n", |
3258 | bond_mode_name(bond->params.mode)); | 3301 | bond_mode_name(bond->params.mode)); |
3259 | 3302 | ||
3303 | if (bond->params.mode == BOND_MODE_XOR || | ||
3304 | bond->params.mode == BOND_MODE_8023AD) { | ||
3305 | seq_printf(seq, "Transmit Hash Policy: %s (%d)\n", | ||
3306 | xmit_hashtype_tbl[bond->params.xmit_policy].modename, | ||
3307 | bond->params.xmit_policy); | ||
3308 | } | ||
3309 | |||
3260 | if (USES_PRIMARY(bond->params.mode)) { | 3310 | if (USES_PRIMARY(bond->params.mode)) { |
3261 | seq_printf(seq, "Primary Slave: %s\n", | 3311 | seq_printf(seq, "Primary Slave: %s\n", |
3262 | (bond->params.primary[0]) ? | 3312 | (bond->primary_slave) ? |
3263 | bond->params.primary : "None"); | 3313 | bond->primary_slave->dev->name : "None"); |
3264 | 3314 | ||
3265 | seq_printf(seq, "Currently Active Slave: %s\n", | 3315 | seq_printf(seq, "Currently Active Slave: %s\n", |
3266 | (curr) ? curr->dev->name : "None"); | 3316 | (curr) ? curr->dev->name : "None"); |
@@ -3273,6 +3323,27 @@ static void bond_info_show_master(struct seq_file *seq) | |||
3273 | seq_printf(seq, "Down Delay (ms): %d\n", | 3323 | seq_printf(seq, "Down Delay (ms): %d\n", |
3274 | bond->params.downdelay * bond->params.miimon); | 3324 | bond->params.downdelay * bond->params.miimon); |
3275 | 3325 | ||
3326 | |||
3327 | /* ARP information */ | ||
3328 | if(bond->params.arp_interval > 0) { | ||
3329 | int printed=0; | ||
3330 | seq_printf(seq, "ARP Polling Interval (ms): %d\n", | ||
3331 | bond->params.arp_interval); | ||
3332 | |||
3333 | seq_printf(seq, "ARP IP target/s (n.n.n.n form):"); | ||
3334 | |||
3335 | for(i = 0; (i < BOND_MAX_ARP_TARGETS) ;i++) { | ||
3336 | if (!bond->params.arp_targets[i]) | ||
3337 | continue; | ||
3338 | if (printed) | ||
3339 | seq_printf(seq, ","); | ||
3340 | target = ntohl(bond->params.arp_targets[i]); | ||
3341 | seq_printf(seq, " %d.%d.%d.%d", HIPQUAD(target)); | ||
3342 | printed = 1; | ||
3343 | } | ||
3344 | seq_printf(seq, "\n"); | ||
3345 | } | ||
3346 | |||
3276 | if (bond->params.mode == BOND_MODE_8023AD) { | 3347 | if (bond->params.mode == BOND_MODE_8023AD) { |
3277 | struct ad_info ad_info; | 3348 | struct ad_info ad_info; |
3278 | 3349 | ||
@@ -3478,7 +3549,10 @@ static int bond_event_changename(struct bonding *bond) | |||
3478 | bond_remove_proc_entry(bond); | 3549 | bond_remove_proc_entry(bond); |
3479 | bond_create_proc_entry(bond); | 3550 | bond_create_proc_entry(bond); |
3480 | #endif | 3551 | #endif |
3481 | 3552 | down_write(&(bonding_rwsem)); | |
3553 | bond_destroy_sysfs_entry(bond); | ||
3554 | bond_create_sysfs_entry(bond); | ||
3555 | up_write(&(bonding_rwsem)); | ||
3482 | return NOTIFY_DONE; | 3556 | return NOTIFY_DONE; |
3483 | } | 3557 | } |
3484 | 3558 | ||
@@ -3955,6 +4029,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd | |||
3955 | return -EPERM; | 4029 | return -EPERM; |
3956 | } | 4030 | } |
3957 | 4031 | ||
4032 | down_write(&(bonding_rwsem)); | ||
3958 | slave_dev = dev_get_by_name(ifr->ifr_slave); | 4033 | slave_dev = dev_get_by_name(ifr->ifr_slave); |
3959 | 4034 | ||
3960 | dprintk("slave_dev=%p: \n", slave_dev); | 4035 | dprintk("slave_dev=%p: \n", slave_dev); |
@@ -3987,6 +4062,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd | |||
3987 | dev_put(slave_dev); | 4062 | dev_put(slave_dev); |
3988 | } | 4063 | } |
3989 | 4064 | ||
4065 | up_write(&(bonding_rwsem)); | ||
3990 | return res; | 4066 | return res; |
3991 | } | 4067 | } |
3992 | 4068 | ||
@@ -4071,6 +4147,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu) | |||
4071 | bond_for_each_slave(bond, slave, i) { | 4147 | bond_for_each_slave(bond, slave, i) { |
4072 | dprintk("s %p s->p %p c_m %p\n", slave, | 4148 | dprintk("s %p s->p %p c_m %p\n", slave, |
4073 | slave->prev, slave->dev->change_mtu); | 4149 | slave->prev, slave->dev->change_mtu); |
4150 | |||
4074 | res = dev_set_mtu(slave->dev, new_mtu); | 4151 | res = dev_set_mtu(slave->dev, new_mtu); |
4075 | 4152 | ||
4076 | if (res) { | 4153 | if (res) { |
@@ -4397,8 +4474,9 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) | |||
4397 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | 4474 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); |
4398 | if (!skb2) { | 4475 | if (!skb2) { |
4399 | printk(KERN_ERR DRV_NAME | 4476 | printk(KERN_ERR DRV_NAME |
4400 | ": Error: bond_xmit_broadcast(): " | 4477 | ": %s: Error: bond_xmit_broadcast(): " |
4401 | "skb_clone() failed\n"); | 4478 | "skb_clone() failed\n", |
4479 | bond_dev->name); | ||
4402 | continue; | 4480 | continue; |
4403 | } | 4481 | } |
4404 | 4482 | ||
@@ -4431,7 +4509,7 @@ out: | |||
4431 | /* | 4509 | /* |
4432 | * set bond mode specific net device operations | 4510 | * set bond mode specific net device operations |
4433 | */ | 4511 | */ |
4434 | static inline void bond_set_mode_ops(struct bonding *bond, int mode) | 4512 | void bond_set_mode_ops(struct bonding *bond, int mode) |
4435 | { | 4513 | { |
4436 | struct net_device *bond_dev = bond->dev; | 4514 | struct net_device *bond_dev = bond->dev; |
4437 | 4515 | ||
@@ -4467,7 +4545,8 @@ static inline void bond_set_mode_ops(struct bonding *bond, int mode) | |||
4467 | default: | 4545 | default: |
4468 | /* Should never happen, mode already checked */ | 4546 | /* Should never happen, mode already checked */ |
4469 | printk(KERN_ERR DRV_NAME | 4547 | printk(KERN_ERR DRV_NAME |
4470 | ": Error: Unknown bonding mode %d\n", | 4548 | ": %s: Error: Unknown bonding mode %d\n", |
4549 | bond_dev->name, | ||
4471 | mode); | 4550 | mode); |
4472 | break; | 4551 | break; |
4473 | } | 4552 | } |
@@ -4491,7 +4570,7 @@ static struct ethtool_ops bond_ethtool_ops = { | |||
4491 | * Does not allocate but creates a /proc entry. | 4570 | * Does not allocate but creates a /proc entry. |
4492 | * Allowed to fail. | 4571 | * Allowed to fail. |
4493 | */ | 4572 | */ |
4494 | static int __init bond_init(struct net_device *bond_dev, struct bond_params *params) | 4573 | static int bond_init(struct net_device *bond_dev, struct bond_params *params) |
4495 | { | 4574 | { |
4496 | struct bonding *bond = bond_dev->priv; | 4575 | struct bonding *bond = bond_dev->priv; |
4497 | 4576 | ||
@@ -4565,7 +4644,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par | |||
4565 | /* De-initialize device specific data. | 4644 | /* De-initialize device specific data. |
4566 | * Caller must hold rtnl_lock. | 4645 | * Caller must hold rtnl_lock. |
4567 | */ | 4646 | */ |
4568 | static inline void bond_deinit(struct net_device *bond_dev) | 4647 | void bond_deinit(struct net_device *bond_dev) |
4569 | { | 4648 | { |
4570 | struct bonding *bond = bond_dev->priv; | 4649 | struct bonding *bond = bond_dev->priv; |
4571 | 4650 | ||
@@ -4601,7 +4680,7 @@ static void bond_free_all(void) | |||
4601 | * Convert string input module parms. Accept either the | 4680 | * Convert string input module parms. Accept either the |
4602 | * number of the mode or its string name. | 4681 | * number of the mode or its string name. |
4603 | */ | 4682 | */ |
4604 | static inline int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl) | 4683 | int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl) |
4605 | { | 4684 | { |
4606 | int i; | 4685 | int i; |
4607 | 4686 | ||
@@ -4670,7 +4749,7 @@ static int bond_check_params(struct bond_params *params) | |||
4670 | if (max_bonds < 1 || max_bonds > INT_MAX) { | 4749 | if (max_bonds < 1 || max_bonds > INT_MAX) { |
4671 | printk(KERN_WARNING DRV_NAME | 4750 | printk(KERN_WARNING DRV_NAME |
4672 | ": Warning: max_bonds (%d) not in range %d-%d, so it " | 4751 | ": Warning: max_bonds (%d) not in range %d-%d, so it " |
4673 | "was reset to BOND_DEFAULT_MAX_BONDS (%d)", | 4752 | "was reset to BOND_DEFAULT_MAX_BONDS (%d)\n", |
4674 | max_bonds, 1, INT_MAX, BOND_DEFAULT_MAX_BONDS); | 4753 | max_bonds, 1, INT_MAX, BOND_DEFAULT_MAX_BONDS); |
4675 | max_bonds = BOND_DEFAULT_MAX_BONDS; | 4754 | max_bonds = BOND_DEFAULT_MAX_BONDS; |
4676 | } | 4755 | } |
@@ -4881,81 +4960,96 @@ static int bond_check_params(struct bond_params *params) | |||
4881 | return 0; | 4960 | return 0; |
4882 | } | 4961 | } |
4883 | 4962 | ||
4963 | /* Create a new bond based on the specified name and bonding parameters. | ||
4964 | * Caller must NOT hold rtnl_lock; we need to release it here before we | ||
4965 | * set up our sysfs entries. | ||
4966 | */ | ||
4967 | int bond_create(char *name, struct bond_params *params, struct bonding **newbond) | ||
4968 | { | ||
4969 | struct net_device *bond_dev; | ||
4970 | int res; | ||
4971 | |||
4972 | rtnl_lock(); | ||
4973 | bond_dev = alloc_netdev(sizeof(struct bonding), name, ether_setup); | ||
4974 | if (!bond_dev) { | ||
4975 | printk(KERN_ERR DRV_NAME | ||
4976 | ": %s: eek! can't alloc netdev!\n", | ||
4977 | name); | ||
4978 | res = -ENOMEM; | ||
4979 | goto out_rtnl; | ||
4980 | } | ||
4981 | |||
4982 | /* bond_init() must be called after dev_alloc_name() (for the | ||
4983 | * /proc files), but before register_netdevice(), because we | ||
4984 | * need to set function pointers. | ||
4985 | */ | ||
4986 | |||
4987 | res = bond_init(bond_dev, params); | ||
4988 | if (res < 0) { | ||
4989 | goto out_netdev; | ||
4990 | } | ||
4991 | |||
4992 | SET_MODULE_OWNER(bond_dev); | ||
4993 | |||
4994 | res = register_netdevice(bond_dev); | ||
4995 | if (res < 0) { | ||
4996 | goto out_bond; | ||
4997 | } | ||
4998 | if (newbond) | ||
4999 | *newbond = bond_dev->priv; | ||
5000 | |||
5001 | rtnl_unlock(); /* allows sysfs registration of net device */ | ||
5002 | res = bond_create_sysfs_entry(bond_dev->priv); | ||
5003 | goto done; | ||
5004 | out_bond: | ||
5005 | bond_deinit(bond_dev); | ||
5006 | out_netdev: | ||
5007 | free_netdev(bond_dev); | ||
5008 | out_rtnl: | ||
5009 | rtnl_unlock(); | ||
5010 | done: | ||
5011 | return res; | ||
5012 | } | ||
5013 | |||
4884 | static int __init bonding_init(void) | 5014 | static int __init bonding_init(void) |
4885 | { | 5015 | { |
4886 | struct bond_params params; | ||
4887 | int i; | 5016 | int i; |
4888 | int res; | 5017 | int res; |
5018 | char new_bond_name[8]; /* Enough room for 999 bonds at init. */ | ||
4889 | 5019 | ||
4890 | printk(KERN_INFO "%s", version); | 5020 | printk(KERN_INFO "%s", version); |
4891 | 5021 | ||
4892 | res = bond_check_params(¶ms); | 5022 | res = bond_check_params(&bonding_defaults); |
4893 | if (res) { | 5023 | if (res) { |
4894 | return res; | 5024 | goto out; |
4895 | } | 5025 | } |
4896 | 5026 | ||
4897 | rtnl_lock(); | ||
4898 | |||
4899 | #ifdef CONFIG_PROC_FS | 5027 | #ifdef CONFIG_PROC_FS |
4900 | bond_create_proc_dir(); | 5028 | bond_create_proc_dir(); |
4901 | #endif | 5029 | #endif |
4902 | |||
4903 | for (i = 0; i < max_bonds; i++) { | 5030 | for (i = 0; i < max_bonds; i++) { |
4904 | struct net_device *bond_dev; | 5031 | sprintf(new_bond_name, "bond%d",i); |
4905 | 5032 | res = bond_create(new_bond_name,&bonding_defaults, NULL); | |
4906 | bond_dev = alloc_netdev(sizeof(struct bonding), "", ether_setup); | 5033 | if (res) |
4907 | if (!bond_dev) { | 5034 | goto err; |
4908 | res = -ENOMEM; | ||
4909 | goto out_err; | ||
4910 | } | ||
4911 | |||
4912 | res = dev_alloc_name(bond_dev, "bond%d"); | ||
4913 | if (res < 0) { | ||
4914 | free_netdev(bond_dev); | ||
4915 | goto out_err; | ||
4916 | } | ||
4917 | |||
4918 | /* bond_init() must be called after dev_alloc_name() (for the | ||
4919 | * /proc files), but before register_netdevice(), because we | ||
4920 | * need to set function pointers. | ||
4921 | */ | ||
4922 | res = bond_init(bond_dev, ¶ms); | ||
4923 | if (res < 0) { | ||
4924 | free_netdev(bond_dev); | ||
4925 | goto out_err; | ||
4926 | } | ||
4927 | |||
4928 | SET_MODULE_OWNER(bond_dev); | ||
4929 | |||
4930 | res = register_netdevice(bond_dev); | ||
4931 | if (res < 0) { | ||
4932 | bond_deinit(bond_dev); | ||
4933 | free_netdev(bond_dev); | ||
4934 | goto out_err; | ||
4935 | } | ||
4936 | } | 5035 | } |
4937 | 5036 | ||
4938 | rtnl_unlock(); | 5037 | res = bond_create_sysfs(); |
5038 | if (res) | ||
5039 | goto err; | ||
5040 | |||
4939 | register_netdevice_notifier(&bond_netdev_notifier); | 5041 | register_netdevice_notifier(&bond_netdev_notifier); |
4940 | register_inetaddr_notifier(&bond_inetaddr_notifier); | 5042 | register_inetaddr_notifier(&bond_inetaddr_notifier); |
4941 | 5043 | ||
4942 | return 0; | 5044 | goto out; |
4943 | 5045 | err: | |
4944 | out_err: | ||
4945 | /* | ||
4946 | * rtnl_unlock() will run netdev_run_todo(), putting the | ||
4947 | * thus-far-registered bonding devices into a state which | ||
4948 | * unregigister_netdevice() will accept | ||
4949 | */ | ||
4950 | rtnl_unlock(); | ||
4951 | rtnl_lock(); | 5046 | rtnl_lock(); |
4952 | |||
4953 | /* free and unregister all bonds that were successfully added */ | ||
4954 | bond_free_all(); | 5047 | bond_free_all(); |
4955 | 5048 | bond_destroy_sysfs(); | |
4956 | rtnl_unlock(); | 5049 | rtnl_unlock(); |
4957 | 5050 | out: | |
4958 | return res; | 5051 | return res; |
5052 | |||
4959 | } | 5053 | } |
4960 | 5054 | ||
4961 | static void __exit bonding_exit(void) | 5055 | static void __exit bonding_exit(void) |
@@ -4965,6 +5059,7 @@ static void __exit bonding_exit(void) | |||
4965 | 5059 | ||
4966 | rtnl_lock(); | 5060 | rtnl_lock(); |
4967 | bond_free_all(); | 5061 | bond_free_all(); |
5062 | bond_destroy_sysfs(); | ||
4968 | rtnl_unlock(); | 5063 | rtnl_unlock(); |
4969 | } | 5064 | } |
4970 | 5065 | ||
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c new file mode 100644 index 000000000000..c5f1c52863cb --- /dev/null +++ b/drivers/net/bonding/bond_sysfs.c | |||
@@ -0,0 +1,1399 @@ | |||
1 | |||
2 | /* | ||
3 | * Copyright(c) 2004-2005 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
13 | * for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | * | ||
19 | * The full GNU General Public License is included in this distribution in the | ||
20 | * file called LICENSE. | ||
21 | * | ||
22 | * | ||
23 | * Changes: | ||
24 | * | ||
25 | * 2004/12/12 - Mitch Williams <mitch.a.williams at intel dot com> | ||
26 | * - Initial creation of sysfs interface. | ||
27 | * | ||
28 | * 2005/06/22 - Radheka Godse <radheka.godse at intel dot com> | ||
29 | * - Added ifenslave -c type functionality to sysfs | ||
30 | * - Added sysfs files for attributes such as MII Status and | ||
31 | * 802.3ad aggregator that are displayed in /proc | ||
32 | * - Added "name value" format to sysfs "mode" and | ||
33 | * "lacp_rate", for e.g., "active-backup 1" or "slow 0" for | ||
34 | * consistency and ease of script parsing | ||
35 | * - Fixed reversal of octets in arp_ip_targets via sysfs | ||
36 | * - sysfs support to handle bond interface re-naming | ||
37 | * - Moved all sysfs entries into /sys/class/net instead of | ||
38 | * of using a standalone subsystem. | ||
39 | * - Added sysfs symlinks between masters and slaves | ||
40 | * - Corrected bugs in sysfs unload path when creating bonds | ||
41 | * with existing interface names. | ||
42 | * - Removed redundant sysfs stat file since it duplicates slave info | ||
43 | * from the proc file | ||
44 | * - Fixed errors in sysfs show/store arp targets. | ||
45 | * - For consistency with ifenslave, instead of exiting | ||
46 | * with an error, updated bonding sysfs to | ||
47 | * close and attempt to enslave an up adapter. | ||
48 | * - Fixed NULL dereference when adding a slave interface | ||
49 | * that does not exist. | ||
50 | * - Added checks in sysfs bonding to reject invalid ip addresses | ||
51 | * - Synch up with post linux-2.6.12 bonding changes | ||
52 | * - Created sysfs bond attrib for xmit_hash_policy | ||
53 | * | ||
54 | * 2005/09/19 - Mitch Williams <mitch.a.williams at intel dot com> | ||
55 | * - Changed semantics of multi-item files to be command-based | ||
56 | * instead of list-based. | ||
57 | * - Changed ARP target handler to use in_aton instead of sscanf | ||
58 | * - Style changes. | ||
59 | * 2005/09/27 - Mitch Williams <mitch.a.williams at intel dot com> | ||
60 | * - Made line endings consistent. | ||
61 | * - Removed "none" from primary output - just put blank instead | ||
62 | * - Fixed bug with long interface names | ||
63 | */ | ||
64 | #include <linux/config.h> | ||
65 | #include <linux/kernel.h> | ||
66 | #include <linux/module.h> | ||
67 | #include <linux/sched.h> | ||
68 | #include <linux/device.h> | ||
69 | #include <linux/sysdev.h> | ||
70 | #include <linux/fs.h> | ||
71 | #include <linux/types.h> | ||
72 | #include <linux/string.h> | ||
73 | #include <linux/netdevice.h> | ||
74 | #include <linux/inetdevice.h> | ||
75 | #include <linux/in.h> | ||
76 | #include <linux/sysfs.h> | ||
77 | #include <linux/string.h> | ||
78 | #include <linux/ctype.h> | ||
79 | #include <linux/inet.h> | ||
80 | #include <linux/rtnetlink.h> | ||
81 | |||
82 | /* #define BONDING_DEBUG 1 */ | ||
83 | #include "bonding.h" | ||
84 | #define to_class_dev(obj) container_of(obj,struct class_device,kobj) | ||
85 | #define to_net_dev(class) container_of(class, struct net_device, class_dev) | ||
86 | #define to_bond(cd) ((struct bonding *)(to_net_dev(cd)->priv)) | ||
87 | |||
88 | /*---------------------------- Declarations -------------------------------*/ | ||
89 | |||
90 | |||
91 | extern struct list_head bond_dev_list; | ||
92 | extern struct bond_params bonding_defaults; | ||
93 | extern struct bond_parm_tbl bond_mode_tbl[]; | ||
94 | extern struct bond_parm_tbl bond_lacp_tbl[]; | ||
95 | extern struct bond_parm_tbl xmit_hashtype_tbl[]; | ||
96 | |||
97 | static int expected_refcount = -1; | ||
98 | static struct class *netdev_class; | ||
99 | /*--------------------------- Data Structures -----------------------------*/ | ||
100 | |||
101 | /* Bonding sysfs lock. Why can't we just use the subsytem lock? | ||
102 | * Because kobject_register tries to acquire the subsystem lock. If | ||
103 | * we already hold the lock (which we would if the user was creating | ||
104 | * a new bond through the sysfs interface), we deadlock. | ||
105 | * This lock is only needed when deleting a bond - we need to make sure | ||
106 | * that we don't collide with an ongoing ioctl. | ||
107 | */ | ||
108 | |||
109 | struct rw_semaphore bonding_rwsem; | ||
110 | |||
111 | |||
112 | |||
113 | |||
114 | /*------------------------------ Functions --------------------------------*/ | ||
115 | |||
116 | /* | ||
117 | * "show" function for the bond_masters attribute. | ||
118 | * The class parameter is ignored. | ||
119 | */ | ||
120 | static ssize_t bonding_show_bonds(struct class *cls, char *buffer) | ||
121 | { | ||
122 | int res = 0; | ||
123 | struct bonding *bond; | ||
124 | |||
125 | down_read(&(bonding_rwsem)); | ||
126 | |||
127 | list_for_each_entry(bond, &bond_dev_list, bond_list) { | ||
128 | if (res > (PAGE_SIZE - IFNAMSIZ)) { | ||
129 | /* not enough space for another interface name */ | ||
130 | if ((PAGE_SIZE - res) > 10) | ||
131 | res = PAGE_SIZE - 10; | ||
132 | res += sprintf(buffer + res, "++more++"); | ||
133 | break; | ||
134 | } | ||
135 | res += sprintf(buffer + res, "%s ", | ||
136 | bond->dev->name); | ||
137 | } | ||
138 | res += sprintf(buffer + res, "\n"); | ||
139 | res++; | ||
140 | up_read(&(bonding_rwsem)); | ||
141 | return res; | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * "store" function for the bond_masters attribute. This is what | ||
146 | * creates and deletes entire bonds. | ||
147 | * | ||
148 | * The class parameter is ignored. | ||
149 | * | ||
150 | */ | ||
151 | |||
152 | static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t count) | ||
153 | { | ||
154 | char command[IFNAMSIZ + 1] = {0, }; | ||
155 | char *ifname; | ||
156 | int res = count; | ||
157 | struct bonding *bond; | ||
158 | struct bonding *nxt; | ||
159 | |||
160 | down_write(&(bonding_rwsem)); | ||
161 | sscanf(buffer, "%16s", command); /* IFNAMSIZ*/ | ||
162 | ifname = command + 1; | ||
163 | if ((strlen(command) <= 1) || | ||
164 | !dev_valid_name(ifname)) | ||
165 | goto err_no_cmd; | ||
166 | |||
167 | if (command[0] == '+') { | ||
168 | |||
169 | /* Check to see if the bond already exists. */ | ||
170 | list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) | ||
171 | if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) { | ||
172 | printk(KERN_ERR DRV_NAME | ||
173 | ": cannot add bond %s; it already exists\n", | ||
174 | ifname); | ||
175 | res = -EPERM; | ||
176 | goto out; | ||
177 | } | ||
178 | |||
179 | printk(KERN_INFO DRV_NAME | ||
180 | ": %s is being created...\n", ifname); | ||
181 | if (bond_create(ifname, &bonding_defaults, &bond)) { | ||
182 | printk(KERN_INFO DRV_NAME | ||
183 | ": %s interface already exists. Bond creation failed.\n", | ||
184 | ifname); | ||
185 | res = -EPERM; | ||
186 | } | ||
187 | goto out; | ||
188 | } | ||
189 | |||
190 | if (command[0] == '-') { | ||
191 | list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) | ||
192 | if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) { | ||
193 | rtnl_lock(); | ||
194 | /* check the ref count on the bond's kobject. | ||
195 | * If it's > expected, then there's a file open, | ||
196 | * and we have to fail. | ||
197 | */ | ||
198 | if (atomic_read(&bond->dev->class_dev.kobj.kref.refcount) | ||
199 | > expected_refcount){ | ||
200 | rtnl_unlock(); | ||
201 | printk(KERN_INFO DRV_NAME | ||
202 | ": Unable remove bond %s due to open references.\n", | ||
203 | ifname); | ||
204 | res = -EPERM; | ||
205 | goto out; | ||
206 | } | ||
207 | printk(KERN_INFO DRV_NAME | ||
208 | ": %s is being deleted...\n", | ||
209 | bond->dev->name); | ||
210 | unregister_netdevice(bond->dev); | ||
211 | bond_deinit(bond->dev); | ||
212 | bond_destroy_sysfs_entry(bond); | ||
213 | rtnl_unlock(); | ||
214 | goto out; | ||
215 | } | ||
216 | |||
217 | printk(KERN_ERR DRV_NAME | ||
218 | ": unable to delete non-existent bond %s\n", ifname); | ||
219 | res = -ENODEV; | ||
220 | goto out; | ||
221 | } | ||
222 | |||
223 | err_no_cmd: | ||
224 | printk(KERN_ERR DRV_NAME | ||
225 | ": no command found in bonding_masters. Use +ifname or -ifname.\n"); | ||
226 | res = -EPERM; | ||
227 | |||
228 | /* Always return either count or an error. If you return 0, you'll | ||
229 | * get called forever, which is bad. | ||
230 | */ | ||
231 | out: | ||
232 | up_write(&(bonding_rwsem)); | ||
233 | return res; | ||
234 | } | ||
235 | /* class attribute for bond_masters file. This ends up in /sys/class/net */ | ||
236 | static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO, | ||
237 | bonding_show_bonds, bonding_store_bonds); | ||
238 | |||
239 | int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave) | ||
240 | { | ||
241 | char linkname[IFNAMSIZ+7]; | ||
242 | int ret = 0; | ||
243 | |||
244 | /* first, create a link from the slave back to the master */ | ||
245 | ret = sysfs_create_link(&(slave->class_dev.kobj), &(master->class_dev.kobj), | ||
246 | "master"); | ||
247 | if (ret) | ||
248 | return ret; | ||
249 | /* next, create a link from the master to the slave */ | ||
250 | sprintf(linkname,"slave_%s",slave->name); | ||
251 | ret = sysfs_create_link(&(master->class_dev.kobj), &(slave->class_dev.kobj), | ||
252 | linkname); | ||
253 | return ret; | ||
254 | |||
255 | } | ||
256 | |||
257 | void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave) | ||
258 | { | ||
259 | char linkname[IFNAMSIZ+7]; | ||
260 | |||
261 | sysfs_remove_link(&(slave->class_dev.kobj), "master"); | ||
262 | sprintf(linkname,"slave_%s",slave->name); | ||
263 | sysfs_remove_link(&(master->class_dev.kobj), linkname); | ||
264 | } | ||
265 | |||
266 | |||
267 | /* | ||
268 | * Show the slaves in the current bond. | ||
269 | */ | ||
270 | static ssize_t bonding_show_slaves(struct class_device *cd, char *buf) | ||
271 | { | ||
272 | struct slave *slave; | ||
273 | int i, res = 0; | ||
274 | struct bonding *bond = to_bond(cd); | ||
275 | |||
276 | read_lock_bh(&bond->lock); | ||
277 | bond_for_each_slave(bond, slave, i) { | ||
278 | if (res > (PAGE_SIZE - IFNAMSIZ)) { | ||
279 | /* not enough space for another interface name */ | ||
280 | if ((PAGE_SIZE - res) > 10) | ||
281 | res = PAGE_SIZE - 10; | ||
282 | res += sprintf(buf + res, "++more++"); | ||
283 | break; | ||
284 | } | ||
285 | res += sprintf(buf + res, "%s ", slave->dev->name); | ||
286 | } | ||
287 | read_unlock_bh(&bond->lock); | ||
288 | res += sprintf(buf + res, "\n"); | ||
289 | res++; | ||
290 | return res; | ||
291 | } | ||
292 | |||
293 | /* | ||
294 | * Set the slaves in the current bond. The bond interface must be | ||
295 | * up for this to succeed. | ||
296 | * This function is largely the same flow as bonding_update_bonds(). | ||
297 | */ | ||
298 | static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer, size_t count) | ||
299 | { | ||
300 | char command[IFNAMSIZ + 1] = { 0, }; | ||
301 | char *ifname; | ||
302 | int i, res, found, ret = count; | ||
303 | struct slave *slave; | ||
304 | struct net_device *dev = 0; | ||
305 | struct bonding *bond = to_bond(cd); | ||
306 | |||
307 | /* Quick sanity check -- is the bond interface up? */ | ||
308 | if (!(bond->dev->flags & IFF_UP)) { | ||
309 | printk(KERN_ERR DRV_NAME | ||
310 | ": %s: Unable to update slaves because interface is down.\n", | ||
311 | bond->dev->name); | ||
312 | ret = -EPERM; | ||
313 | goto out; | ||
314 | } | ||
315 | |||
316 | /* Note: We can't hold bond->lock here, as bond_create grabs it. */ | ||
317 | |||
318 | sscanf(buffer, "%16s", command); /* IFNAMSIZ*/ | ||
319 | ifname = command + 1; | ||
320 | if ((strlen(command) <= 1) || | ||
321 | !dev_valid_name(ifname)) | ||
322 | goto err_no_cmd; | ||
323 | |||
324 | if (command[0] == '+') { | ||
325 | |||
326 | /* Got a slave name in ifname. Is it already in the list? */ | ||
327 | found = 0; | ||
328 | read_lock_bh(&bond->lock); | ||
329 | bond_for_each_slave(bond, slave, i) | ||
330 | if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { | ||
331 | printk(KERN_ERR DRV_NAME | ||
332 | ": %s: Interface %s is already enslaved!\n", | ||
333 | bond->dev->name, ifname); | ||
334 | ret = -EPERM; | ||
335 | read_unlock_bh(&bond->lock); | ||
336 | goto out; | ||
337 | } | ||
338 | |||
339 | read_unlock_bh(&bond->lock); | ||
340 | printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n", | ||
341 | bond->dev->name, ifname); | ||
342 | dev = dev_get_by_name(ifname); | ||
343 | if (!dev) { | ||
344 | printk(KERN_INFO DRV_NAME | ||
345 | ": %s: Interface %s does not exist!\n", | ||
346 | bond->dev->name, ifname); | ||
347 | ret = -EPERM; | ||
348 | goto out; | ||
349 | } | ||
350 | else | ||
351 | dev_put(dev); | ||
352 | |||
353 | if (dev->flags & IFF_UP) { | ||
354 | printk(KERN_ERR DRV_NAME | ||
355 | ": %s: Error: Unable to enslave %s " | ||
356 | "because it is already up.\n", | ||
357 | bond->dev->name, dev->name); | ||
358 | ret = -EPERM; | ||
359 | goto out; | ||
360 | } | ||
361 | /* If this is the first slave, then we need to set | ||
362 | the master's hardware address to be the same as the | ||
363 | slave's. */ | ||
364 | if (!(*((u32 *) & (bond->dev->dev_addr[0])))) { | ||
365 | memcpy(bond->dev->dev_addr, dev->dev_addr, | ||
366 | dev->addr_len); | ||
367 | } | ||
368 | |||
369 | /* Set the slave's MTU to match the bond */ | ||
370 | if (dev->mtu != bond->dev->mtu) { | ||
371 | if (dev->change_mtu) { | ||
372 | res = dev->change_mtu(dev, | ||
373 | bond->dev->mtu); | ||
374 | if (res) { | ||
375 | ret = res; | ||
376 | goto out; | ||
377 | } | ||
378 | } else { | ||
379 | dev->mtu = bond->dev->mtu; | ||
380 | } | ||
381 | } | ||
382 | rtnl_lock(); | ||
383 | res = bond_enslave(bond->dev, dev); | ||
384 | rtnl_unlock(); | ||
385 | if (res) { | ||
386 | ret = res; | ||
387 | } | ||
388 | goto out; | ||
389 | } | ||
390 | |||
391 | if (command[0] == '-') { | ||
392 | dev = NULL; | ||
393 | bond_for_each_slave(bond, slave, i) | ||
394 | if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { | ||
395 | dev = slave->dev; | ||
396 | break; | ||
397 | } | ||
398 | if (dev) { | ||
399 | printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n", | ||
400 | bond->dev->name, dev->name); | ||
401 | rtnl_lock(); | ||
402 | res = bond_release(bond->dev, dev); | ||
403 | rtnl_unlock(); | ||
404 | if (res) { | ||
405 | ret = res; | ||
406 | goto out; | ||
407 | } | ||
408 | /* set the slave MTU to the default */ | ||
409 | if (dev->change_mtu) { | ||
410 | dev->change_mtu(dev, 1500); | ||
411 | } else { | ||
412 | dev->mtu = 1500; | ||
413 | } | ||
414 | } | ||
415 | else { | ||
416 | printk(KERN_ERR DRV_NAME ": unable to remove non-existent slave %s for bond %s.\n", | ||
417 | ifname, bond->dev->name); | ||
418 | ret = -ENODEV; | ||
419 | } | ||
420 | goto out; | ||
421 | } | ||
422 | |||
423 | err_no_cmd: | ||
424 | printk(KERN_ERR DRV_NAME ": no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name); | ||
425 | ret = -EPERM; | ||
426 | |||
427 | out: | ||
428 | return ret; | ||
429 | } | ||
430 | |||
431 | static CLASS_DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves); | ||
432 | |||
433 | /* | ||
434 | * Show and set the bonding mode. The bond interface must be down to | ||
435 | * change the mode. | ||
436 | */ | ||
437 | static ssize_t bonding_show_mode(struct class_device *cd, char *buf) | ||
438 | { | ||
439 | struct bonding *bond = to_bond(cd); | ||
440 | |||
441 | return sprintf(buf, "%s %d\n", | ||
442 | bond_mode_tbl[bond->params.mode].modename, | ||
443 | bond->params.mode) + 1; | ||
444 | } | ||
445 | |||
446 | static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size_t count) | ||
447 | { | ||
448 | int new_value, ret = count; | ||
449 | struct bonding *bond = to_bond(cd); | ||
450 | |||
451 | if (bond->dev->flags & IFF_UP) { | ||
452 | printk(KERN_ERR DRV_NAME | ||
453 | ": unable to update mode of %s because interface is up.\n", | ||
454 | bond->dev->name); | ||
455 | ret = -EPERM; | ||
456 | goto out; | ||
457 | } | ||
458 | |||
459 | new_value = bond_parse_parm((char *)buf, bond_mode_tbl); | ||
460 | if (new_value < 0) { | ||
461 | printk(KERN_ERR DRV_NAME | ||
462 | ": %s: Ignoring invalid mode value %.*s.\n", | ||
463 | bond->dev->name, | ||
464 | (int)strlen(buf) - 1, buf); | ||
465 | ret = -EINVAL; | ||
466 | goto out; | ||
467 | } else { | ||
468 | bond->params.mode = new_value; | ||
469 | bond_set_mode_ops(bond, bond->params.mode); | ||
470 | printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n", | ||
471 | bond->dev->name, bond_mode_tbl[new_value].modename, new_value); | ||
472 | } | ||
473 | out: | ||
474 | return ret; | ||
475 | } | ||
476 | static CLASS_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode); | ||
477 | |||
478 | /* | ||
479 | * Show and set the bonding transmit hash method. The bond interface must be down to | ||
480 | * change the xmit hash policy. | ||
481 | */ | ||
482 | static ssize_t bonding_show_xmit_hash(struct class_device *cd, char *buf) | ||
483 | { | ||
484 | int count; | ||
485 | struct bonding *bond = to_bond(cd); | ||
486 | |||
487 | if ((bond->params.mode != BOND_MODE_XOR) && | ||
488 | (bond->params.mode != BOND_MODE_8023AD)) { | ||
489 | // Not Applicable | ||
490 | count = sprintf(buf, "NA\n") + 1; | ||
491 | } else { | ||
492 | count = sprintf(buf, "%s %d\n", | ||
493 | xmit_hashtype_tbl[bond->params.xmit_policy].modename, | ||
494 | bond->params.xmit_policy) + 1; | ||
495 | } | ||
496 | |||
497 | return count; | ||
498 | } | ||
499 | |||
500 | static ssize_t bonding_store_xmit_hash(struct class_device *cd, const char *buf, size_t count) | ||
501 | { | ||
502 | int new_value, ret = count; | ||
503 | struct bonding *bond = to_bond(cd); | ||
504 | |||
505 | if (bond->dev->flags & IFF_UP) { | ||
506 | printk(KERN_ERR DRV_NAME | ||
507 | "%s: Interface is up. Unable to update xmit policy.\n", | ||
508 | bond->dev->name); | ||
509 | ret = -EPERM; | ||
510 | goto out; | ||
511 | } | ||
512 | |||
513 | if ((bond->params.mode != BOND_MODE_XOR) && | ||
514 | (bond->params.mode != BOND_MODE_8023AD)) { | ||
515 | printk(KERN_ERR DRV_NAME | ||
516 | "%s: Transmit hash policy is irrelevant in this mode.\n", | ||
517 | bond->dev->name); | ||
518 | ret = -EPERM; | ||
519 | goto out; | ||
520 | } | ||
521 | |||
522 | new_value = bond_parse_parm((char *)buf, xmit_hashtype_tbl); | ||
523 | if (new_value < 0) { | ||
524 | printk(KERN_ERR DRV_NAME | ||
525 | ": %s: Ignoring invalid xmit hash policy value %.*s.\n", | ||
526 | bond->dev->name, | ||
527 | (int)strlen(buf) - 1, buf); | ||
528 | ret = -EINVAL; | ||
529 | goto out; | ||
530 | } else { | ||
531 | bond->params.xmit_policy = new_value; | ||
532 | bond_set_mode_ops(bond, bond->params.mode); | ||
533 | printk(KERN_INFO DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n", | ||
534 | bond->dev->name, xmit_hashtype_tbl[new_value].modename, new_value); | ||
535 | } | ||
536 | out: | ||
537 | return ret; | ||
538 | } | ||
539 | static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash); | ||
540 | |||
541 | /* | ||
542 | * Show and set the arp timer interval. There are two tricky bits | ||
543 | * here. First, if ARP monitoring is activated, then we must disable | ||
544 | * MII monitoring. Second, if the ARP timer isn't running, we must | ||
545 | * start it. | ||
546 | */ | ||
547 | static ssize_t bonding_show_arp_interval(struct class_device *cd, char *buf) | ||
548 | { | ||
549 | struct bonding *bond = to_bond(cd); | ||
550 | |||
551 | return sprintf(buf, "%d\n", bond->params.arp_interval) + 1; | ||
552 | } | ||
553 | |||
554 | static ssize_t bonding_store_arp_interval(struct class_device *cd, const char *buf, size_t count) | ||
555 | { | ||
556 | int new_value, ret = count; | ||
557 | struct bonding *bond = to_bond(cd); | ||
558 | |||
559 | if (sscanf(buf, "%d", &new_value) != 1) { | ||
560 | printk(KERN_ERR DRV_NAME | ||
561 | ": %s: no arp_interval value specified.\n", | ||
562 | bond->dev->name); | ||
563 | ret = -EINVAL; | ||
564 | goto out; | ||
565 | } | ||
566 | if (new_value < 0) { | ||
567 | printk(KERN_ERR DRV_NAME | ||
568 | ": %s: Invalid arp_interval value %d not in range 1-%d; rejected.\n", | ||
569 | bond->dev->name, new_value, INT_MAX); | ||
570 | ret = -EINVAL; | ||
571 | goto out; | ||
572 | } | ||
573 | |||
574 | printk(KERN_INFO DRV_NAME | ||
575 | ": %s: Setting ARP monitoring interval to %d.\n", | ||
576 | bond->dev->name, new_value); | ||
577 | bond->params.arp_interval = new_value; | ||
578 | if (bond->params.miimon) { | ||
579 | printk(KERN_INFO DRV_NAME | ||
580 | ": %s: ARP monitoring cannot be used with MII monitoring. " | ||
581 | "%s Disabling MII monitoring.\n", | ||
582 | bond->dev->name, bond->dev->name); | ||
583 | bond->params.miimon = 0; | ||
584 | /* Kill MII timer, else it brings bond's link down */ | ||
585 | if (bond->arp_timer.function) { | ||
586 | printk(KERN_INFO DRV_NAME | ||
587 | ": %s: Kill MII timer, else it brings bond's link down...\n", | ||
588 | bond->dev->name); | ||
589 | del_timer_sync(&bond->mii_timer); | ||
590 | } | ||
591 | } | ||
592 | if (!bond->params.arp_targets[0]) { | ||
593 | printk(KERN_INFO DRV_NAME | ||
594 | ": %s: ARP monitoring has been set up, " | ||
595 | "but no ARP targets have been specified.\n", | ||
596 | bond->dev->name); | ||
597 | } | ||
598 | if (bond->dev->flags & IFF_UP) { | ||
599 | /* If the interface is up, we may need to fire off | ||
600 | * the ARP timer. If the interface is down, the | ||
601 | * timer will get fired off when the open function | ||
602 | * is called. | ||
603 | */ | ||
604 | if (bond->arp_timer.function) { | ||
605 | /* The timer's already set up, so fire it off */ | ||
606 | mod_timer(&bond->arp_timer, jiffies + 1); | ||
607 | } else { | ||
608 | /* Set up the timer. */ | ||
609 | init_timer(&bond->arp_timer); | ||
610 | bond->arp_timer.expires = jiffies + 1; | ||
611 | bond->arp_timer.data = | ||
612 | (unsigned long) bond->dev; | ||
613 | if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { | ||
614 | bond->arp_timer.function = | ||
615 | (void *) | ||
616 | &bond_activebackup_arp_mon; | ||
617 | } else { | ||
618 | bond->arp_timer.function = | ||
619 | (void *) | ||
620 | &bond_loadbalance_arp_mon; | ||
621 | } | ||
622 | add_timer(&bond->arp_timer); | ||
623 | } | ||
624 | } | ||
625 | |||
626 | out: | ||
627 | return ret; | ||
628 | } | ||
629 | static CLASS_DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval); | ||
630 | |||
631 | /* | ||
632 | * Show and set the arp targets. | ||
633 | */ | ||
634 | static ssize_t bonding_show_arp_targets(struct class_device *cd, char *buf) | ||
635 | { | ||
636 | int i, res = 0; | ||
637 | struct bonding *bond = to_bond(cd); | ||
638 | |||
639 | for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) { | ||
640 | if (bond->params.arp_targets[i]) | ||
641 | res += sprintf(buf + res, "%u.%u.%u.%u ", | ||
642 | NIPQUAD(bond->params.arp_targets[i])); | ||
643 | } | ||
644 | if (res) | ||
645 | res--; /* eat the leftover space */ | ||
646 | res += sprintf(buf + res, "\n"); | ||
647 | res++; | ||
648 | return res; | ||
649 | } | ||
650 | |||
651 | static ssize_t bonding_store_arp_targets(struct class_device *cd, const char *buf, size_t count) | ||
652 | { | ||
653 | u32 newtarget; | ||
654 | int i = 0, done = 0, ret = count; | ||
655 | struct bonding *bond = to_bond(cd); | ||
656 | u32 *targets; | ||
657 | |||
658 | targets = bond->params.arp_targets; | ||
659 | newtarget = in_aton(buf + 1); | ||
660 | /* look for adds */ | ||
661 | if (buf[0] == '+') { | ||
662 | if ((newtarget == 0) || (newtarget == INADDR_BROADCAST)) { | ||
663 | printk(KERN_ERR DRV_NAME | ||
664 | ": %s: invalid ARP target %u.%u.%u.%u specified for addition\n", | ||
665 | bond->dev->name, NIPQUAD(newtarget)); | ||
666 | ret = -EINVAL; | ||
667 | goto out; | ||
668 | } | ||
669 | /* look for an empty slot to put the target in, and check for dupes */ | ||
670 | for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) { | ||
671 | if (targets[i] == newtarget) { /* duplicate */ | ||
672 | printk(KERN_ERR DRV_NAME | ||
673 | ": %s: ARP target %u.%u.%u.%u is already present\n", | ||
674 | bond->dev->name, NIPQUAD(newtarget)); | ||
675 | if (done) | ||
676 | targets[i] = 0; | ||
677 | ret = -EINVAL; | ||
678 | goto out; | ||
679 | } | ||
680 | if (targets[i] == 0 && !done) { | ||
681 | printk(KERN_INFO DRV_NAME | ||
682 | ": %s: adding ARP target %d.%d.%d.%d.\n", | ||
683 | bond->dev->name, NIPQUAD(newtarget)); | ||
684 | done = 1; | ||
685 | targets[i] = newtarget; | ||
686 | } | ||
687 | } | ||
688 | if (!done) { | ||
689 | printk(KERN_ERR DRV_NAME | ||
690 | ": %s: ARP target table is full!\n", | ||
691 | bond->dev->name); | ||
692 | ret = -EINVAL; | ||
693 | goto out; | ||
694 | } | ||
695 | |||
696 | } | ||
697 | else if (buf[0] == '-') { | ||
698 | if ((newtarget == 0) || (newtarget == INADDR_BROADCAST)) { | ||
699 | printk(KERN_ERR DRV_NAME | ||
700 | ": %s: invalid ARP target %d.%d.%d.%d specified for removal\n", | ||
701 | bond->dev->name, NIPQUAD(newtarget)); | ||
702 | ret = -EINVAL; | ||
703 | goto out; | ||
704 | } | ||
705 | |||
706 | for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) { | ||
707 | if (targets[i] == newtarget) { | ||
708 | printk(KERN_INFO DRV_NAME | ||
709 | ": %s: removing ARP target %d.%d.%d.%d.\n", | ||
710 | bond->dev->name, NIPQUAD(newtarget)); | ||
711 | targets[i] = 0; | ||
712 | done = 1; | ||
713 | } | ||
714 | } | ||
715 | if (!done) { | ||
716 | printk(KERN_INFO DRV_NAME | ||
717 | ": %s: unable to remove nonexistent ARP target %d.%d.%d.%d.\n", | ||
718 | bond->dev->name, NIPQUAD(newtarget)); | ||
719 | ret = -EINVAL; | ||
720 | goto out; | ||
721 | } | ||
722 | } | ||
723 | else { | ||
724 | printk(KERN_ERR DRV_NAME ": no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n", | ||
725 | bond->dev->name); | ||
726 | ret = -EPERM; | ||
727 | goto out; | ||
728 | } | ||
729 | |||
730 | out: | ||
731 | return ret; | ||
732 | } | ||
733 | static CLASS_DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets); | ||
734 | |||
735 | /* | ||
736 | * Show and set the up and down delays. These must be multiples of the | ||
737 | * MII monitoring value, and are stored internally as the multiplier. | ||
738 | * Thus, we must translate to MS for the real world. | ||
739 | */ | ||
740 | static ssize_t bonding_show_downdelay(struct class_device *cd, char *buf) | ||
741 | { | ||
742 | struct bonding *bond = to_bond(cd); | ||
743 | |||
744 | return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon) + 1; | ||
745 | } | ||
746 | |||
747 | static ssize_t bonding_store_downdelay(struct class_device *cd, const char *buf, size_t count) | ||
748 | { | ||
749 | int new_value, ret = count; | ||
750 | struct bonding *bond = to_bond(cd); | ||
751 | |||
752 | if (!(bond->params.miimon)) { | ||
753 | printk(KERN_ERR DRV_NAME | ||
754 | ": %s: Unable to set down delay as MII monitoring is disabled\n", | ||
755 | bond->dev->name); | ||
756 | ret = -EPERM; | ||
757 | goto out; | ||
758 | } | ||
759 | |||
760 | if (sscanf(buf, "%d", &new_value) != 1) { | ||
761 | printk(KERN_ERR DRV_NAME | ||
762 | ": %s: no down delay value specified.\n", | ||
763 | bond->dev->name); | ||
764 | ret = -EINVAL; | ||
765 | goto out; | ||
766 | } | ||
767 | if (new_value < 0) { | ||
768 | printk(KERN_ERR DRV_NAME | ||
769 | ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n", | ||
770 | bond->dev->name, new_value, 1, INT_MAX); | ||
771 | ret = -EINVAL; | ||
772 | goto out; | ||
773 | } else { | ||
774 | if ((new_value % bond->params.miimon) != 0) { | ||
775 | printk(KERN_WARNING DRV_NAME | ||
776 | ": %s: Warning: down delay (%d) is not a multiple " | ||
777 | "of miimon (%d), delay rounded to %d ms\n", | ||
778 | bond->dev->name, new_value, bond->params.miimon, | ||
779 | (new_value / bond->params.miimon) * | ||
780 | bond->params.miimon); | ||
781 | } | ||
782 | bond->params.downdelay = new_value / bond->params.miimon; | ||
783 | printk(KERN_INFO DRV_NAME ": %s: Setting down delay to %d.\n", | ||
784 | bond->dev->name, bond->params.downdelay * bond->params.miimon); | ||
785 | |||
786 | } | ||
787 | |||
788 | out: | ||
789 | return ret; | ||
790 | } | ||
791 | static CLASS_DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay); | ||
792 | |||
793 | static ssize_t bonding_show_updelay(struct class_device *cd, char *buf) | ||
794 | { | ||
795 | struct bonding *bond = to_bond(cd); | ||
796 | |||
797 | return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon) + 1; | ||
798 | |||
799 | } | ||
800 | |||
801 | static ssize_t bonding_store_updelay(struct class_device *cd, const char *buf, size_t count) | ||
802 | { | ||
803 | int new_value, ret = count; | ||
804 | struct bonding *bond = to_bond(cd); | ||
805 | |||
806 | if (!(bond->params.miimon)) { | ||
807 | printk(KERN_ERR DRV_NAME | ||
808 | ": %s: Unable to set up delay as MII monitoring is disabled\n", | ||
809 | bond->dev->name); | ||
810 | ret = -EPERM; | ||
811 | goto out; | ||
812 | } | ||
813 | |||
814 | if (sscanf(buf, "%d", &new_value) != 1) { | ||
815 | printk(KERN_ERR DRV_NAME | ||
816 | ": %s: no up delay value specified.\n", | ||
817 | bond->dev->name); | ||
818 | ret = -EINVAL; | ||
819 | goto out; | ||
820 | } | ||
821 | if (new_value < 0) { | ||
822 | printk(KERN_ERR DRV_NAME | ||
823 | ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n", | ||
824 | bond->dev->name, new_value, 1, INT_MAX); | ||
825 | ret = -EINVAL; | ||
826 | goto out; | ||
827 | } else { | ||
828 | if ((new_value % bond->params.miimon) != 0) { | ||
829 | printk(KERN_WARNING DRV_NAME | ||
830 | ": %s: Warning: up delay (%d) is not a multiple " | ||
831 | "of miimon (%d), updelay rounded to %d ms\n", | ||
832 | bond->dev->name, new_value, bond->params.miimon, | ||
833 | (new_value / bond->params.miimon) * | ||
834 | bond->params.miimon); | ||
835 | } | ||
836 | bond->params.updelay = new_value / bond->params.miimon; | ||
837 | printk(KERN_INFO DRV_NAME ": %s: Setting up delay to %d.\n", | ||
838 | bond->dev->name, bond->params.updelay * bond->params.miimon); | ||
839 | |||
840 | } | ||
841 | |||
842 | out: | ||
843 | return ret; | ||
844 | } | ||
845 | static CLASS_DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay); | ||
846 | |||
847 | /* | ||
848 | * Show and set the LACP interval. Interface must be down, and the mode | ||
849 | * must be set to 802.3ad mode. | ||
850 | */ | ||
851 | static ssize_t bonding_show_lacp(struct class_device *cd, char *buf) | ||
852 | { | ||
853 | struct bonding *bond = to_bond(cd); | ||
854 | |||
855 | return sprintf(buf, "%s %d\n", | ||
856 | bond_lacp_tbl[bond->params.lacp_fast].modename, | ||
857 | bond->params.lacp_fast) + 1; | ||
858 | } | ||
859 | |||
860 | static ssize_t bonding_store_lacp(struct class_device *cd, const char *buf, size_t count) | ||
861 | { | ||
862 | int new_value, ret = count; | ||
863 | struct bonding *bond = to_bond(cd); | ||
864 | |||
865 | if (bond->dev->flags & IFF_UP) { | ||
866 | printk(KERN_ERR DRV_NAME | ||
867 | ": %s: Unable to update LACP rate because interface is up.\n", | ||
868 | bond->dev->name); | ||
869 | ret = -EPERM; | ||
870 | goto out; | ||
871 | } | ||
872 | |||
873 | if (bond->params.mode != BOND_MODE_8023AD) { | ||
874 | printk(KERN_ERR DRV_NAME | ||
875 | ": %s: Unable to update LACP rate because bond is not in 802.3ad mode.\n", | ||
876 | bond->dev->name); | ||
877 | ret = -EPERM; | ||
878 | goto out; | ||
879 | } | ||
880 | |||
881 | new_value = bond_parse_parm((char *)buf, bond_lacp_tbl); | ||
882 | |||
883 | if ((new_value == 1) || (new_value == 0)) { | ||
884 | bond->params.lacp_fast = new_value; | ||
885 | printk(KERN_INFO DRV_NAME | ||
886 | ": %s: Setting LACP rate to %s (%d).\n", | ||
887 | bond->dev->name, bond_lacp_tbl[new_value].modename, new_value); | ||
888 | } else { | ||
889 | printk(KERN_ERR DRV_NAME | ||
890 | ": %s: Ignoring invalid LACP rate value %.*s.\n", | ||
891 | bond->dev->name, (int)strlen(buf) - 1, buf); | ||
892 | ret = -EINVAL; | ||
893 | } | ||
894 | out: | ||
895 | return ret; | ||
896 | } | ||
897 | static CLASS_DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp); | ||
898 | |||
899 | /* | ||
900 | * Show and set the MII monitor interval. There are two tricky bits | ||
901 | * here. First, if MII monitoring is activated, then we must disable | ||
902 | * ARP monitoring. Second, if the timer isn't running, we must | ||
903 | * start it. | ||
904 | */ | ||
905 | static ssize_t bonding_show_miimon(struct class_device *cd, char *buf) | ||
906 | { | ||
907 | struct bonding *bond = to_bond(cd); | ||
908 | |||
909 | return sprintf(buf, "%d\n", bond->params.miimon) + 1; | ||
910 | } | ||
911 | |||
912 | static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, size_t count) | ||
913 | { | ||
914 | int new_value, ret = count; | ||
915 | struct bonding *bond = to_bond(cd); | ||
916 | |||
917 | if (sscanf(buf, "%d", &new_value) != 1) { | ||
918 | printk(KERN_ERR DRV_NAME | ||
919 | ": %s: no miimon value specified.\n", | ||
920 | bond->dev->name); | ||
921 | ret = -EINVAL; | ||
922 | goto out; | ||
923 | } | ||
924 | if (new_value < 0) { | ||
925 | printk(KERN_ERR DRV_NAME | ||
926 | ": %s: Invalid miimon value %d not in range %d-%d; rejected.\n", | ||
927 | bond->dev->name, new_value, 1, INT_MAX); | ||
928 | ret = -EINVAL; | ||
929 | goto out; | ||
930 | } else { | ||
931 | printk(KERN_INFO DRV_NAME | ||
932 | ": %s: Setting MII monitoring interval to %d.\n", | ||
933 | bond->dev->name, new_value); | ||
934 | bond->params.miimon = new_value; | ||
935 | if(bond->params.updelay) | ||
936 | printk(KERN_INFO DRV_NAME | ||
937 | ": %s: Note: Updating updelay (to %d) " | ||
938 | "since it is a multiple of the miimon value.\n", | ||
939 | bond->dev->name, | ||
940 | bond->params.updelay * bond->params.miimon); | ||
941 | if(bond->params.downdelay) | ||
942 | printk(KERN_INFO DRV_NAME | ||
943 | ": %s: Note: Updating downdelay (to %d) " | ||
944 | "since it is a multiple of the miimon value.\n", | ||
945 | bond->dev->name, | ||
946 | bond->params.downdelay * bond->params.miimon); | ||
947 | if (bond->params.arp_interval) { | ||
948 | printk(KERN_INFO DRV_NAME | ||
949 | ": %s: MII monitoring cannot be used with " | ||
950 | "ARP monitoring. Disabling ARP monitoring...\n", | ||
951 | bond->dev->name); | ||
952 | bond->params.arp_interval = 0; | ||
953 | /* Kill ARP timer, else it brings bond's link down */ | ||
954 | if (bond->mii_timer.function) { | ||
955 | printk(KERN_INFO DRV_NAME | ||
956 | ": %s: Kill ARP timer, else it brings bond's link down...\n", | ||
957 | bond->dev->name); | ||
958 | del_timer_sync(&bond->arp_timer); | ||
959 | } | ||
960 | } | ||
961 | |||
962 | if (bond->dev->flags & IFF_UP) { | ||
963 | /* If the interface is up, we may need to fire off | ||
964 | * the MII timer. If the interface is down, the | ||
965 | * timer will get fired off when the open function | ||
966 | * is called. | ||
967 | */ | ||
968 | if (bond->mii_timer.function) { | ||
969 | /* The timer's already set up, so fire it off */ | ||
970 | mod_timer(&bond->mii_timer, jiffies + 1); | ||
971 | } else { | ||
972 | /* Set up the timer. */ | ||
973 | init_timer(&bond->mii_timer); | ||
974 | bond->mii_timer.expires = jiffies + 1; | ||
975 | bond->mii_timer.data = | ||
976 | (unsigned long) bond->dev; | ||
977 | bond->mii_timer.function = | ||
978 | (void *) &bond_mii_monitor; | ||
979 | add_timer(&bond->mii_timer); | ||
980 | } | ||
981 | } | ||
982 | } | ||
983 | out: | ||
984 | return ret; | ||
985 | } | ||
986 | static CLASS_DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon); | ||
987 | |||
988 | /* | ||
989 | * Show and set the primary slave. The store function is much | ||
990 | * simpler than bonding_store_slaves function because it only needs to | ||
991 | * handle one interface name. | ||
992 | * The bond must be a mode that supports a primary for this be | ||
993 | * set. | ||
994 | */ | ||
995 | static ssize_t bonding_show_primary(struct class_device *cd, char *buf) | ||
996 | { | ||
997 | int count = 0; | ||
998 | struct bonding *bond = to_bond(cd); | ||
999 | |||
1000 | if (bond->primary_slave) | ||
1001 | count = sprintf(buf, "%s\n", bond->primary_slave->dev->name) + 1; | ||
1002 | else | ||
1003 | count = sprintf(buf, "\n") + 1; | ||
1004 | |||
1005 | return count; | ||
1006 | } | ||
1007 | |||
1008 | static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, size_t count) | ||
1009 | { | ||
1010 | int i; | ||
1011 | struct slave *slave; | ||
1012 | struct bonding *bond = to_bond(cd); | ||
1013 | |||
1014 | write_lock_bh(&bond->lock); | ||
1015 | if (!USES_PRIMARY(bond->params.mode)) { | ||
1016 | printk(KERN_INFO DRV_NAME | ||
1017 | ": %s: Unable to set primary slave; %s is in mode %d\n", | ||
1018 | bond->dev->name, bond->dev->name, bond->params.mode); | ||
1019 | } else { | ||
1020 | bond_for_each_slave(bond, slave, i) { | ||
1021 | if (strnicmp | ||
1022 | (slave->dev->name, buf, | ||
1023 | strlen(slave->dev->name)) == 0) { | ||
1024 | printk(KERN_INFO DRV_NAME | ||
1025 | ": %s: Setting %s as primary slave.\n", | ||
1026 | bond->dev->name, slave->dev->name); | ||
1027 | bond->primary_slave = slave; | ||
1028 | bond_select_active_slave(bond); | ||
1029 | goto out; | ||
1030 | } | ||
1031 | } | ||
1032 | |||
1033 | /* if we got here, then we didn't match the name of any slave */ | ||
1034 | |||
1035 | if (strlen(buf) == 0 || buf[0] == '\n') { | ||
1036 | printk(KERN_INFO DRV_NAME | ||
1037 | ": %s: Setting primary slave to None.\n", | ||
1038 | bond->dev->name); | ||
1039 | bond->primary_slave = 0; | ||
1040 | bond_select_active_slave(bond); | ||
1041 | } else { | ||
1042 | printk(KERN_INFO DRV_NAME | ||
1043 | ": %s: Unable to set %.*s as primary slave as it is not a slave.\n", | ||
1044 | bond->dev->name, (int)strlen(buf) - 1, buf); | ||
1045 | } | ||
1046 | } | ||
1047 | out: | ||
1048 | write_unlock_bh(&bond->lock); | ||
1049 | return count; | ||
1050 | } | ||
1051 | static CLASS_DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary); | ||
1052 | |||
1053 | /* | ||
1054 | * Show and set the use_carrier flag. | ||
1055 | */ | ||
1056 | static ssize_t bonding_show_carrier(struct class_device *cd, char *buf) | ||
1057 | { | ||
1058 | struct bonding *bond = to_bond(cd); | ||
1059 | |||
1060 | return sprintf(buf, "%d\n", bond->params.use_carrier) + 1; | ||
1061 | } | ||
1062 | |||
1063 | static ssize_t bonding_store_carrier(struct class_device *cd, const char *buf, size_t count) | ||
1064 | { | ||
1065 | int new_value, ret = count; | ||
1066 | struct bonding *bond = to_bond(cd); | ||
1067 | |||
1068 | |||
1069 | if (sscanf(buf, "%d", &new_value) != 1) { | ||
1070 | printk(KERN_ERR DRV_NAME | ||
1071 | ": %s: no use_carrier value specified.\n", | ||
1072 | bond->dev->name); | ||
1073 | ret = -EINVAL; | ||
1074 | goto out; | ||
1075 | } | ||
1076 | if ((new_value == 0) || (new_value == 1)) { | ||
1077 | bond->params.use_carrier = new_value; | ||
1078 | printk(KERN_INFO DRV_NAME ": %s: Setting use_carrier to %d.\n", | ||
1079 | bond->dev->name, new_value); | ||
1080 | } else { | ||
1081 | printk(KERN_INFO DRV_NAME | ||
1082 | ": %s: Ignoring invalid use_carrier value %d.\n", | ||
1083 | bond->dev->name, new_value); | ||
1084 | } | ||
1085 | out: | ||
1086 | return count; | ||
1087 | } | ||
1088 | static CLASS_DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier); | ||
1089 | |||
1090 | |||
1091 | /* | ||
1092 | * Show and set currently active_slave. | ||
1093 | */ | ||
1094 | static ssize_t bonding_show_active_slave(struct class_device *cd, char *buf) | ||
1095 | { | ||
1096 | struct slave *curr; | ||
1097 | struct bonding *bond = to_bond(cd); | ||
1098 | int count; | ||
1099 | |||
1100 | |||
1101 | read_lock(&bond->curr_slave_lock); | ||
1102 | curr = bond->curr_active_slave; | ||
1103 | read_unlock(&bond->curr_slave_lock); | ||
1104 | |||
1105 | if (USES_PRIMARY(bond->params.mode) && curr) | ||
1106 | count = sprintf(buf, "%s\n", curr->dev->name) + 1; | ||
1107 | else | ||
1108 | count = sprintf(buf, "\n") + 1; | ||
1109 | return count; | ||
1110 | } | ||
1111 | |||
1112 | static ssize_t bonding_store_active_slave(struct class_device *cd, const char *buf, size_t count) | ||
1113 | { | ||
1114 | int i; | ||
1115 | struct slave *slave; | ||
1116 | struct slave *old_active = NULL; | ||
1117 | struct slave *new_active = NULL; | ||
1118 | struct bonding *bond = to_bond(cd); | ||
1119 | |||
1120 | write_lock_bh(&bond->lock); | ||
1121 | if (!USES_PRIMARY(bond->params.mode)) { | ||
1122 | printk(KERN_INFO DRV_NAME | ||
1123 | ": %s: Unable to change active slave; %s is in mode %d\n", | ||
1124 | bond->dev->name, bond->dev->name, bond->params.mode); | ||
1125 | } else { | ||
1126 | bond_for_each_slave(bond, slave, i) { | ||
1127 | if (strnicmp | ||
1128 | (slave->dev->name, buf, | ||
1129 | strlen(slave->dev->name)) == 0) { | ||
1130 | old_active = bond->curr_active_slave; | ||
1131 | new_active = slave; | ||
1132 | if (new_active && (new_active == old_active)) { | ||
1133 | /* do nothing */ | ||
1134 | printk(KERN_INFO DRV_NAME | ||
1135 | ": %s: %s is already the current active slave.\n", | ||
1136 | bond->dev->name, slave->dev->name); | ||
1137 | goto out; | ||
1138 | } | ||
1139 | else { | ||
1140 | if ((new_active) && | ||
1141 | (old_active) && | ||
1142 | (new_active->link == BOND_LINK_UP) && | ||
1143 | IS_UP(new_active->dev)) { | ||
1144 | printk(KERN_INFO DRV_NAME | ||
1145 | ": %s: Setting %s as active slave.\n", | ||
1146 | bond->dev->name, slave->dev->name); | ||
1147 | bond_change_active_slave(bond, new_active); | ||
1148 | } | ||
1149 | else { | ||
1150 | printk(KERN_INFO DRV_NAME | ||
1151 | ": %s: Could not set %s as active slave; " | ||
1152 | "either %s is down or the link is down.\n", | ||
1153 | bond->dev->name, slave->dev->name, | ||
1154 | slave->dev->name); | ||
1155 | } | ||
1156 | goto out; | ||
1157 | } | ||
1158 | } | ||
1159 | } | ||
1160 | |||
1161 | /* if we got here, then we didn't match the name of any slave */ | ||
1162 | |||
1163 | if (strlen(buf) == 0 || buf[0] == '\n') { | ||
1164 | printk(KERN_INFO DRV_NAME | ||
1165 | ": %s: Setting active slave to None.\n", | ||
1166 | bond->dev->name); | ||
1167 | bond->primary_slave = 0; | ||
1168 | bond_select_active_slave(bond); | ||
1169 | } else { | ||
1170 | printk(KERN_INFO DRV_NAME | ||
1171 | ": %s: Unable to set %.*s as active slave as it is not a slave.\n", | ||
1172 | bond->dev->name, (int)strlen(buf) - 1, buf); | ||
1173 | } | ||
1174 | } | ||
1175 | out: | ||
1176 | write_unlock_bh(&bond->lock); | ||
1177 | return count; | ||
1178 | |||
1179 | } | ||
1180 | static CLASS_DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave); | ||
1181 | |||
1182 | |||
1183 | /* | ||
1184 | * Show link status of the bond interface. | ||
1185 | */ | ||
1186 | static ssize_t bonding_show_mii_status(struct class_device *cd, char *buf) | ||
1187 | { | ||
1188 | struct slave *curr; | ||
1189 | struct bonding *bond = to_bond(cd); | ||
1190 | |||
1191 | read_lock(&bond->curr_slave_lock); | ||
1192 | curr = bond->curr_active_slave; | ||
1193 | read_unlock(&bond->curr_slave_lock); | ||
1194 | |||
1195 | return sprintf(buf, "%s\n", (curr) ? "up" : "down") + 1; | ||
1196 | } | ||
1197 | static CLASS_DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL); | ||
1198 | |||
1199 | |||
1200 | /* | ||
1201 | * Show current 802.3ad aggregator ID. | ||
1202 | */ | ||
1203 | static ssize_t bonding_show_ad_aggregator(struct class_device *cd, char *buf) | ||
1204 | { | ||
1205 | int count = 0; | ||
1206 | struct bonding *bond = to_bond(cd); | ||
1207 | |||
1208 | if (bond->params.mode == BOND_MODE_8023AD) { | ||
1209 | struct ad_info ad_info; | ||
1210 | count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.aggregator_id) + 1; | ||
1211 | } | ||
1212 | else | ||
1213 | count = sprintf(buf, "\n") + 1; | ||
1214 | |||
1215 | return count; | ||
1216 | } | ||
1217 | static CLASS_DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL); | ||
1218 | |||
1219 | |||
1220 | /* | ||
1221 | * Show number of active 802.3ad ports. | ||
1222 | */ | ||
1223 | static ssize_t bonding_show_ad_num_ports(struct class_device *cd, char *buf) | ||
1224 | { | ||
1225 | int count = 0; | ||
1226 | struct bonding *bond = to_bond(cd); | ||
1227 | |||
1228 | if (bond->params.mode == BOND_MODE_8023AD) { | ||
1229 | struct ad_info ad_info; | ||
1230 | count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0: ad_info.ports) + 1; | ||
1231 | } | ||
1232 | else | ||
1233 | count = sprintf(buf, "\n") + 1; | ||
1234 | |||
1235 | return count; | ||
1236 | } | ||
1237 | static CLASS_DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL); | ||
1238 | |||
1239 | |||
1240 | /* | ||
1241 | * Show current 802.3ad actor key. | ||
1242 | */ | ||
1243 | static ssize_t bonding_show_ad_actor_key(struct class_device *cd, char *buf) | ||
1244 | { | ||
1245 | int count = 0; | ||
1246 | struct bonding *bond = to_bond(cd); | ||
1247 | |||
1248 | if (bond->params.mode == BOND_MODE_8023AD) { | ||
1249 | struct ad_info ad_info; | ||
1250 | count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.actor_key) + 1; | ||
1251 | } | ||
1252 | else | ||
1253 | count = sprintf(buf, "\n") + 1; | ||
1254 | |||
1255 | return count; | ||
1256 | } | ||
1257 | static CLASS_DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL); | ||
1258 | |||
1259 | |||
1260 | /* | ||
1261 | * Show current 802.3ad partner key. | ||
1262 | */ | ||
1263 | static ssize_t bonding_show_ad_partner_key(struct class_device *cd, char *buf) | ||
1264 | { | ||
1265 | int count = 0; | ||
1266 | struct bonding *bond = to_bond(cd); | ||
1267 | |||
1268 | if (bond->params.mode == BOND_MODE_8023AD) { | ||
1269 | struct ad_info ad_info; | ||
1270 | count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.partner_key) + 1; | ||
1271 | } | ||
1272 | else | ||
1273 | count = sprintf(buf, "\n") + 1; | ||
1274 | |||
1275 | return count; | ||
1276 | } | ||
1277 | static CLASS_DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL); | ||
1278 | |||
1279 | |||
1280 | /* | ||
1281 | * Show current 802.3ad partner mac. | ||
1282 | */ | ||
1283 | static ssize_t bonding_show_ad_partner_mac(struct class_device *cd, char *buf) | ||
1284 | { | ||
1285 | int count = 0; | ||
1286 | struct bonding *bond = to_bond(cd); | ||
1287 | |||
1288 | if (bond->params.mode == BOND_MODE_8023AD) { | ||
1289 | struct ad_info ad_info; | ||
1290 | if (!bond_3ad_get_active_agg_info(bond, &ad_info)) { | ||
1291 | count = sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
1292 | ad_info.partner_system[0], | ||
1293 | ad_info.partner_system[1], | ||
1294 | ad_info.partner_system[2], | ||
1295 | ad_info.partner_system[3], | ||
1296 | ad_info.partner_system[4], | ||
1297 | ad_info.partner_system[5]) + 1; | ||
1298 | } | ||
1299 | } | ||
1300 | else | ||
1301 | count = sprintf(buf, "\n") + 1; | ||
1302 | |||
1303 | return count; | ||
1304 | } | ||
1305 | static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL); | ||
1306 | |||
1307 | |||
1308 | |||
1309 | static struct attribute *per_bond_attrs[] = { | ||
1310 | &class_device_attr_slaves.attr, | ||
1311 | &class_device_attr_mode.attr, | ||
1312 | &class_device_attr_arp_interval.attr, | ||
1313 | &class_device_attr_arp_ip_target.attr, | ||
1314 | &class_device_attr_downdelay.attr, | ||
1315 | &class_device_attr_updelay.attr, | ||
1316 | &class_device_attr_lacp_rate.attr, | ||
1317 | &class_device_attr_xmit_hash_policy.attr, | ||
1318 | &class_device_attr_miimon.attr, | ||
1319 | &class_device_attr_primary.attr, | ||
1320 | &class_device_attr_use_carrier.attr, | ||
1321 | &class_device_attr_active_slave.attr, | ||
1322 | &class_device_attr_mii_status.attr, | ||
1323 | &class_device_attr_ad_aggregator.attr, | ||
1324 | &class_device_attr_ad_num_ports.attr, | ||
1325 | &class_device_attr_ad_actor_key.attr, | ||
1326 | &class_device_attr_ad_partner_key.attr, | ||
1327 | &class_device_attr_ad_partner_mac.attr, | ||
1328 | NULL, | ||
1329 | }; | ||
1330 | |||
1331 | static struct attribute_group bonding_group = { | ||
1332 | .name = "bonding", | ||
1333 | .attrs = per_bond_attrs, | ||
1334 | }; | ||
1335 | |||
1336 | /* | ||
1337 | * Initialize sysfs. This sets up the bonding_masters file in | ||
1338 | * /sys/class/net. | ||
1339 | */ | ||
1340 | int bond_create_sysfs(void) | ||
1341 | { | ||
1342 | int ret = 0; | ||
1343 | struct bonding *firstbond; | ||
1344 | |||
1345 | init_rwsem(&bonding_rwsem); | ||
1346 | |||
1347 | /* get the netdev class pointer */ | ||
1348 | firstbond = container_of(bond_dev_list.next, struct bonding, bond_list); | ||
1349 | if (!firstbond) | ||
1350 | return -ENODEV; | ||
1351 | |||
1352 | netdev_class = firstbond->dev->class_dev.class; | ||
1353 | if (!netdev_class) | ||
1354 | return -ENODEV; | ||
1355 | |||
1356 | ret = class_create_file(netdev_class, &class_attr_bonding_masters); | ||
1357 | |||
1358 | return ret; | ||
1359 | |||
1360 | } | ||
1361 | |||
1362 | /* | ||
1363 | * Remove /sys/class/net/bonding_masters. | ||
1364 | */ | ||
1365 | void bond_destroy_sysfs(void) | ||
1366 | { | ||
1367 | if (netdev_class) | ||
1368 | class_remove_file(netdev_class, &class_attr_bonding_masters); | ||
1369 | } | ||
1370 | |||
1371 | /* | ||
1372 | * Initialize sysfs for each bond. This sets up and registers | ||
1373 | * the 'bondctl' directory for each individual bond under /sys/class/net. | ||
1374 | */ | ||
1375 | int bond_create_sysfs_entry(struct bonding *bond) | ||
1376 | { | ||
1377 | struct net_device *dev = bond->dev; | ||
1378 | int err; | ||
1379 | |||
1380 | err = sysfs_create_group(&(dev->class_dev.kobj), &bonding_group); | ||
1381 | if (err) { | ||
1382 | printk(KERN_EMERG "eek! didn't create group!\n"); | ||
1383 | } | ||
1384 | |||
1385 | if (expected_refcount < 1) | ||
1386 | expected_refcount = atomic_read(&bond->dev->class_dev.kobj.kref.refcount); | ||
1387 | |||
1388 | return err; | ||
1389 | } | ||
1390 | /* | ||
1391 | * Remove sysfs entries for each bond. | ||
1392 | */ | ||
1393 | void bond_destroy_sysfs_entry(struct bonding *bond) | ||
1394 | { | ||
1395 | struct net_device *dev = bond->dev; | ||
1396 | |||
1397 | sysfs_remove_group(&(dev->class_dev.kobj), &bonding_group); | ||
1398 | } | ||
1399 | |||
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 1433e91db0f7..d6d085480f21 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -29,6 +29,10 @@ | |||
29 | * 2005/05/05 - Jason Gabler <jygabler at lbl dot gov> | 29 | * 2005/05/05 - Jason Gabler <jygabler at lbl dot gov> |
30 | * - added "xmit_policy" kernel parameter for alternate hashing policy | 30 | * - added "xmit_policy" kernel parameter for alternate hashing policy |
31 | * support for mode 2 | 31 | * support for mode 2 |
32 | * | ||
33 | * 2005/09/27 - Mitch Williams <mitch.a.williams at intel dot com> | ||
34 | * Radheka Godse <radheka.godse at intel dot com> | ||
35 | * - Added bonding sysfs interface | ||
32 | */ | 36 | */ |
33 | 37 | ||
34 | #ifndef _LINUX_BONDING_H | 38 | #ifndef _LINUX_BONDING_H |
@@ -37,11 +41,12 @@ | |||
37 | #include <linux/timer.h> | 41 | #include <linux/timer.h> |
38 | #include <linux/proc_fs.h> | 42 | #include <linux/proc_fs.h> |
39 | #include <linux/if_bonding.h> | 43 | #include <linux/if_bonding.h> |
44 | #include <linux/kobject.h> | ||
40 | #include "bond_3ad.h" | 45 | #include "bond_3ad.h" |
41 | #include "bond_alb.h" | 46 | #include "bond_alb.h" |
42 | 47 | ||
43 | #define DRV_VERSION "2.6.5" | 48 | #define DRV_VERSION "3.0.0" |
44 | #define DRV_RELDATE "November 4, 2005" | 49 | #define DRV_RELDATE "November 8, 2005" |
45 | #define DRV_NAME "bonding" | 50 | #define DRV_NAME "bonding" |
46 | #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" | 51 | #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" |
47 | 52 | ||
@@ -152,6 +157,11 @@ struct bond_params { | |||
152 | u32 arp_targets[BOND_MAX_ARP_TARGETS]; | 157 | u32 arp_targets[BOND_MAX_ARP_TARGETS]; |
153 | }; | 158 | }; |
154 | 159 | ||
160 | struct bond_parm_tbl { | ||
161 | char *modename; | ||
162 | int mode; | ||
163 | }; | ||
164 | |||
155 | struct vlan_entry { | 165 | struct vlan_entry { |
156 | struct list_head vlan_list; | 166 | struct list_head vlan_list; |
157 | u32 vlan_ip; | 167 | u32 vlan_ip; |
@@ -159,7 +169,7 @@ struct vlan_entry { | |||
159 | }; | 169 | }; |
160 | 170 | ||
161 | struct slave { | 171 | struct slave { |
162 | struct net_device *dev; /* first - usefull for panic debug */ | 172 | struct net_device *dev; /* first - useful for panic debug */ |
163 | struct slave *next; | 173 | struct slave *next; |
164 | struct slave *prev; | 174 | struct slave *prev; |
165 | s16 delay; | 175 | s16 delay; |
@@ -185,7 +195,7 @@ struct slave { | |||
185 | * beforehand. | 195 | * beforehand. |
186 | */ | 196 | */ |
187 | struct bonding { | 197 | struct bonding { |
188 | struct net_device *dev; /* first - usefull for panic debug */ | 198 | struct net_device *dev; /* first - useful for panic debug */ |
189 | struct slave *first_slave; | 199 | struct slave *first_slave; |
190 | struct slave *curr_active_slave; | 200 | struct slave *curr_active_slave; |
191 | struct slave *current_arp_slave; | 201 | struct slave *current_arp_slave; |
@@ -255,6 +265,25 @@ extern inline void bond_set_slave_active_flags(struct slave *slave) | |||
255 | 265 | ||
256 | struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); | 266 | struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); |
257 | int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); | 267 | int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); |
268 | int bond_create(char *name, struct bond_params *params, struct bonding **newbond); | ||
269 | void bond_deinit(struct net_device *bond_dev); | ||
270 | int bond_create_sysfs(void); | ||
271 | void bond_destroy_sysfs(void); | ||
272 | void bond_destroy_sysfs_entry(struct bonding *bond); | ||
273 | int bond_create_sysfs_entry(struct bonding *bond); | ||
274 | int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave); | ||
275 | void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave); | ||
276 | int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev); | ||
277 | int bond_release(struct net_device *bond_dev, struct net_device *slave_dev); | ||
278 | int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev); | ||
279 | void bond_mii_monitor(struct net_device *bond_dev); | ||
280 | void bond_loadbalance_arp_mon(struct net_device *bond_dev); | ||
281 | void bond_activebackup_arp_mon(struct net_device *bond_dev); | ||
282 | void bond_set_mode_ops(struct bonding *bond, int mode); | ||
283 | int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl); | ||
284 | const char *bond_mode_name(int mode); | ||
285 | void bond_select_active_slave(struct bonding *bond); | ||
286 | void bond_change_active_slave(struct bonding *bond, struct slave *new_active); | ||
258 | 287 | ||
259 | #endif /* _LINUX_BONDING_H */ | 288 | #endif /* _LINUX_BONDING_H */ |
260 | 289 | ||
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index e3a329539f1c..0f030b73cbb3 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Based on 8260_io/fcc_enet.c | 6 | * Based on 8260_io/fcc_enet.c |
7 | * | 7 | * |
8 | * Author: Andy Fleming | 8 | * Author: Andy Fleming |
9 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 9 | * Maintainer: Kumar Gala |
10 | * | 10 | * |
11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
12 | * | 12 | * |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 220084e53341..5065ba82cb76 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * Based on 8260_io/fcc_enet.c | 6 | * Based on 8260_io/fcc_enet.c |
7 | * | 7 | * |
8 | * Author: Andy Fleming | 8 | * Author: Andy Fleming |
9 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 9 | * Maintainer: Kumar Gala |
10 | * | 10 | * |
11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 11 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
12 | * | 12 | * |
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 5a2d810ce575..cfa3cd7c91a0 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Based on e1000 ethtool support | 6 | * Based on e1000 ethtool support |
7 | * | 7 | * |
8 | * Author: Andy Fleming | 8 | * Author: Andy Fleming |
9 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 9 | * Maintainer: Kumar Gala |
10 | * | 10 | * |
11 | * Copyright (c) 2003,2004 Freescale Semiconductor, Inc. | 11 | * Copyright (c) 2003,2004 Freescale Semiconductor, Inc. |
12 | * | 12 | * |
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 9544279e8bcd..04a462c2a5b7 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Provides Bus interface for MIIM regs | 5 | * Provides Bus interface for MIIM regs |
6 | * | 6 | * |
7 | * Author: Andy Fleming | 7 | * Author: Andy Fleming |
8 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 8 | * Maintainer: Kumar Gala |
9 | * | 9 | * |
10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
11 | * | 11 | * |
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h index 56e5665d5c9b..e85eb216fb5b 100644 --- a/drivers/net/gianfar_mii.h +++ b/drivers/net/gianfar_mii.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * Driver for the MDIO bus controller in the Gianfar register space | 5 | * Driver for the MDIO bus controller in the Gianfar register space |
6 | * | 6 | * |
7 | * Author: Andy Fleming | 7 | * Author: Andy Fleming |
8 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | 8 | * Maintainer: Kumar Gala |
9 | * | 9 | * |
10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. | 10 | * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. |
11 | * | 11 | * |
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c index 9bf34681d3df..2e7882eb7d6f 100644 --- a/drivers/net/irda/ali-ircc.c +++ b/drivers/net/irda/ali-ircc.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/byteorder.h> | 40 | #include <asm/byteorder.h> |
41 | 41 | ||
42 | #include <linux/pm.h> | 42 | #include <linux/pm.h> |
43 | #include <linux/pm_legacy.h> | ||
43 | 44 | ||
44 | #include <net/irda/wrapper.h> | 45 | #include <net/irda/wrapper.h> |
45 | #include <net/irda/irda.h> | 46 | #include <net/irda/irda.h> |
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 805714ec9a8a..ee717d0e939e 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <asm/byteorder.h> | 59 | #include <asm/byteorder.h> |
60 | 60 | ||
61 | #include <linux/pm.h> | 61 | #include <linux/pm.h> |
62 | #include <linux/pm_legacy.h> | ||
62 | 63 | ||
63 | #include <net/irda/wrapper.h> | 64 | #include <net/irda/wrapper.h> |
64 | #include <net/irda/irda.h> | 65 | #include <net/irda/irda.h> |
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 1d4d88680db1..3d95fa20cd88 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux. | 1 | /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux. |
2 | Copyright 1999 Silicon Integrated System Corporation | 2 | Copyright 1999 Silicon Integrated System Corporation |
3 | Revision: 1.08.08 Jan. 22 2005 | 3 | Revision: 1.08.09 Sep. 19 2005 |
4 | 4 | ||
5 | Modified from the driver which is originally written by Donald Becker. | 5 | Modified from the driver which is originally written by Donald Becker. |
6 | 6 | ||
@@ -17,6 +17,7 @@ | |||
17 | SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution, | 17 | SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution, |
18 | preliminary Rev. 1.0 Jan. 18, 1998 | 18 | preliminary Rev. 1.0 Jan. 18, 1998 |
19 | 19 | ||
20 | Rev 1.08.09 Sep. 19 2005 Daniele Venzano add Wake on LAN support | ||
20 | Rev 1.08.08 Jan. 22 2005 Daniele Venzano use netif_msg for debugging messages | 21 | Rev 1.08.08 Jan. 22 2005 Daniele Venzano use netif_msg for debugging messages |
21 | Rev 1.08.07 Nov. 2 2003 Daniele Venzano <webvenza@libero.it> add suspend/resume support | 22 | Rev 1.08.07 Nov. 2 2003 Daniele Venzano <webvenza@libero.it> add suspend/resume support |
22 | Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support | 23 | Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support |
@@ -76,7 +77,7 @@ | |||
76 | #include "sis900.h" | 77 | #include "sis900.h" |
77 | 78 | ||
78 | #define SIS900_MODULE_NAME "sis900" | 79 | #define SIS900_MODULE_NAME "sis900" |
79 | #define SIS900_DRV_VERSION "v1.08.08 Jan. 22 2005" | 80 | #define SIS900_DRV_VERSION "v1.08.09 Sep. 19 2005" |
80 | 81 | ||
81 | static char version[] __devinitdata = | 82 | static char version[] __devinitdata = |
82 | KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n"; | 83 | KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n"; |
@@ -538,6 +539,11 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev, | |||
538 | printk("%2.2x:", (u8)net_dev->dev_addr[i]); | 539 | printk("%2.2x:", (u8)net_dev->dev_addr[i]); |
539 | printk("%2.2x.\n", net_dev->dev_addr[i]); | 540 | printk("%2.2x.\n", net_dev->dev_addr[i]); |
540 | 541 | ||
542 | /* Detect Wake on Lan support */ | ||
543 | ret = inl(CFGPMC & PMESP); | ||
544 | if (netif_msg_probe(sis_priv) && (ret & PME_D3C) == 0) | ||
545 | printk(KERN_INFO "%s: Wake on LAN only available from suspend to RAM.", net_dev->name); | ||
546 | |||
541 | return 0; | 547 | return 0; |
542 | 548 | ||
543 | err_unmap_rx: | 549 | err_unmap_rx: |
@@ -2015,6 +2021,67 @@ static int sis900_nway_reset(struct net_device *net_dev) | |||
2015 | return mii_nway_restart(&sis_priv->mii_info); | 2021 | return mii_nway_restart(&sis_priv->mii_info); |
2016 | } | 2022 | } |
2017 | 2023 | ||
2024 | /** | ||
2025 | * sis900_set_wol - Set up Wake on Lan registers | ||
2026 | * @net_dev: the net device to probe | ||
2027 | * @wol: container for info passed to the driver | ||
2028 | * | ||
2029 | * Process ethtool command "wol" to setup wake on lan features. | ||
2030 | * SiS900 supports sending WoL events if a correct packet is received, | ||
2031 | * but there is no simple way to filter them to only a subset (broadcast, | ||
2032 | * multicast, unicast or arp). | ||
2033 | */ | ||
2034 | |||
2035 | static int sis900_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol) | ||
2036 | { | ||
2037 | struct sis900_private *sis_priv = net_dev->priv; | ||
2038 | long pmctrl_addr = net_dev->base_addr + pmctrl; | ||
2039 | u32 cfgpmcsr = 0, pmctrl_bits = 0; | ||
2040 | |||
2041 | if (wol->wolopts == 0) { | ||
2042 | pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr); | ||
2043 | cfgpmcsr |= ~PME_EN; | ||
2044 | pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr); | ||
2045 | outl(pmctrl_bits, pmctrl_addr); | ||
2046 | if (netif_msg_wol(sis_priv)) | ||
2047 | printk(KERN_DEBUG "%s: Wake on LAN disabled\n", net_dev->name); | ||
2048 | return 0; | ||
2049 | } | ||
2050 | |||
2051 | if (wol->wolopts & (WAKE_MAGICSECURE | WAKE_UCAST | WAKE_MCAST | ||
2052 | | WAKE_BCAST | WAKE_ARP)) | ||
2053 | return -EINVAL; | ||
2054 | |||
2055 | if (wol->wolopts & WAKE_MAGIC) | ||
2056 | pmctrl_bits |= MAGICPKT; | ||
2057 | if (wol->wolopts & WAKE_PHY) | ||
2058 | pmctrl_bits |= LINKON; | ||
2059 | |||
2060 | outl(pmctrl_bits, pmctrl_addr); | ||
2061 | |||
2062 | pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr); | ||
2063 | cfgpmcsr |= PME_EN; | ||
2064 | pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr); | ||
2065 | if (netif_msg_wol(sis_priv)) | ||
2066 | printk(KERN_DEBUG "%s: Wake on LAN enabled\n", net_dev->name); | ||
2067 | |||
2068 | return 0; | ||
2069 | } | ||
2070 | |||
2071 | static void sis900_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol) | ||
2072 | { | ||
2073 | long pmctrl_addr = net_dev->base_addr + pmctrl; | ||
2074 | u32 pmctrl_bits; | ||
2075 | |||
2076 | pmctrl_bits = inl(pmctrl_addr); | ||
2077 | if (pmctrl_bits & MAGICPKT) | ||
2078 | wol->wolopts |= WAKE_MAGIC; | ||
2079 | if (pmctrl_bits & LINKON) | ||
2080 | wol->wolopts |= WAKE_PHY; | ||
2081 | |||
2082 | wol->supported = (WAKE_PHY | WAKE_MAGIC); | ||
2083 | } | ||
2084 | |||
2018 | static struct ethtool_ops sis900_ethtool_ops = { | 2085 | static struct ethtool_ops sis900_ethtool_ops = { |
2019 | .get_drvinfo = sis900_get_drvinfo, | 2086 | .get_drvinfo = sis900_get_drvinfo, |
2020 | .get_msglevel = sis900_get_msglevel, | 2087 | .get_msglevel = sis900_get_msglevel, |
@@ -2023,6 +2090,8 @@ static struct ethtool_ops sis900_ethtool_ops = { | |||
2023 | .get_settings = sis900_get_settings, | 2090 | .get_settings = sis900_get_settings, |
2024 | .set_settings = sis900_set_settings, | 2091 | .set_settings = sis900_set_settings, |
2025 | .nway_reset = sis900_nway_reset, | 2092 | .nway_reset = sis900_nway_reset, |
2093 | .get_wol = sis900_get_wol, | ||
2094 | .set_wol = sis900_set_wol | ||
2026 | }; | 2095 | }; |
2027 | 2096 | ||
2028 | /** | 2097 | /** |
diff --git a/drivers/net/sis900.h b/drivers/net/sis900.h index de3c06735d15..4233ea55670f 100644 --- a/drivers/net/sis900.h +++ b/drivers/net/sis900.h | |||
@@ -33,6 +33,7 @@ enum sis900_registers { | |||
33 | rxcfg=0x34, //Receive Configuration Register | 33 | rxcfg=0x34, //Receive Configuration Register |
34 | flctrl=0x38, //Flow Control Register | 34 | flctrl=0x38, //Flow Control Register |
35 | rxlen=0x3c, //Receive Packet Length Register | 35 | rxlen=0x3c, //Receive Packet Length Register |
36 | cfgpmcsr=0x44, //Configuration Power Management Control/Status Register | ||
36 | rfcr=0x48, //Receive Filter Control Register | 37 | rfcr=0x48, //Receive Filter Control Register |
37 | rfdr=0x4C, //Receive Filter Data Register | 38 | rfdr=0x4C, //Receive Filter Data Register |
38 | pmctrl=0xB0, //Power Management Control Register | 39 | pmctrl=0xB0, //Power Management Control Register |
@@ -140,6 +141,50 @@ enum sis96x_eeprom_command { | |||
140 | EEREQ = 0x00000400, EEDONE = 0x00000200, EEGNT = 0x00000100 | 141 | EEREQ = 0x00000400, EEDONE = 0x00000200, EEGNT = 0x00000100 |
141 | }; | 142 | }; |
142 | 143 | ||
144 | /* PCI Registers */ | ||
145 | enum sis900_pci_registers { | ||
146 | CFGPMC = 0x40, | ||
147 | CFGPMCSR = 0x44 | ||
148 | }; | ||
149 | |||
150 | /* Power management capabilities bits */ | ||
151 | enum sis900_cfgpmc_register_bits { | ||
152 | PMVER = 0x00070000, | ||
153 | DSI = 0x00100000, | ||
154 | PMESP = 0xf8000000 | ||
155 | }; | ||
156 | |||
157 | enum sis900_pmesp_bits { | ||
158 | PME_D0 = 0x1, | ||
159 | PME_D1 = 0x2, | ||
160 | PME_D2 = 0x4, | ||
161 | PME_D3H = 0x8, | ||
162 | PME_D3C = 0x10 | ||
163 | }; | ||
164 | |||
165 | /* Power management control/status bits */ | ||
166 | enum sis900_cfgpmcsr_register_bits { | ||
167 | PMESTS = 0x00004000, | ||
168 | PME_EN = 0x00000100, // Power management enable | ||
169 | PWR_STA = 0x00000003 // Current power state | ||
170 | }; | ||
171 | |||
172 | /* Wake-on-LAN support. */ | ||
173 | enum sis900_power_management_control_register_bits { | ||
174 | LINKLOSS = 0x00000001, | ||
175 | LINKON = 0x00000002, | ||
176 | MAGICPKT = 0x00000400, | ||
177 | ALGORITHM = 0x00000800, | ||
178 | FRM1EN = 0x00100000, | ||
179 | FRM2EN = 0x00200000, | ||
180 | FRM3EN = 0x00400000, | ||
181 | FRM1ACS = 0x01000000, | ||
182 | FRM2ACS = 0x02000000, | ||
183 | FRM3ACS = 0x04000000, | ||
184 | WAKEALL = 0x40000000, | ||
185 | GATECLK = 0x80000000 | ||
186 | }; | ||
187 | |||
143 | /* Management Data I/O (mdio) frame */ | 188 | /* Management Data I/O (mdio) frame */ |
144 | #define MIIread 0x6000 | 189 | #define MIIread 0x6000 |
145 | #define MIIwrite 0x5002 | 190 | #define MIIwrite 0x5002 |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c new file mode 100644 index 000000000000..9f89000e5ad5 --- /dev/null +++ b/drivers/net/sky2.c | |||
@@ -0,0 +1,3039 @@ | |||
1 | /* | ||
2 | * New driver for Marvell Yukon 2 chipset. | ||
3 | * Based on earlier sk98lin, and skge driver. | ||
4 | * | ||
5 | * This driver intentionally does not support all the features | ||
6 | * of the original driver such as link fail-over and link management because | ||
7 | * those should be done at higher levels. | ||
8 | * | ||
9 | * Copyright (C) 2005 Stephen Hemminger <shemminger@osdl.org> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | /* | ||
27 | * TODO | ||
28 | * - coalescing setting? | ||
29 | * | ||
30 | * TOTEST | ||
31 | * - speed setting | ||
32 | * - suspend/resume | ||
33 | */ | ||
34 | |||
35 | #include <linux/config.h> | ||
36 | #include <linux/crc32.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/version.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/netdevice.h> | ||
41 | #include <linux/dma-mapping.h> | ||
42 | #include <linux/etherdevice.h> | ||
43 | #include <linux/ethtool.h> | ||
44 | #include <linux/pci.h> | ||
45 | #include <linux/ip.h> | ||
46 | #include <linux/tcp.h> | ||
47 | #include <linux/in.h> | ||
48 | #include <linux/delay.h> | ||
49 | #include <linux/if_vlan.h> | ||
50 | |||
51 | #include <asm/irq.h> | ||
52 | |||
53 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) | ||
54 | #define SKY2_VLAN_TAG_USED 1 | ||
55 | #endif | ||
56 | |||
57 | #include "sky2.h" | ||
58 | |||
59 | #define DRV_NAME "sky2" | ||
60 | #define DRV_VERSION "0.7" | ||
61 | #define PFX DRV_NAME " " | ||
62 | |||
63 | /* | ||
64 | * The Yukon II chipset takes 64 bit command blocks (called list elements) | ||
65 | * that are organized into three (receive, transmit, status) different rings | ||
66 | * similar to Tigon3. A transmit can require several elements; | ||
67 | * a receive requires one (or two if using 64 bit dma). | ||
68 | */ | ||
69 | |||
70 | #ifdef CONFIG_SKY2_EC_A1 | ||
71 | #define is_ec_a1(hw) \ | ||
72 | ((hw)->chip_id == CHIP_ID_YUKON_EC && \ | ||
73 | (hw)->chip_rev == CHIP_REV_YU_EC_A1) | ||
74 | #else | ||
75 | #define is_ec_a1(hw) 0 | ||
76 | #endif | ||
77 | |||
78 | #define RX_LE_SIZE 256 | ||
79 | #define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le)) | ||
80 | #define RX_MAX_PENDING (RX_LE_SIZE/2 - 2) | ||
81 | #define RX_DEF_PENDING 128 | ||
82 | #define RX_COPY_THRESHOLD 256 | ||
83 | |||
84 | #define TX_RING_SIZE 512 | ||
85 | #define TX_DEF_PENDING (TX_RING_SIZE - 1) | ||
86 | #define TX_MIN_PENDING 64 | ||
87 | #define MAX_SKB_TX_LE (4 + 2*MAX_SKB_FRAGS) | ||
88 | |||
89 | #define STATUS_RING_SIZE 2048 /* 2 ports * (TX + 2*RX) */ | ||
90 | #define STATUS_LE_BYTES (STATUS_RING_SIZE*sizeof(struct sky2_status_le)) | ||
91 | #define ETH_JUMBO_MTU 9000 | ||
92 | #define TX_WATCHDOG (5 * HZ) | ||
93 | #define NAPI_WEIGHT 64 | ||
94 | #define PHY_RETRIES 1000 | ||
95 | |||
96 | static const u32 default_msg = | ||
97 | NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | ||
98 | | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR | ||
99 | | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN | NETIF_MSG_INTR; | ||
100 | |||
101 | static int debug = -1; /* defaults above */ | ||
102 | module_param(debug, int, 0); | ||
103 | MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); | ||
104 | |||
105 | static const struct pci_device_id sky2_id_table[] = { | ||
106 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, | ||
107 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, | ||
108 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, | ||
109 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, | ||
110 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, | ||
111 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, | ||
112 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, | ||
113 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4343) }, | ||
114 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4344) }, | ||
115 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4345) }, | ||
116 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4346) }, | ||
117 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4347) }, | ||
118 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) }, | ||
119 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, | ||
120 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, | ||
121 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, | ||
122 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, | ||
123 | { 0 } | ||
124 | }; | ||
125 | |||
126 | MODULE_DEVICE_TABLE(pci, sky2_id_table); | ||
127 | |||
128 | /* Avoid conditionals by using array */ | ||
129 | static const unsigned txqaddr[] = { Q_XA1, Q_XA2 }; | ||
130 | static const unsigned rxqaddr[] = { Q_R1, Q_R2 }; | ||
131 | |||
132 | static const char *yukon_name[] = { | ||
133 | [CHIP_ID_YUKON_LITE - CHIP_ID_YUKON] = "Lite", /* 0xb0 */ | ||
134 | [CHIP_ID_YUKON_LP - CHIP_ID_YUKON] = "LP", /* 0xb2 */ | ||
135 | [CHIP_ID_YUKON_XL - CHIP_ID_YUKON] = "XL", /* 0xb3 */ | ||
136 | |||
137 | [CHIP_ID_YUKON_EC - CHIP_ID_YUKON] = "EC", /* 0xb6 */ | ||
138 | [CHIP_ID_YUKON_FE - CHIP_ID_YUKON] = "FE", /* 0xb7 */ | ||
139 | }; | ||
140 | |||
141 | |||
142 | /* Access to external PHY */ | ||
143 | static void gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | gma_write16(hw, port, GM_SMI_DATA, val); | ||
148 | gma_write16(hw, port, GM_SMI_CTRL, | ||
149 | GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg)); | ||
150 | |||
151 | for (i = 0; i < PHY_RETRIES; i++) { | ||
152 | if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) | ||
153 | return; | ||
154 | udelay(1); | ||
155 | } | ||
156 | printk(KERN_WARNING PFX "%s: phy write timeout\n", hw->dev[port]->name); | ||
157 | } | ||
158 | |||
159 | static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) | ||
160 | { | ||
161 | int i; | ||
162 | |||
163 | gma_write16(hw, port, GM_SMI_CTRL, GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | ||
164 | | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); | ||
165 | |||
166 | for (i = 0; i < PHY_RETRIES; i++) { | ||
167 | if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) | ||
168 | goto ready; | ||
169 | udelay(1); | ||
170 | } | ||
171 | |||
172 | printk(KERN_WARNING PFX "%s: phy read timeout\n", hw->dev[port]->name); | ||
173 | ready: | ||
174 | return gma_read16(hw, port, GM_SMI_DATA); | ||
175 | } | ||
176 | |||
177 | static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) | ||
178 | { | ||
179 | u16 power_control; | ||
180 | u32 reg1; | ||
181 | int vaux; | ||
182 | int ret = 0; | ||
183 | |||
184 | pr_debug("sky2_set_power_state %d\n", state); | ||
185 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
186 | |||
187 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control); | ||
188 | vaux = (sky2_read8(hw, B0_CTST) & Y2_VAUX_AVAIL) && | ||
189 | (power_control & PCI_PM_CAP_PME_D3cold); | ||
190 | |||
191 | pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control); | ||
192 | |||
193 | power_control |= PCI_PM_CTRL_PME_STATUS; | ||
194 | power_control &= ~(PCI_PM_CTRL_STATE_MASK); | ||
195 | |||
196 | switch (state) { | ||
197 | case PCI_D0: | ||
198 | /* switch power to VCC (WA for VAUX problem) */ | ||
199 | sky2_write8(hw, B0_POWER_CTRL, | ||
200 | PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); | ||
201 | |||
202 | /* disable Core Clock Division, */ | ||
203 | sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); | ||
204 | |||
205 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | ||
206 | /* enable bits are inverted */ | ||
207 | sky2_write8(hw, B2_Y2_CLK_GATE, | ||
208 | Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | | ||
209 | Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | | ||
210 | Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); | ||
211 | else | ||
212 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | ||
213 | |||
214 | /* Turn off phy power saving */ | ||
215 | pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®1); | ||
216 | reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); | ||
217 | |||
218 | /* looks like this XL is back asswards .. */ | ||
219 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) { | ||
220 | reg1 |= PCI_Y2_PHY1_COMA; | ||
221 | if (hw->ports > 1) | ||
222 | reg1 |= PCI_Y2_PHY2_COMA; | ||
223 | } | ||
224 | pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1); | ||
225 | break; | ||
226 | |||
227 | case PCI_D3hot: | ||
228 | case PCI_D3cold: | ||
229 | /* Turn on phy power saving */ | ||
230 | pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®1); | ||
231 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | ||
232 | reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); | ||
233 | else | ||
234 | reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); | ||
235 | pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1); | ||
236 | |||
237 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | ||
238 | sky2_write8(hw, B2_Y2_CLK_GATE, 0); | ||
239 | else | ||
240 | /* enable bits are inverted */ | ||
241 | sky2_write8(hw, B2_Y2_CLK_GATE, | ||
242 | Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | | ||
243 | Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | | ||
244 | Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS); | ||
245 | |||
246 | /* switch power to VAUX */ | ||
247 | if (vaux && state != PCI_D3cold) | ||
248 | sky2_write8(hw, B0_POWER_CTRL, | ||
249 | (PC_VAUX_ENA | PC_VCC_ENA | | ||
250 | PC_VAUX_ON | PC_VCC_OFF)); | ||
251 | break; | ||
252 | default: | ||
253 | printk(KERN_ERR PFX "Unknown power state %d\n", state); | ||
254 | ret = -1; | ||
255 | } | ||
256 | |||
257 | pci_write_config_byte(hw->pdev, hw->pm_cap + PCI_PM_CTRL, power_control); | ||
258 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | ||
259 | return ret; | ||
260 | } | ||
261 | |||
262 | static void sky2_phy_reset(struct sky2_hw *hw, unsigned port) | ||
263 | { | ||
264 | u16 reg; | ||
265 | |||
266 | /* disable all GMAC IRQ's */ | ||
267 | sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); | ||
268 | /* disable PHY IRQs */ | ||
269 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); | ||
270 | |||
271 | gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */ | ||
272 | gma_write16(hw, port, GM_MC_ADDR_H2, 0); | ||
273 | gma_write16(hw, port, GM_MC_ADDR_H3, 0); | ||
274 | gma_write16(hw, port, GM_MC_ADDR_H4, 0); | ||
275 | |||
276 | reg = gma_read16(hw, port, GM_RX_CTRL); | ||
277 | reg |= GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA; | ||
278 | gma_write16(hw, port, GM_RX_CTRL, reg); | ||
279 | } | ||
280 | |||
281 | static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | ||
282 | { | ||
283 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); | ||
284 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover; | ||
285 | |||
286 | if (sky2->autoneg == AUTONEG_ENABLE && hw->chip_id != CHIP_ID_YUKON_XL) { | ||
287 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); | ||
288 | |||
289 | ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | | ||
290 | PHY_M_EC_MAC_S_MSK); | ||
291 | ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); | ||
292 | |||
293 | if (hw->chip_id == CHIP_ID_YUKON_EC) | ||
294 | ectrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA; | ||
295 | else | ||
296 | ectrl |= PHY_M_EC_M_DSC(2) | PHY_M_EC_S_DSC(3); | ||
297 | |||
298 | gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl); | ||
299 | } | ||
300 | |||
301 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | ||
302 | if (hw->copper) { | ||
303 | if (hw->chip_id == CHIP_ID_YUKON_FE) { | ||
304 | /* enable automatic crossover */ | ||
305 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; | ||
306 | } else { | ||
307 | /* disable energy detect */ | ||
308 | ctrl &= ~PHY_M_PC_EN_DET_MSK; | ||
309 | |||
310 | /* enable automatic crossover */ | ||
311 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); | ||
312 | |||
313 | if (sky2->autoneg == AUTONEG_ENABLE && | ||
314 | hw->chip_id == CHIP_ID_YUKON_XL) { | ||
315 | ctrl &= ~PHY_M_PC_DSC_MSK; | ||
316 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; | ||
317 | } | ||
318 | } | ||
319 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); | ||
320 | } else { | ||
321 | /* workaround for deviation #4.88 (CRC errors) */ | ||
322 | /* disable Automatic Crossover */ | ||
323 | |||
324 | ctrl &= ~PHY_M_PC_MDIX_MSK; | ||
325 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); | ||
326 | |||
327 | if (hw->chip_id == CHIP_ID_YUKON_XL) { | ||
328 | /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */ | ||
329 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2); | ||
330 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | ||
331 | ctrl &= ~PHY_M_MAC_MD_MSK; | ||
332 | ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX); | ||
333 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); | ||
334 | |||
335 | /* select page 1 to access Fiber registers */ | ||
336 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 1); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); | ||
341 | if (sky2->autoneg == AUTONEG_DISABLE) | ||
342 | ctrl &= ~PHY_CT_ANE; | ||
343 | else | ||
344 | ctrl |= PHY_CT_ANE; | ||
345 | |||
346 | ctrl |= PHY_CT_RESET; | ||
347 | gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); | ||
348 | |||
349 | ctrl = 0; | ||
350 | ct1000 = 0; | ||
351 | adv = PHY_AN_CSMA; | ||
352 | |||
353 | if (sky2->autoneg == AUTONEG_ENABLE) { | ||
354 | if (hw->copper) { | ||
355 | if (sky2->advertising & ADVERTISED_1000baseT_Full) | ||
356 | ct1000 |= PHY_M_1000C_AFD; | ||
357 | if (sky2->advertising & ADVERTISED_1000baseT_Half) | ||
358 | ct1000 |= PHY_M_1000C_AHD; | ||
359 | if (sky2->advertising & ADVERTISED_100baseT_Full) | ||
360 | adv |= PHY_M_AN_100_FD; | ||
361 | if (sky2->advertising & ADVERTISED_100baseT_Half) | ||
362 | adv |= PHY_M_AN_100_HD; | ||
363 | if (sky2->advertising & ADVERTISED_10baseT_Full) | ||
364 | adv |= PHY_M_AN_10_FD; | ||
365 | if (sky2->advertising & ADVERTISED_10baseT_Half) | ||
366 | adv |= PHY_M_AN_10_HD; | ||
367 | } else /* special defines for FIBER (88E1011S only) */ | ||
368 | adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; | ||
369 | |||
370 | /* Set Flow-control capabilities */ | ||
371 | if (sky2->tx_pause && sky2->rx_pause) | ||
372 | adv |= PHY_AN_PAUSE_CAP; /* symmetric */ | ||
373 | else if (sky2->rx_pause && !sky2->tx_pause) | ||
374 | adv |= PHY_AN_PAUSE_ASYM | PHY_AN_PAUSE_CAP; | ||
375 | else if (!sky2->rx_pause && sky2->tx_pause) | ||
376 | adv |= PHY_AN_PAUSE_ASYM; /* local */ | ||
377 | |||
378 | /* Restart Auto-negotiation */ | ||
379 | ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG; | ||
380 | } else { | ||
381 | /* forced speed/duplex settings */ | ||
382 | ct1000 = PHY_M_1000C_MSE; | ||
383 | |||
384 | if (sky2->duplex == DUPLEX_FULL) | ||
385 | ctrl |= PHY_CT_DUP_MD; | ||
386 | |||
387 | switch (sky2->speed) { | ||
388 | case SPEED_1000: | ||
389 | ctrl |= PHY_CT_SP1000; | ||
390 | break; | ||
391 | case SPEED_100: | ||
392 | ctrl |= PHY_CT_SP100; | ||
393 | break; | ||
394 | } | ||
395 | |||
396 | ctrl |= PHY_CT_RESET; | ||
397 | } | ||
398 | |||
399 | if (hw->chip_id != CHIP_ID_YUKON_FE) | ||
400 | gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); | ||
401 | |||
402 | gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); | ||
403 | gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); | ||
404 | |||
405 | /* Setup Phy LED's */ | ||
406 | ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS); | ||
407 | ledover = 0; | ||
408 | |||
409 | switch (hw->chip_id) { | ||
410 | case CHIP_ID_YUKON_FE: | ||
411 | /* on 88E3082 these bits are at 11..9 (shifted left) */ | ||
412 | ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1; | ||
413 | |||
414 | ctrl = gm_phy_read(hw, port, PHY_MARV_FE_LED_PAR); | ||
415 | |||
416 | /* delete ACT LED control bits */ | ||
417 | ctrl &= ~PHY_M_FELP_LED1_MSK; | ||
418 | /* change ACT LED control to blink mode */ | ||
419 | ctrl |= PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL); | ||
420 | gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); | ||
421 | break; | ||
422 | |||
423 | case CHIP_ID_YUKON_XL: | ||
424 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | ||
425 | |||
426 | /* select page 3 to access LED control register */ | ||
427 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | ||
428 | |||
429 | /* set LED Function Control register */ | ||
430 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ | ||
431 | PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */ | ||
432 | PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */ | ||
433 | PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */ | ||
434 | |||
435 | /* set Polarity Control register */ | ||
436 | gm_phy_write(hw, port, PHY_MARV_PHY_STAT, | ||
437 | (PHY_M_POLC_LS1_P_MIX(4) | | ||
438 | PHY_M_POLC_IS0_P_MIX(4) | | ||
439 | PHY_M_POLC_LOS_CTRL(2) | | ||
440 | PHY_M_POLC_INIT_CTRL(2) | | ||
441 | PHY_M_POLC_STA1_CTRL(2) | | ||
442 | PHY_M_POLC_STA0_CTRL(2))); | ||
443 | |||
444 | /* restore page register */ | ||
445 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | ||
446 | break; | ||
447 | |||
448 | default: | ||
449 | /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */ | ||
450 | ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL; | ||
451 | /* turn off the Rx LED (LED_RX) */ | ||
452 | ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); | ||
453 | } | ||
454 | |||
455 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); | ||
456 | |||
457 | if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { | ||
458 | /* turn on 100 Mbps LED (LED_LINK100) */ | ||
459 | ledover |= PHY_M_LED_MO_100(MO_LED_ON); | ||
460 | } | ||
461 | |||
462 | if (ledover) | ||
463 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); | ||
464 | |||
465 | /* Enable phy interrupt on auto-negotiation complete (or link up) */ | ||
466 | if (sky2->autoneg == AUTONEG_ENABLE) | ||
467 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); | ||
468 | else | ||
469 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); | ||
470 | } | ||
471 | |||
472 | static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | ||
473 | { | ||
474 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); | ||
475 | u16 reg; | ||
476 | int i; | ||
477 | const u8 *addr = hw->dev[port]->dev_addr; | ||
478 | |||
479 | sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); | ||
480 | sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); | ||
481 | |||
482 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); | ||
483 | |||
484 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0 && port == 1) { | ||
485 | /* WA DEV_472 -- looks like crossed wires on port 2 */ | ||
486 | /* clear GMAC 1 Control reset */ | ||
487 | sky2_write8(hw, SK_REG(0, GMAC_CTRL), GMC_RST_CLR); | ||
488 | do { | ||
489 | sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_SET); | ||
490 | sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_CLR); | ||
491 | } while (gm_phy_read(hw, 1, PHY_MARV_ID0) != PHY_MARV_ID0_VAL || | ||
492 | gm_phy_read(hw, 1, PHY_MARV_ID1) != PHY_MARV_ID1_Y2 || | ||
493 | gm_phy_read(hw, 1, PHY_MARV_INT_MASK) != 0); | ||
494 | } | ||
495 | |||
496 | if (sky2->autoneg == AUTONEG_DISABLE) { | ||
497 | reg = gma_read16(hw, port, GM_GP_CTRL); | ||
498 | reg |= GM_GPCR_AU_ALL_DIS; | ||
499 | gma_write16(hw, port, GM_GP_CTRL, reg); | ||
500 | gma_read16(hw, port, GM_GP_CTRL); | ||
501 | |||
502 | switch (sky2->speed) { | ||
503 | case SPEED_1000: | ||
504 | reg |= GM_GPCR_SPEED_1000; | ||
505 | /* fallthru */ | ||
506 | case SPEED_100: | ||
507 | reg |= GM_GPCR_SPEED_100; | ||
508 | } | ||
509 | |||
510 | if (sky2->duplex == DUPLEX_FULL) | ||
511 | reg |= GM_GPCR_DUP_FULL; | ||
512 | } else | ||
513 | reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL; | ||
514 | |||
515 | if (!sky2->tx_pause && !sky2->rx_pause) { | ||
516 | sky2_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); | ||
517 | reg |= | ||
518 | GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; | ||
519 | } else if (sky2->tx_pause && !sky2->rx_pause) { | ||
520 | /* disable Rx flow-control */ | ||
521 | reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; | ||
522 | } | ||
523 | |||
524 | gma_write16(hw, port, GM_GP_CTRL, reg); | ||
525 | |||
526 | sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); | ||
527 | |||
528 | spin_lock_bh(&hw->phy_lock); | ||
529 | sky2_phy_init(hw, port); | ||
530 | spin_unlock_bh(&hw->phy_lock); | ||
531 | |||
532 | /* MIB clear */ | ||
533 | reg = gma_read16(hw, port, GM_PHY_ADDR); | ||
534 | gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR); | ||
535 | |||
536 | for (i = 0; i < GM_MIB_CNT_SIZE; i++) | ||
537 | gma_read16(hw, port, GM_MIB_CNT_BASE + 8 * i); | ||
538 | gma_write16(hw, port, GM_PHY_ADDR, reg); | ||
539 | |||
540 | /* transmit control */ | ||
541 | gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF)); | ||
542 | |||
543 | /* receive control reg: unicast + multicast + no FCS */ | ||
544 | gma_write16(hw, port, GM_RX_CTRL, | ||
545 | GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA); | ||
546 | |||
547 | /* transmit flow control */ | ||
548 | gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff); | ||
549 | |||
550 | /* transmit parameter */ | ||
551 | gma_write16(hw, port, GM_TX_PARAM, | ||
552 | TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) | | ||
553 | TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) | | ||
554 | TX_IPG_JAM_DATA(TX_IPG_JAM_DEF) | | ||
555 | TX_BACK_OFF_LIM(TX_BOF_LIM_DEF)); | ||
556 | |||
557 | /* serial mode register */ | ||
558 | reg = DATA_BLIND_VAL(DATA_BLIND_DEF) | | ||
559 | GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); | ||
560 | |||
561 | if (hw->dev[port]->mtu > ETH_DATA_LEN) | ||
562 | reg |= GM_SMOD_JUMBO_ENA; | ||
563 | |||
564 | gma_write16(hw, port, GM_SERIAL_MODE, reg); | ||
565 | |||
566 | /* virtual address for data */ | ||
567 | gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr); | ||
568 | |||
569 | /* physical address: used for pause frames */ | ||
570 | gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr); | ||
571 | |||
572 | /* ignore counter overflows */ | ||
573 | gma_write16(hw, port, GM_TX_IRQ_MSK, 0); | ||
574 | gma_write16(hw, port, GM_RX_IRQ_MSK, 0); | ||
575 | gma_write16(hw, port, GM_TR_IRQ_MSK, 0); | ||
576 | |||
577 | /* Configure Rx MAC FIFO */ | ||
578 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); | ||
579 | sky2_write16(hw, SK_REG(port, RX_GMF_CTRL_T), | ||
580 | GMF_RX_CTRL_DEF); | ||
581 | |||
582 | /* Flush Rx MAC FIFO on any flow control or error */ | ||
583 | reg = GMR_FS_ANY_ERR; | ||
584 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev <= 1) | ||
585 | reg = 0; /* WA dev #4.115 */ | ||
586 | |||
587 | sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), reg); | ||
588 | /* Set threshold to 0xa (64 bytes) | ||
589 | * ASF disabled so no need to do WA dev #4.30 | ||
590 | */ | ||
591 | sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF); | ||
592 | |||
593 | /* Configure Tx MAC FIFO */ | ||
594 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); | ||
595 | sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); | ||
596 | } | ||
597 | |||
598 | static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, size_t len) | ||
599 | { | ||
600 | u32 end; | ||
601 | |||
602 | start /= 8; | ||
603 | len /= 8; | ||
604 | end = start + len - 1; | ||
605 | |||
606 | sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); | ||
607 | sky2_write32(hw, RB_ADDR(q, RB_START), start); | ||
608 | sky2_write32(hw, RB_ADDR(q, RB_END), end); | ||
609 | sky2_write32(hw, RB_ADDR(q, RB_WP), start); | ||
610 | sky2_write32(hw, RB_ADDR(q, RB_RP), start); | ||
611 | |||
612 | if (q == Q_R1 || q == Q_R2) { | ||
613 | u32 rxup, rxlo; | ||
614 | |||
615 | rxlo = len/2; | ||
616 | rxup = rxlo + len/4; | ||
617 | |||
618 | /* Set thresholds on receive queue's */ | ||
619 | sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), rxup); | ||
620 | sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), rxlo); | ||
621 | } else { | ||
622 | /* Enable store & forward on Tx queue's because | ||
623 | * Tx FIFO is only 1K on Yukon | ||
624 | */ | ||
625 | sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD); | ||
626 | } | ||
627 | |||
628 | sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD); | ||
629 | sky2_read8(hw, RB_ADDR(q, RB_CTRL)); | ||
630 | } | ||
631 | |||
632 | /* Setup Bus Memory Interface */ | ||
633 | static void sky2_qset(struct sky2_hw *hw, u16 q, u32 wm) | ||
634 | { | ||
635 | sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_RESET); | ||
636 | sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_OPER_INIT); | ||
637 | sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_FIFO_OP_ON); | ||
638 | sky2_write32(hw, Q_ADDR(q, Q_WM), wm); | ||
639 | } | ||
640 | |||
641 | /* Setup prefetch unit registers. This is the interface between | ||
642 | * hardware and driver list elements | ||
643 | */ | ||
644 | static inline void sky2_prefetch_init(struct sky2_hw *hw, u32 qaddr, | ||
645 | u64 addr, u32 last) | ||
646 | { | ||
647 | sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); | ||
648 | sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_CLR); | ||
649 | sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_HI), addr >> 32); | ||
650 | sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_LO), (u32) addr); | ||
651 | sky2_write16(hw, Y2_QADDR(qaddr, PREF_UNIT_LAST_IDX), last); | ||
652 | sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_OP_ON); | ||
653 | |||
654 | sky2_read32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL)); | ||
655 | } | ||
656 | |||
657 | static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2) | ||
658 | { | ||
659 | struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod; | ||
660 | |||
661 | sky2->tx_prod = (sky2->tx_prod + 1) % TX_RING_SIZE; | ||
662 | return le; | ||
663 | } | ||
664 | |||
665 | /* | ||
666 | * This is a workaround code taken from SysKonnect sk98lin driver | ||
667 | * to deal with chip bug on Yukon EC rev 0 in the wraparound case. | ||
668 | */ | ||
669 | static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, | ||
670 | u16 idx, u16 *last, u16 size) | ||
671 | { | ||
672 | if (is_ec_a1(hw) && idx < *last) { | ||
673 | u16 hwget = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX)); | ||
674 | |||
675 | if (hwget == 0) { | ||
676 | /* Start prefetching again */ | ||
677 | sky2_write8(hw, Y2_QADDR(q, PREF_UNIT_FIFO_WM), 0xe0); | ||
678 | goto setnew; | ||
679 | } | ||
680 | |||
681 | if (hwget == size - 1) { | ||
682 | /* set watermark to one list element */ | ||
683 | sky2_write8(hw, Y2_QADDR(q, PREF_UNIT_FIFO_WM), 8); | ||
684 | |||
685 | /* set put index to first list element */ | ||
686 | sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), 0); | ||
687 | } else /* have hardware go to end of list */ | ||
688 | sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), | ||
689 | size - 1); | ||
690 | } else { | ||
691 | setnew: | ||
692 | sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx); | ||
693 | } | ||
694 | *last = idx; | ||
695 | } | ||
696 | |||
697 | |||
698 | static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) | ||
699 | { | ||
700 | struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put; | ||
701 | sky2->rx_put = (sky2->rx_put + 1) % RX_LE_SIZE; | ||
702 | return le; | ||
703 | } | ||
704 | |||
705 | /* Build description to hardware about buffer */ | ||
706 | static inline void sky2_rx_add(struct sky2_port *sky2, struct ring_info *re) | ||
707 | { | ||
708 | struct sky2_rx_le *le; | ||
709 | u32 hi = (re->mapaddr >> 16) >> 16; | ||
710 | |||
711 | re->idx = sky2->rx_put; | ||
712 | if (sky2->rx_addr64 != hi) { | ||
713 | le = sky2_next_rx(sky2); | ||
714 | le->addr = cpu_to_le32(hi); | ||
715 | le->ctrl = 0; | ||
716 | le->opcode = OP_ADDR64 | HW_OWNER; | ||
717 | sky2->rx_addr64 = hi; | ||
718 | } | ||
719 | |||
720 | le = sky2_next_rx(sky2); | ||
721 | le->addr = cpu_to_le32((u32) re->mapaddr); | ||
722 | le->length = cpu_to_le16(re->maplen); | ||
723 | le->ctrl = 0; | ||
724 | le->opcode = OP_PACKET | HW_OWNER; | ||
725 | } | ||
726 | |||
727 | |||
728 | /* Tell chip where to start receive checksum. | ||
729 | * Actually has two checksums, but set both same to avoid possible byte | ||
730 | * order problems. | ||
731 | */ | ||
732 | static void rx_set_checksum(struct sky2_port *sky2) | ||
733 | { | ||
734 | struct sky2_rx_le *le; | ||
735 | |||
736 | le = sky2_next_rx(sky2); | ||
737 | le->addr = (ETH_HLEN << 16) | ETH_HLEN; | ||
738 | le->ctrl = 0; | ||
739 | le->opcode = OP_TCPSTART | HW_OWNER; | ||
740 | |||
741 | sky2_write32(sky2->hw, | ||
742 | Q_ADDR(rxqaddr[sky2->port], Q_CSR), | ||
743 | sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); | ||
744 | |||
745 | } | ||
746 | |||
747 | /* | ||
748 | * The RX Stop command will not work for Yukon-2 if the BMU does not | ||
749 | * reach the end of packet and since we can't make sure that we have | ||
750 | * incoming data, we must reset the BMU while it is not doing a DMA | ||
751 | * transfer. Since it is possible that the RX path is still active, | ||
752 | * the RX RAM buffer will be stopped first, so any possible incoming | ||
753 | * data will not trigger a DMA. After the RAM buffer is stopped, the | ||
754 | * BMU is polled until any DMA in progress is ended and only then it | ||
755 | * will be reset. | ||
756 | */ | ||
757 | static void sky2_rx_stop(struct sky2_port *sky2) | ||
758 | { | ||
759 | struct sky2_hw *hw = sky2->hw; | ||
760 | unsigned rxq = rxqaddr[sky2->port]; | ||
761 | int i; | ||
762 | |||
763 | /* disable the RAM Buffer receive queue */ | ||
764 | sky2_write8(hw, RB_ADDR(rxq, RB_CTRL), RB_DIS_OP_MD); | ||
765 | |||
766 | for (i = 0; i < 0xffff; i++) | ||
767 | if (sky2_read8(hw, RB_ADDR(rxq, Q_RSL)) | ||
768 | == sky2_read8(hw, RB_ADDR(rxq, Q_RL))) | ||
769 | goto stopped; | ||
770 | |||
771 | printk(KERN_WARNING PFX "%s: receiver stop failed\n", | ||
772 | sky2->netdev->name); | ||
773 | stopped: | ||
774 | sky2_write32(hw, Q_ADDR(rxq, Q_CSR), BMU_RST_SET | BMU_FIFO_RST); | ||
775 | |||
776 | /* reset the Rx prefetch unit */ | ||
777 | sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); | ||
778 | } | ||
779 | |||
780 | /* Clean out receive buffer area, assumes receiver hardware stopped */ | ||
781 | static void sky2_rx_clean(struct sky2_port *sky2) | ||
782 | { | ||
783 | unsigned i; | ||
784 | |||
785 | memset(sky2->rx_le, 0, RX_LE_BYTES); | ||
786 | for (i = 0; i < sky2->rx_pending; i++) { | ||
787 | struct ring_info *re = sky2->rx_ring + i; | ||
788 | |||
789 | if (re->skb) { | ||
790 | pci_unmap_single(sky2->hw->pdev, | ||
791 | re->mapaddr, re->maplen, | ||
792 | PCI_DMA_FROMDEVICE); | ||
793 | kfree_skb(re->skb); | ||
794 | re->skb = NULL; | ||
795 | } | ||
796 | } | ||
797 | } | ||
798 | |||
799 | #ifdef SKY2_VLAN_TAG_USED | ||
800 | static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) | ||
801 | { | ||
802 | struct sky2_port *sky2 = netdev_priv(dev); | ||
803 | struct sky2_hw *hw = sky2->hw; | ||
804 | u16 port = sky2->port; | ||
805 | unsigned long flags; | ||
806 | |||
807 | spin_lock_irqsave(&sky2->tx_lock, flags); | ||
808 | |||
809 | sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON); | ||
810 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON); | ||
811 | sky2->vlgrp = grp; | ||
812 | |||
813 | spin_unlock_irqrestore(&sky2->tx_lock, flags); | ||
814 | } | ||
815 | |||
816 | static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | ||
817 | { | ||
818 | struct sky2_port *sky2 = netdev_priv(dev); | ||
819 | struct sky2_hw *hw = sky2->hw; | ||
820 | u16 port = sky2->port; | ||
821 | unsigned long flags; | ||
822 | |||
823 | spin_lock_irqsave(&sky2->tx_lock, flags); | ||
824 | |||
825 | sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF); | ||
826 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF); | ||
827 | if (sky2->vlgrp) | ||
828 | sky2->vlgrp->vlan_devices[vid] = NULL; | ||
829 | |||
830 | spin_unlock_irqrestore(&sky2->tx_lock, flags); | ||
831 | } | ||
832 | #endif | ||
833 | |||
834 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | ||
835 | static inline unsigned rx_size(const struct sky2_port *sky2) | ||
836 | { | ||
837 | return roundup(sky2->netdev->mtu + ETH_HLEN + 4, 8); | ||
838 | } | ||
839 | |||
840 | /* | ||
841 | * Allocate and setup receiver buffer pool. | ||
842 | * In case of 64 bit dma, there are 2X as many list elements | ||
843 | * available as ring entries | ||
844 | * and need to reserve one list element so we don't wrap around. | ||
845 | * | ||
846 | * It appears the hardware has a bug in the FIFO logic that | ||
847 | * cause it to hang if the FIFO gets overrun and the receive buffer | ||
848 | * is not aligned. This means we can't use skb_reserve to align | ||
849 | * the IP header. | ||
850 | */ | ||
851 | static int sky2_rx_start(struct sky2_port *sky2) | ||
852 | { | ||
853 | struct sky2_hw *hw = sky2->hw; | ||
854 | unsigned size = rx_size(sky2); | ||
855 | unsigned rxq = rxqaddr[sky2->port]; | ||
856 | int i; | ||
857 | |||
858 | sky2->rx_put = sky2->rx_next = 0; | ||
859 | sky2_qset(hw, rxq, is_pciex(hw) ? 0x80 : 0x600); | ||
860 | sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); | ||
861 | |||
862 | rx_set_checksum(sky2); | ||
863 | for (i = 0; i < sky2->rx_pending; i++) { | ||
864 | struct ring_info *re = sky2->rx_ring + i; | ||
865 | |||
866 | re->skb = dev_alloc_skb(size); | ||
867 | if (!re->skb) | ||
868 | goto nomem; | ||
869 | |||
870 | re->mapaddr = pci_map_single(hw->pdev, re->skb->data, | ||
871 | size, PCI_DMA_FROMDEVICE); | ||
872 | re->maplen = size; | ||
873 | sky2_rx_add(sky2, re); | ||
874 | } | ||
875 | |||
876 | /* Tell chip about available buffers */ | ||
877 | sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); | ||
878 | sky2->rx_last_put = sky2_read16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX)); | ||
879 | return 0; | ||
880 | nomem: | ||
881 | sky2_rx_clean(sky2); | ||
882 | return -ENOMEM; | ||
883 | } | ||
884 | |||
885 | /* Bring up network interface. */ | ||
886 | static int sky2_up(struct net_device *dev) | ||
887 | { | ||
888 | struct sky2_port *sky2 = netdev_priv(dev); | ||
889 | struct sky2_hw *hw = sky2->hw; | ||
890 | unsigned port = sky2->port; | ||
891 | u32 ramsize, rxspace; | ||
892 | int err = -ENOMEM; | ||
893 | |||
894 | if (netif_msg_ifup(sky2)) | ||
895 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); | ||
896 | |||
897 | /* must be power of 2 */ | ||
898 | sky2->tx_le = pci_alloc_consistent(hw->pdev, | ||
899 | TX_RING_SIZE * | ||
900 | sizeof(struct sky2_tx_le), | ||
901 | &sky2->tx_le_map); | ||
902 | if (!sky2->tx_le) | ||
903 | goto err_out; | ||
904 | |||
905 | sky2->tx_ring = kzalloc(TX_RING_SIZE * sizeof(struct ring_info), | ||
906 | GFP_KERNEL); | ||
907 | if (!sky2->tx_ring) | ||
908 | goto err_out; | ||
909 | sky2->tx_prod = sky2->tx_cons = 0; | ||
910 | |||
911 | sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES, | ||
912 | &sky2->rx_le_map); | ||
913 | if (!sky2->rx_le) | ||
914 | goto err_out; | ||
915 | memset(sky2->rx_le, 0, RX_LE_BYTES); | ||
916 | |||
917 | sky2->rx_ring = kzalloc(sky2->rx_pending * sizeof(struct ring_info), | ||
918 | GFP_KERNEL); | ||
919 | if (!sky2->rx_ring) | ||
920 | goto err_out; | ||
921 | |||
922 | sky2_mac_init(hw, port); | ||
923 | |||
924 | /* Configure RAM buffers */ | ||
925 | if (hw->chip_id == CHIP_ID_YUKON_FE || | ||
926 | (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == 2)) | ||
927 | ramsize = 4096; | ||
928 | else { | ||
929 | u8 e0 = sky2_read8(hw, B2_E_0); | ||
930 | ramsize = (e0 == 0) ? (128 * 1024) : (e0 * 4096); | ||
931 | } | ||
932 | |||
933 | /* 2/3 for Rx */ | ||
934 | rxspace = (2 * ramsize) / 3; | ||
935 | sky2_ramset(hw, rxqaddr[port], 0, rxspace); | ||
936 | sky2_ramset(hw, txqaddr[port], rxspace, ramsize - rxspace); | ||
937 | |||
938 | /* Make sure SyncQ is disabled */ | ||
939 | sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL), | ||
940 | RB_RST_SET); | ||
941 | |||
942 | sky2_qset(hw, txqaddr[port], 0x600); | ||
943 | sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, | ||
944 | TX_RING_SIZE - 1); | ||
945 | |||
946 | err = sky2_rx_start(sky2); | ||
947 | if (err) | ||
948 | goto err_out; | ||
949 | |||
950 | /* Enable interrupts from phy/mac for port */ | ||
951 | hw->intr_mask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2; | ||
952 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
953 | return 0; | ||
954 | |||
955 | err_out: | ||
956 | if (sky2->rx_le) | ||
957 | pci_free_consistent(hw->pdev, RX_LE_BYTES, | ||
958 | sky2->rx_le, sky2->rx_le_map); | ||
959 | if (sky2->tx_le) | ||
960 | pci_free_consistent(hw->pdev, | ||
961 | TX_RING_SIZE * sizeof(struct sky2_tx_le), | ||
962 | sky2->tx_le, sky2->tx_le_map); | ||
963 | if (sky2->tx_ring) | ||
964 | kfree(sky2->tx_ring); | ||
965 | if (sky2->rx_ring) | ||
966 | kfree(sky2->rx_ring); | ||
967 | |||
968 | return err; | ||
969 | } | ||
970 | |||
971 | /* Modular subtraction in ring */ | ||
972 | static inline int tx_dist(unsigned tail, unsigned head) | ||
973 | { | ||
974 | return (head >= tail ? head : head + TX_RING_SIZE) - tail; | ||
975 | } | ||
976 | |||
977 | /* Number of list elements available for next tx */ | ||
978 | static inline int tx_avail(const struct sky2_port *sky2) | ||
979 | { | ||
980 | return sky2->tx_pending - tx_dist(sky2->tx_cons, sky2->tx_prod); | ||
981 | } | ||
982 | |||
983 | /* Estimate of number of transmit list elements required */ | ||
984 | static inline unsigned tx_le_req(const struct sk_buff *skb) | ||
985 | { | ||
986 | unsigned count; | ||
987 | |||
988 | count = sizeof(dma_addr_t) / sizeof(u32); | ||
989 | count += skb_shinfo(skb)->nr_frags * count; | ||
990 | |||
991 | if (skb_shinfo(skb)->tso_size) | ||
992 | ++count; | ||
993 | |||
994 | if (skb->ip_summed) | ||
995 | ++count; | ||
996 | |||
997 | return count; | ||
998 | } | ||
999 | |||
1000 | /* | ||
1001 | * Put one packet in ring for transmit. | ||
1002 | * A single packet can generate multiple list elements, and | ||
1003 | * the number of ring elements will probably be less than the number | ||
1004 | * of list elements used. | ||
1005 | */ | ||
1006 | static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) | ||
1007 | { | ||
1008 | struct sky2_port *sky2 = netdev_priv(dev); | ||
1009 | struct sky2_hw *hw = sky2->hw; | ||
1010 | struct sky2_tx_le *le = NULL; | ||
1011 | struct ring_info *re; | ||
1012 | unsigned long flags; | ||
1013 | unsigned i, len; | ||
1014 | dma_addr_t mapping; | ||
1015 | u32 addr64; | ||
1016 | u16 mss; | ||
1017 | u8 ctrl; | ||
1018 | |||
1019 | local_irq_save(flags); | ||
1020 | if (!spin_trylock(&sky2->tx_lock)) { | ||
1021 | local_irq_restore(flags); | ||
1022 | return NETDEV_TX_LOCKED; | ||
1023 | } | ||
1024 | |||
1025 | if (unlikely(tx_avail(sky2) < tx_le_req(skb))) { | ||
1026 | netif_stop_queue(dev); | ||
1027 | spin_unlock_irqrestore(&sky2->tx_lock, flags); | ||
1028 | |||
1029 | printk(KERN_WARNING PFX "%s: ring full when queue awake!\n", | ||
1030 | dev->name); | ||
1031 | return NETDEV_TX_BUSY; | ||
1032 | } | ||
1033 | |||
1034 | if (unlikely(netif_msg_tx_queued(sky2))) | ||
1035 | printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n", | ||
1036 | dev->name, sky2->tx_prod, skb->len); | ||
1037 | |||
1038 | len = skb_headlen(skb); | ||
1039 | mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); | ||
1040 | addr64 = (mapping >> 16) >> 16; | ||
1041 | |||
1042 | re = sky2->tx_ring + sky2->tx_prod; | ||
1043 | |||
1044 | /* Send high bits if changed */ | ||
1045 | if (addr64 != sky2->tx_addr64) { | ||
1046 | le = get_tx_le(sky2); | ||
1047 | le->tx.addr = cpu_to_le32(addr64); | ||
1048 | le->ctrl = 0; | ||
1049 | le->opcode = OP_ADDR64 | HW_OWNER; | ||
1050 | sky2->tx_addr64 = addr64; | ||
1051 | } | ||
1052 | |||
1053 | /* Check for TCP Segmentation Offload */ | ||
1054 | mss = skb_shinfo(skb)->tso_size; | ||
1055 | if (mss != 0) { | ||
1056 | /* just drop the packet if non-linear expansion fails */ | ||
1057 | if (skb_header_cloned(skb) && | ||
1058 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { | ||
1059 | dev_kfree_skb_any(skb); | ||
1060 | goto out_unlock; | ||
1061 | } | ||
1062 | |||
1063 | mss += ((skb->h.th->doff - 5) * 4); /* TCP options */ | ||
1064 | mss += (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr); | ||
1065 | mss += ETH_HLEN; | ||
1066 | } | ||
1067 | |||
1068 | if (mss != sky2->tx_last_mss) { | ||
1069 | le = get_tx_le(sky2); | ||
1070 | le->tx.tso.size = cpu_to_le16(mss); | ||
1071 | le->tx.tso.rsvd = 0; | ||
1072 | le->opcode = OP_LRGLEN | HW_OWNER; | ||
1073 | le->ctrl = 0; | ||
1074 | sky2->tx_last_mss = mss; | ||
1075 | } | ||
1076 | |||
1077 | ctrl = 0; | ||
1078 | #ifdef SKY2_VLAN_TAG_USED | ||
1079 | /* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */ | ||
1080 | if (sky2->vlgrp && vlan_tx_tag_present(skb)) { | ||
1081 | if (!le) { | ||
1082 | le = get_tx_le(sky2); | ||
1083 | le->tx.addr = 0; | ||
1084 | le->opcode = OP_VLAN|HW_OWNER; | ||
1085 | le->ctrl = 0; | ||
1086 | } else | ||
1087 | le->opcode |= OP_VLAN; | ||
1088 | le->length = cpu_to_be16(vlan_tx_tag_get(skb)); | ||
1089 | ctrl |= INS_VLAN; | ||
1090 | } | ||
1091 | #endif | ||
1092 | |||
1093 | /* Handle TCP checksum offload */ | ||
1094 | if (skb->ip_summed == CHECKSUM_HW) { | ||
1095 | u16 hdr = skb->h.raw - skb->data; | ||
1096 | u16 offset = hdr + skb->csum; | ||
1097 | |||
1098 | ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; | ||
1099 | if (skb->nh.iph->protocol == IPPROTO_UDP) | ||
1100 | ctrl |= UDPTCP; | ||
1101 | |||
1102 | le = get_tx_le(sky2); | ||
1103 | le->tx.csum.start = cpu_to_le16(hdr); | ||
1104 | le->tx.csum.offset = cpu_to_le16(offset); | ||
1105 | le->length = 0; /* initial checksum value */ | ||
1106 | le->ctrl = 1; /* one packet */ | ||
1107 | le->opcode = OP_TCPLISW | HW_OWNER; | ||
1108 | } | ||
1109 | |||
1110 | le = get_tx_le(sky2); | ||
1111 | le->tx.addr = cpu_to_le32((u32) mapping); | ||
1112 | le->length = cpu_to_le16(len); | ||
1113 | le->ctrl = ctrl; | ||
1114 | le->opcode = mss ? (OP_LARGESEND | HW_OWNER) : (OP_PACKET | HW_OWNER); | ||
1115 | |||
1116 | /* Record the transmit mapping info */ | ||
1117 | re->skb = skb; | ||
1118 | re->mapaddr = mapping; | ||
1119 | re->maplen = len; | ||
1120 | |||
1121 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
1122 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | ||
1123 | struct ring_info *fre; | ||
1124 | |||
1125 | mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset, | ||
1126 | frag->size, PCI_DMA_TODEVICE); | ||
1127 | addr64 = (mapping >> 16) >> 16; | ||
1128 | if (addr64 != sky2->tx_addr64) { | ||
1129 | le = get_tx_le(sky2); | ||
1130 | le->tx.addr = cpu_to_le32(addr64); | ||
1131 | le->ctrl = 0; | ||
1132 | le->opcode = OP_ADDR64 | HW_OWNER; | ||
1133 | sky2->tx_addr64 = addr64; | ||
1134 | } | ||
1135 | |||
1136 | le = get_tx_le(sky2); | ||
1137 | le->tx.addr = cpu_to_le32((u32) mapping); | ||
1138 | le->length = cpu_to_le16(frag->size); | ||
1139 | le->ctrl = ctrl; | ||
1140 | le->opcode = OP_BUFFER | HW_OWNER; | ||
1141 | |||
1142 | fre = sky2->tx_ring | ||
1143 | + ((re - sky2->tx_ring) + i + 1) % TX_RING_SIZE; | ||
1144 | fre->skb = NULL; | ||
1145 | fre->mapaddr = mapping; | ||
1146 | fre->maplen = frag->size; | ||
1147 | } | ||
1148 | re->idx = sky2->tx_prod; | ||
1149 | le->ctrl |= EOP; | ||
1150 | |||
1151 | sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod, | ||
1152 | &sky2->tx_last_put, TX_RING_SIZE); | ||
1153 | |||
1154 | if (tx_avail(sky2) < MAX_SKB_TX_LE + 1) | ||
1155 | netif_stop_queue(dev); | ||
1156 | |||
1157 | out_unlock: | ||
1158 | mmiowb(); | ||
1159 | spin_unlock_irqrestore(&sky2->tx_lock, flags); | ||
1160 | |||
1161 | dev->trans_start = jiffies; | ||
1162 | return NETDEV_TX_OK; | ||
1163 | } | ||
1164 | |||
1165 | /* | ||
1166 | * Free ring elements from starting at tx_cons until "done" | ||
1167 | * | ||
1168 | * NB: the hardware will tell us about partial completion of multi-part | ||
1169 | * buffers; these are deferred until completion. | ||
1170 | */ | ||
1171 | static void sky2_tx_complete(struct sky2_port *sky2, u16 done) | ||
1172 | { | ||
1173 | struct net_device *dev = sky2->netdev; | ||
1174 | unsigned i; | ||
1175 | |||
1176 | if (unlikely(netif_msg_tx_done(sky2))) | ||
1177 | printk(KERN_DEBUG "%s: tx done, up to %u\n", | ||
1178 | dev->name, done); | ||
1179 | |||
1180 | spin_lock(&sky2->tx_lock); | ||
1181 | |||
1182 | while (sky2->tx_cons != done) { | ||
1183 | struct ring_info *re = sky2->tx_ring + sky2->tx_cons; | ||
1184 | struct sk_buff *skb; | ||
1185 | |||
1186 | /* Check for partial status */ | ||
1187 | if (tx_dist(sky2->tx_cons, done) | ||
1188 | < tx_dist(sky2->tx_cons, re->idx)) | ||
1189 | goto out; | ||
1190 | |||
1191 | skb = re->skb; | ||
1192 | pci_unmap_single(sky2->hw->pdev, | ||
1193 | re->mapaddr, re->maplen, PCI_DMA_TODEVICE); | ||
1194 | |||
1195 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
1196 | struct ring_info *fre; | ||
1197 | fre = | ||
1198 | sky2->tx_ring + (sky2->tx_cons + i + | ||
1199 | 1) % TX_RING_SIZE; | ||
1200 | pci_unmap_page(sky2->hw->pdev, fre->mapaddr, | ||
1201 | fre->maplen, PCI_DMA_TODEVICE); | ||
1202 | } | ||
1203 | |||
1204 | dev_kfree_skb_any(skb); | ||
1205 | |||
1206 | sky2->tx_cons = re->idx; | ||
1207 | } | ||
1208 | out: | ||
1209 | |||
1210 | if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE) | ||
1211 | netif_wake_queue(dev); | ||
1212 | spin_unlock(&sky2->tx_lock); | ||
1213 | } | ||
1214 | |||
1215 | /* Cleanup all untransmitted buffers, assume transmitter not running */ | ||
1216 | static inline void sky2_tx_clean(struct sky2_port *sky2) | ||
1217 | { | ||
1218 | sky2_tx_complete(sky2, sky2->tx_prod); | ||
1219 | } | ||
1220 | |||
1221 | /* Network shutdown */ | ||
1222 | static int sky2_down(struct net_device *dev) | ||
1223 | { | ||
1224 | struct sky2_port *sky2 = netdev_priv(dev); | ||
1225 | struct sky2_hw *hw = sky2->hw; | ||
1226 | unsigned port = sky2->port; | ||
1227 | u16 ctrl; | ||
1228 | |||
1229 | if (netif_msg_ifdown(sky2)) | ||
1230 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); | ||
1231 | |||
1232 | netif_stop_queue(dev); | ||
1233 | |||
1234 | sky2_phy_reset(hw, port); | ||
1235 | |||
1236 | /* Stop transmitter */ | ||
1237 | sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_STOP); | ||
1238 | sky2_read32(hw, Q_ADDR(txqaddr[port], Q_CSR)); | ||
1239 | |||
1240 | sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), | ||
1241 | RB_RST_SET | RB_DIS_OP_MD); | ||
1242 | |||
1243 | ctrl = gma_read16(hw, port, GM_GP_CTRL); | ||
1244 | ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA); | ||
1245 | gma_write16(hw, port, GM_GP_CTRL, ctrl); | ||
1246 | |||
1247 | sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); | ||
1248 | |||
1249 | /* Workaround shared GMAC reset */ | ||
1250 | if (!(hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0 | ||
1251 | && port == 0 && hw->dev[1] && netif_running(hw->dev[1]))) | ||
1252 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); | ||
1253 | |||
1254 | /* Disable Force Sync bit and Enable Alloc bit */ | ||
1255 | sky2_write8(hw, SK_REG(port, TXA_CTRL), | ||
1256 | TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); | ||
1257 | |||
1258 | /* Stop Interval Timer and Limit Counter of Tx Arbiter */ | ||
1259 | sky2_write32(hw, SK_REG(port, TXA_ITI_INI), 0L); | ||
1260 | sky2_write32(hw, SK_REG(port, TXA_LIM_INI), 0L); | ||
1261 | |||
1262 | /* Reset the PCI FIFO of the async Tx queue */ | ||
1263 | sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), | ||
1264 | BMU_RST_SET | BMU_FIFO_RST); | ||
1265 | |||
1266 | /* Reset the Tx prefetch units */ | ||
1267 | sky2_write32(hw, Y2_QADDR(txqaddr[port], PREF_UNIT_CTRL), | ||
1268 | PREF_UNIT_RST_SET); | ||
1269 | |||
1270 | sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET); | ||
1271 | |||
1272 | sky2_rx_stop(sky2); | ||
1273 | |||
1274 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); | ||
1275 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); | ||
1276 | |||
1277 | /* turn off LED's */ | ||
1278 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | ||
1279 | |||
1280 | sky2_tx_clean(sky2); | ||
1281 | sky2_rx_clean(sky2); | ||
1282 | |||
1283 | pci_free_consistent(hw->pdev, RX_LE_BYTES, | ||
1284 | sky2->rx_le, sky2->rx_le_map); | ||
1285 | kfree(sky2->rx_ring); | ||
1286 | |||
1287 | pci_free_consistent(hw->pdev, | ||
1288 | TX_RING_SIZE * sizeof(struct sky2_tx_le), | ||
1289 | sky2->tx_le, sky2->tx_le_map); | ||
1290 | kfree(sky2->tx_ring); | ||
1291 | |||
1292 | return 0; | ||
1293 | } | ||
1294 | |||
1295 | static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux) | ||
1296 | { | ||
1297 | if (!hw->copper) | ||
1298 | return SPEED_1000; | ||
1299 | |||
1300 | if (hw->chip_id == CHIP_ID_YUKON_FE) | ||
1301 | return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10; | ||
1302 | |||
1303 | switch (aux & PHY_M_PS_SPEED_MSK) { | ||
1304 | case PHY_M_PS_SPEED_1000: | ||
1305 | return SPEED_1000; | ||
1306 | case PHY_M_PS_SPEED_100: | ||
1307 | return SPEED_100; | ||
1308 | default: | ||
1309 | return SPEED_10; | ||
1310 | } | ||
1311 | } | ||
1312 | |||
1313 | static void sky2_link_up(struct sky2_port *sky2) | ||
1314 | { | ||
1315 | struct sky2_hw *hw = sky2->hw; | ||
1316 | unsigned port = sky2->port; | ||
1317 | u16 reg; | ||
1318 | |||
1319 | /* disable Rx GMAC FIFO flush mode */ | ||
1320 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RX_F_FL_OFF); | ||
1321 | |||
1322 | /* Enable Transmit FIFO Underrun */ | ||
1323 | sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK); | ||
1324 | |||
1325 | reg = gma_read16(hw, port, GM_GP_CTRL); | ||
1326 | if (sky2->duplex == DUPLEX_FULL || sky2->autoneg == AUTONEG_ENABLE) | ||
1327 | reg |= GM_GPCR_DUP_FULL; | ||
1328 | |||
1329 | /* enable Rx/Tx */ | ||
1330 | reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; | ||
1331 | gma_write16(hw, port, GM_GP_CTRL, reg); | ||
1332 | gma_read16(hw, port, GM_GP_CTRL); | ||
1333 | |||
1334 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); | ||
1335 | |||
1336 | netif_carrier_on(sky2->netdev); | ||
1337 | netif_wake_queue(sky2->netdev); | ||
1338 | |||
1339 | /* Turn on link LED */ | ||
1340 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), | ||
1341 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); | ||
1342 | |||
1343 | if (hw->chip_id == CHIP_ID_YUKON_XL) { | ||
1344 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | ||
1345 | |||
1346 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | ||
1347 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */ | ||
1348 | PHY_M_LEDC_INIT_CTRL(sky2->speed == | ||
1349 | SPEED_10 ? 7 : 0) | | ||
1350 | PHY_M_LEDC_STA1_CTRL(sky2->speed == | ||
1351 | SPEED_100 ? 7 : 0) | | ||
1352 | PHY_M_LEDC_STA0_CTRL(sky2->speed == | ||
1353 | SPEED_1000 ? 7 : 0)); | ||
1354 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | ||
1355 | } | ||
1356 | |||
1357 | if (netif_msg_link(sky2)) | ||
1358 | printk(KERN_INFO PFX | ||
1359 | "%s: Link is up at %d Mbps, %s duplex, flow control %s\n", | ||
1360 | sky2->netdev->name, sky2->speed, | ||
1361 | sky2->duplex == DUPLEX_FULL ? "full" : "half", | ||
1362 | (sky2->tx_pause && sky2->rx_pause) ? "both" : | ||
1363 | sky2->tx_pause ? "tx" : sky2->rx_pause ? "rx" : "none"); | ||
1364 | } | ||
1365 | |||
1366 | static void sky2_link_down(struct sky2_port *sky2) | ||
1367 | { | ||
1368 | struct sky2_hw *hw = sky2->hw; | ||
1369 | unsigned port = sky2->port; | ||
1370 | u16 reg; | ||
1371 | |||
1372 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); | ||
1373 | |||
1374 | reg = gma_read16(hw, port, GM_GP_CTRL); | ||
1375 | reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); | ||
1376 | gma_write16(hw, port, GM_GP_CTRL, reg); | ||
1377 | gma_read16(hw, port, GM_GP_CTRL); /* PCI post */ | ||
1378 | |||
1379 | if (sky2->rx_pause && !sky2->tx_pause) { | ||
1380 | /* restore Asymmetric Pause bit */ | ||
1381 | gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, | ||
1382 | gm_phy_read(hw, port, PHY_MARV_AUNE_ADV) | ||
1383 | | PHY_M_AN_ASP); | ||
1384 | } | ||
1385 | |||
1386 | sky2_phy_reset(hw, port); | ||
1387 | |||
1388 | netif_carrier_off(sky2->netdev); | ||
1389 | netif_stop_queue(sky2->netdev); | ||
1390 | |||
1391 | /* Turn on link LED */ | ||
1392 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); | ||
1393 | |||
1394 | if (netif_msg_link(sky2)) | ||
1395 | printk(KERN_INFO PFX "%s: Link is down.\n", sky2->netdev->name); | ||
1396 | sky2_phy_init(hw, port); | ||
1397 | } | ||
1398 | |||
1399 | static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) | ||
1400 | { | ||
1401 | struct sky2_hw *hw = sky2->hw; | ||
1402 | unsigned port = sky2->port; | ||
1403 | u16 lpa; | ||
1404 | |||
1405 | lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP); | ||
1406 | |||
1407 | if (lpa & PHY_M_AN_RF) { | ||
1408 | printk(KERN_ERR PFX "%s: remote fault", sky2->netdev->name); | ||
1409 | return -1; | ||
1410 | } | ||
1411 | |||
1412 | if (hw->chip_id != CHIP_ID_YUKON_FE && | ||
1413 | gm_phy_read(hw, port, PHY_MARV_1000T_STAT) & PHY_B_1000S_MSF) { | ||
1414 | printk(KERN_ERR PFX "%s: master/slave fault", | ||
1415 | sky2->netdev->name); | ||
1416 | return -1; | ||
1417 | } | ||
1418 | |||
1419 | if (!(aux & PHY_M_PS_SPDUP_RES)) { | ||
1420 | printk(KERN_ERR PFX "%s: speed/duplex mismatch", | ||
1421 | sky2->netdev->name); | ||
1422 | return -1; | ||
1423 | } | ||
1424 | |||
1425 | sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; | ||
1426 | |||
1427 | sky2->speed = sky2_phy_speed(hw, aux); | ||
1428 | |||
1429 | /* Pause bits are offset (9..8) */ | ||
1430 | if (hw->chip_id == CHIP_ID_YUKON_XL) | ||
1431 | aux >>= 6; | ||
1432 | |||
1433 | sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0; | ||
1434 | sky2->tx_pause = (aux & PHY_M_PS_TX_P_EN) != 0; | ||
1435 | |||
1436 | if ((sky2->tx_pause || sky2->rx_pause) | ||
1437 | && !(sky2->speed < SPEED_1000 && sky2->duplex == DUPLEX_HALF)) | ||
1438 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); | ||
1439 | else | ||
1440 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); | ||
1441 | |||
1442 | return 0; | ||
1443 | } | ||
1444 | |||
1445 | /* | ||
1446 | * Interrupt from PHY are handled in tasklet (soft irq) | ||
1447 | * because accessing phy registers requires spin wait which might | ||
1448 | * cause excess interrupt latency. | ||
1449 | */ | ||
1450 | static void sky2_phy_task(unsigned long data) | ||
1451 | { | ||
1452 | struct sky2_port *sky2 = (struct sky2_port *)data; | ||
1453 | struct sky2_hw *hw = sky2->hw; | ||
1454 | u16 istatus, phystat; | ||
1455 | |||
1456 | spin_lock(&hw->phy_lock); | ||
1457 | istatus = gm_phy_read(hw, sky2->port, PHY_MARV_INT_STAT); | ||
1458 | phystat = gm_phy_read(hw, sky2->port, PHY_MARV_PHY_STAT); | ||
1459 | |||
1460 | if (netif_msg_intr(sky2)) | ||
1461 | printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", | ||
1462 | sky2->netdev->name, istatus, phystat); | ||
1463 | |||
1464 | if (istatus & PHY_M_IS_AN_COMPL) { | ||
1465 | if (sky2_autoneg_done(sky2, phystat) == 0) | ||
1466 | sky2_link_up(sky2); | ||
1467 | goto out; | ||
1468 | } | ||
1469 | |||
1470 | if (istatus & PHY_M_IS_LSP_CHANGE) | ||
1471 | sky2->speed = sky2_phy_speed(hw, phystat); | ||
1472 | |||
1473 | if (istatus & PHY_M_IS_DUP_CHANGE) | ||
1474 | sky2->duplex = | ||
1475 | (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; | ||
1476 | |||
1477 | if (istatus & PHY_M_IS_LST_CHANGE) { | ||
1478 | if (phystat & PHY_M_PS_LINK_UP) | ||
1479 | sky2_link_up(sky2); | ||
1480 | else | ||
1481 | sky2_link_down(sky2); | ||
1482 | } | ||
1483 | out: | ||
1484 | spin_unlock(&hw->phy_lock); | ||
1485 | |||
1486 | local_irq_disable(); | ||
1487 | hw->intr_mask |= (sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2; | ||
1488 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
1489 | local_irq_enable(); | ||
1490 | } | ||
1491 | |||
1492 | static void sky2_tx_timeout(struct net_device *dev) | ||
1493 | { | ||
1494 | struct sky2_port *sky2 = netdev_priv(dev); | ||
1495 | |||
1496 | if (netif_msg_timer(sky2)) | ||
1497 | printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); | ||
1498 | |||
1499 | sky2_write32(sky2->hw, Q_ADDR(txqaddr[sky2->port], Q_CSR), BMU_STOP); | ||
1500 | sky2_read32(sky2->hw, Q_ADDR(txqaddr[sky2->port], Q_CSR)); | ||
1501 | |||
1502 | sky2_tx_clean(sky2); | ||
1503 | } | ||
1504 | |||
1505 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) | ||
1506 | { | ||
1507 | struct sky2_port *sky2 = netdev_priv(dev); | ||
1508 | struct sky2_hw *hw = sky2->hw; | ||
1509 | int err; | ||
1510 | u16 ctl, mode; | ||
1511 | |||
1512 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) | ||
1513 | return -EINVAL; | ||
1514 | |||
1515 | if (!netif_running(dev)) { | ||
1516 | dev->mtu = new_mtu; | ||
1517 | return 0; | ||
1518 | } | ||
1519 | |||
1520 | local_irq_disable(); | ||
1521 | sky2_write32(hw, B0_IMSK, 0); | ||
1522 | |||
1523 | ctl = gma_read16(hw, sky2->port, GM_GP_CTRL); | ||
1524 | gma_write16(hw, sky2->port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); | ||
1525 | sky2_rx_stop(sky2); | ||
1526 | sky2_rx_clean(sky2); | ||
1527 | |||
1528 | dev->mtu = new_mtu; | ||
1529 | mode = DATA_BLIND_VAL(DATA_BLIND_DEF) | | ||
1530 | GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); | ||
1531 | |||
1532 | if (dev->mtu > ETH_DATA_LEN) | ||
1533 | mode |= GM_SMOD_JUMBO_ENA; | ||
1534 | |||
1535 | gma_write16(hw, sky2->port, GM_SERIAL_MODE, mode); | ||
1536 | |||
1537 | sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD); | ||
1538 | |||
1539 | err = sky2_rx_start(sky2); | ||
1540 | gma_write16(hw, sky2->port, GM_GP_CTRL, ctl); | ||
1541 | |||
1542 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
1543 | sky2_read32(hw, B0_IMSK); | ||
1544 | local_irq_enable(); | ||
1545 | return err; | ||
1546 | } | ||
1547 | |||
1548 | /* | ||
1549 | * Receive one packet. | ||
1550 | * For small packets or errors, just reuse existing skb. | ||
1551 | * For larger packets, get new buffer. | ||
1552 | */ | ||
1553 | static struct sk_buff *sky2_receive(struct sky2_port *sky2, | ||
1554 | u16 length, u32 status) | ||
1555 | { | ||
1556 | struct ring_info *re = sky2->rx_ring + sky2->rx_next; | ||
1557 | struct sk_buff *skb = NULL; | ||
1558 | struct net_device *dev; | ||
1559 | const unsigned int bufsize = rx_size(sky2); | ||
1560 | |||
1561 | if (unlikely(netif_msg_rx_status(sky2))) | ||
1562 | printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n", | ||
1563 | sky2->netdev->name, sky2->rx_next, status, length); | ||
1564 | |||
1565 | sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; | ||
1566 | |||
1567 | if (!(status & GMR_FS_RX_OK) || (status & GMR_FS_ANY_ERR)) | ||
1568 | goto error; | ||
1569 | |||
1570 | if (length < RX_COPY_THRESHOLD) { | ||
1571 | skb = alloc_skb(length + 2, GFP_ATOMIC); | ||
1572 | if (!skb) | ||
1573 | goto resubmit; | ||
1574 | |||
1575 | skb_reserve(skb, 2); | ||
1576 | pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->mapaddr, | ||
1577 | length, PCI_DMA_FROMDEVICE); | ||
1578 | memcpy(skb->data, re->skb->data, length); | ||
1579 | skb->ip_summed = re->skb->ip_summed; | ||
1580 | skb->csum = re->skb->csum; | ||
1581 | pci_dma_sync_single_for_device(sky2->hw->pdev, re->mapaddr, | ||
1582 | length, PCI_DMA_FROMDEVICE); | ||
1583 | } else { | ||
1584 | struct sk_buff *nskb; | ||
1585 | |||
1586 | nskb = dev_alloc_skb(bufsize); | ||
1587 | if (!nskb) | ||
1588 | goto resubmit; | ||
1589 | |||
1590 | skb = re->skb; | ||
1591 | re->skb = nskb; | ||
1592 | pci_unmap_single(sky2->hw->pdev, re->mapaddr, | ||
1593 | re->maplen, PCI_DMA_FROMDEVICE); | ||
1594 | prefetch(skb->data); | ||
1595 | |||
1596 | re->mapaddr = pci_map_single(sky2->hw->pdev, nskb->data, | ||
1597 | bufsize, PCI_DMA_FROMDEVICE); | ||
1598 | re->maplen = bufsize; | ||
1599 | } | ||
1600 | |||
1601 | skb_put(skb, length); | ||
1602 | dev = sky2->netdev; | ||
1603 | skb->dev = dev; | ||
1604 | skb->protocol = eth_type_trans(skb, dev); | ||
1605 | dev->last_rx = jiffies; | ||
1606 | |||
1607 | resubmit: | ||
1608 | re->skb->ip_summed = CHECKSUM_NONE; | ||
1609 | sky2_rx_add(sky2, re); | ||
1610 | |||
1611 | /* Tell receiver about new buffers. */ | ||
1612 | sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put, | ||
1613 | &sky2->rx_last_put, RX_LE_SIZE); | ||
1614 | |||
1615 | return skb; | ||
1616 | |||
1617 | error: | ||
1618 | if (status & GMR_FS_GOOD_FC) | ||
1619 | goto resubmit; | ||
1620 | |||
1621 | if (netif_msg_rx_err(sky2)) | ||
1622 | printk(KERN_INFO PFX "%s: rx error, status 0x%x length %d\n", | ||
1623 | sky2->netdev->name, status, length); | ||
1624 | |||
1625 | if (status & (GMR_FS_LONG_ERR | GMR_FS_UN_SIZE)) | ||
1626 | sky2->net_stats.rx_length_errors++; | ||
1627 | if (status & GMR_FS_FRAGMENT) | ||
1628 | sky2->net_stats.rx_frame_errors++; | ||
1629 | if (status & GMR_FS_CRC_ERR) | ||
1630 | sky2->net_stats.rx_crc_errors++; | ||
1631 | if (status & GMR_FS_RX_FF_OV) | ||
1632 | sky2->net_stats.rx_fifo_errors++; | ||
1633 | |||
1634 | goto resubmit; | ||
1635 | } | ||
1636 | |||
1637 | /* Transmit ring index in reported status block is encoded as: | ||
1638 | * | ||
1639 | * | TXS2 | TXA2 | TXS1 | TXA1 | ||
1640 | */ | ||
1641 | static inline u16 tx_index(u8 port, u32 status, u16 len) | ||
1642 | { | ||
1643 | if (port == 0) | ||
1644 | return status & 0xfff; | ||
1645 | else | ||
1646 | return ((status >> 24) & 0xff) | (len & 0xf) << 8; | ||
1647 | } | ||
1648 | |||
1649 | /* | ||
1650 | * Both ports share the same status interrupt, therefore there is only | ||
1651 | * one poll routine. | ||
1652 | */ | ||
1653 | static int sky2_poll(struct net_device *dev0, int *budget) | ||
1654 | { | ||
1655 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | ||
1656 | unsigned int to_do = min(dev0->quota, *budget); | ||
1657 | unsigned int work_done = 0; | ||
1658 | u16 hwidx; | ||
1659 | |||
1660 | hwidx = sky2_read16(hw, STAT_PUT_IDX); | ||
1661 | BUG_ON(hwidx >= STATUS_RING_SIZE); | ||
1662 | rmb(); | ||
1663 | |||
1664 | do { | ||
1665 | struct sky2_status_le *le = hw->st_le + hw->st_idx; | ||
1666 | struct sky2_port *sky2; | ||
1667 | struct sk_buff *skb; | ||
1668 | u32 status; | ||
1669 | u16 length; | ||
1670 | |||
1671 | /* Are we done yet? */ | ||
1672 | if (hw->st_idx == hwidx) { | ||
1673 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
1674 | hwidx = sky2_read16(hw, STAT_PUT_IDX); | ||
1675 | if (hwidx == hw->st_idx) | ||
1676 | break; | ||
1677 | } | ||
1678 | |||
1679 | hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE; | ||
1680 | prefetch(&hw->st_le[hw->st_idx]); | ||
1681 | |||
1682 | BUG_ON(le->link >= hw->ports || !hw->dev[le->link]); | ||
1683 | |||
1684 | sky2 = netdev_priv(hw->dev[le->link]); | ||
1685 | status = le32_to_cpu(le->status); | ||
1686 | length = le16_to_cpu(le->length); | ||
1687 | |||
1688 | switch (le->opcode & ~HW_OWNER) { | ||
1689 | case OP_RXSTAT: | ||
1690 | skb = sky2_receive(sky2, length, status); | ||
1691 | if (!skb) | ||
1692 | break; | ||
1693 | #ifdef SKY2_VLAN_TAG_USED | ||
1694 | if (sky2->vlgrp && (status & GMR_FS_VLAN)) { | ||
1695 | vlan_hwaccel_receive_skb(skb, | ||
1696 | sky2->vlgrp, | ||
1697 | be16_to_cpu(sky2->rx_tag)); | ||
1698 | } else | ||
1699 | #endif | ||
1700 | netif_receive_skb(skb); | ||
1701 | ++work_done; | ||
1702 | break; | ||
1703 | |||
1704 | #ifdef SKY2_VLAN_TAG_USED | ||
1705 | case OP_RXVLAN: | ||
1706 | sky2->rx_tag = length; | ||
1707 | break; | ||
1708 | |||
1709 | case OP_RXCHKSVLAN: | ||
1710 | sky2->rx_tag = length; | ||
1711 | /* fall through */ | ||
1712 | #endif | ||
1713 | case OP_RXCHKS: | ||
1714 | skb = sky2->rx_ring[sky2->rx_next].skb; | ||
1715 | skb->ip_summed = CHECKSUM_HW; | ||
1716 | skb->csum = le16_to_cpu(status); | ||
1717 | break; | ||
1718 | |||
1719 | case OP_TXINDEXLE: | ||
1720 | sky2_tx_complete(sky2, | ||
1721 | tx_index(sky2->port, status, length)); | ||
1722 | break; | ||
1723 | |||
1724 | default: | ||
1725 | if (net_ratelimit()) | ||
1726 | printk(KERN_WARNING PFX | ||
1727 | "unknown status opcode 0x%x\n", | ||
1728 | le->opcode); | ||
1729 | break; | ||
1730 | } | ||
1731 | |||
1732 | le->opcode = 0; /* paranoia */ | ||
1733 | } while (work_done < to_do); | ||
1734 | |||
1735 | mmiowb(); | ||
1736 | |||
1737 | *budget -= work_done; | ||
1738 | dev0->quota -= work_done; | ||
1739 | if (work_done < to_do) { | ||
1740 | /* | ||
1741 | * Another chip workaround, need to restart TX timer if status | ||
1742 | * LE was handled. WA_DEV_43_418 | ||
1743 | */ | ||
1744 | if (is_ec_a1(hw)) { | ||
1745 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); | ||
1746 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); | ||
1747 | } | ||
1748 | |||
1749 | netif_rx_complete(dev0); | ||
1750 | hw->intr_mask |= Y2_IS_STAT_BMU; | ||
1751 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
1752 | sky2_read32(hw, B0_IMSK); | ||
1753 | } | ||
1754 | |||
1755 | return work_done >= to_do; | ||
1756 | |||
1757 | } | ||
1758 | |||
1759 | static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) | ||
1760 | { | ||
1761 | struct net_device *dev = hw->dev[port]; | ||
1762 | |||
1763 | printk(KERN_INFO PFX "%s: hw error interrupt status 0x%x\n", | ||
1764 | dev->name, status); | ||
1765 | |||
1766 | if (status & Y2_IS_PAR_RD1) { | ||
1767 | printk(KERN_ERR PFX "%s: ram data read parity error\n", | ||
1768 | dev->name); | ||
1769 | /* Clear IRQ */ | ||
1770 | sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_RD_PERR); | ||
1771 | } | ||
1772 | |||
1773 | if (status & Y2_IS_PAR_WR1) { | ||
1774 | printk(KERN_ERR PFX "%s: ram data write parity error\n", | ||
1775 | dev->name); | ||
1776 | |||
1777 | sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_WR_PERR); | ||
1778 | } | ||
1779 | |||
1780 | if (status & Y2_IS_PAR_MAC1) { | ||
1781 | printk(KERN_ERR PFX "%s: MAC parity error\n", dev->name); | ||
1782 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_PE); | ||
1783 | } | ||
1784 | |||
1785 | if (status & Y2_IS_PAR_RX1) { | ||
1786 | printk(KERN_ERR PFX "%s: RX parity error\n", dev->name); | ||
1787 | sky2_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), BMU_CLR_IRQ_PAR); | ||
1788 | } | ||
1789 | |||
1790 | if (status & Y2_IS_TCP_TXA1) { | ||
1791 | printk(KERN_ERR PFX "%s: TCP segmentation error\n", dev->name); | ||
1792 | sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_CLR_IRQ_TCP); | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1796 | static void sky2_hw_intr(struct sky2_hw *hw) | ||
1797 | { | ||
1798 | u32 status = sky2_read32(hw, B0_HWE_ISRC); | ||
1799 | |||
1800 | if (status & Y2_IS_TIST_OV) | ||
1801 | sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ); | ||
1802 | |||
1803 | if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) { | ||
1804 | u16 pci_err; | ||
1805 | |||
1806 | pci_read_config_word(hw->pdev, PCI_STATUS, &pci_err); | ||
1807 | printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n", | ||
1808 | pci_name(hw->pdev), pci_err); | ||
1809 | |||
1810 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
1811 | pci_write_config_word(hw->pdev, PCI_STATUS, | ||
1812 | pci_err | PCI_STATUS_ERROR_BITS); | ||
1813 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | ||
1814 | } | ||
1815 | |||
1816 | if (status & Y2_IS_PCI_EXP) { | ||
1817 | /* PCI-Express uncorrectable Error occurred */ | ||
1818 | u32 pex_err; | ||
1819 | |||
1820 | pci_read_config_dword(hw->pdev, PEX_UNC_ERR_STAT, &pex_err); | ||
1821 | |||
1822 | printk(KERN_ERR PFX "%s: pci express error (0x%x)\n", | ||
1823 | pci_name(hw->pdev), pex_err); | ||
1824 | |||
1825 | /* clear the interrupt */ | ||
1826 | sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
1827 | pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, | ||
1828 | 0xffffffffUL); | ||
1829 | sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | ||
1830 | |||
1831 | if (pex_err & PEX_FATAL_ERRORS) { | ||
1832 | u32 hwmsk = sky2_read32(hw, B0_HWE_IMSK); | ||
1833 | hwmsk &= ~Y2_IS_PCI_EXP; | ||
1834 | sky2_write32(hw, B0_HWE_IMSK, hwmsk); | ||
1835 | } | ||
1836 | } | ||
1837 | |||
1838 | if (status & Y2_HWE_L1_MASK) | ||
1839 | sky2_hw_error(hw, 0, status); | ||
1840 | status >>= 8; | ||
1841 | if (status & Y2_HWE_L1_MASK) | ||
1842 | sky2_hw_error(hw, 1, status); | ||
1843 | } | ||
1844 | |||
1845 | static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) | ||
1846 | { | ||
1847 | struct net_device *dev = hw->dev[port]; | ||
1848 | struct sky2_port *sky2 = netdev_priv(dev); | ||
1849 | u8 status = sky2_read8(hw, SK_REG(port, GMAC_IRQ_SRC)); | ||
1850 | |||
1851 | if (netif_msg_intr(sky2)) | ||
1852 | printk(KERN_INFO PFX "%s: mac interrupt status 0x%x\n", | ||
1853 | dev->name, status); | ||
1854 | |||
1855 | if (status & GM_IS_RX_FF_OR) { | ||
1856 | ++sky2->net_stats.rx_fifo_errors; | ||
1857 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); | ||
1858 | } | ||
1859 | |||
1860 | if (status & GM_IS_TX_FF_UR) { | ||
1861 | ++sky2->net_stats.tx_fifo_errors; | ||
1862 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); | ||
1863 | } | ||
1864 | } | ||
1865 | |||
1866 | static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) | ||
1867 | { | ||
1868 | struct net_device *dev = hw->dev[port]; | ||
1869 | struct sky2_port *sky2 = netdev_priv(dev); | ||
1870 | |||
1871 | hw->intr_mask &= ~(port == 0 ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2); | ||
1872 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
1873 | tasklet_schedule(&sky2->phy_task); | ||
1874 | } | ||
1875 | |||
1876 | static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | ||
1877 | { | ||
1878 | struct sky2_hw *hw = dev_id; | ||
1879 | struct net_device *dev0 = hw->dev[0]; | ||
1880 | u32 status; | ||
1881 | |||
1882 | status = sky2_read32(hw, B0_Y2_SP_ISRC2); | ||
1883 | if (status == 0 || status == ~0) | ||
1884 | return IRQ_NONE; | ||
1885 | |||
1886 | if (status & Y2_IS_HW_ERR) | ||
1887 | sky2_hw_intr(hw); | ||
1888 | |||
1889 | /* Do NAPI for Rx and Tx status */ | ||
1890 | if (status & Y2_IS_STAT_BMU) { | ||
1891 | hw->intr_mask &= ~Y2_IS_STAT_BMU; | ||
1892 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
1893 | prefetch(&hw->st_le[hw->st_idx]); | ||
1894 | |||
1895 | if (netif_rx_schedule_test(dev0)) | ||
1896 | __netif_rx_schedule(dev0); | ||
1897 | } | ||
1898 | |||
1899 | if (status & Y2_IS_IRQ_PHY1) | ||
1900 | sky2_phy_intr(hw, 0); | ||
1901 | |||
1902 | if (status & Y2_IS_IRQ_PHY2) | ||
1903 | sky2_phy_intr(hw, 1); | ||
1904 | |||
1905 | if (status & Y2_IS_IRQ_MAC1) | ||
1906 | sky2_mac_intr(hw, 0); | ||
1907 | |||
1908 | if (status & Y2_IS_IRQ_MAC2) | ||
1909 | sky2_mac_intr(hw, 1); | ||
1910 | |||
1911 | sky2_write32(hw, B0_Y2_SP_ICR, 2); | ||
1912 | |||
1913 | sky2_read32(hw, B0_IMSK); | ||
1914 | |||
1915 | return IRQ_HANDLED; | ||
1916 | } | ||
1917 | |||
1918 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
1919 | static void sky2_netpoll(struct net_device *dev) | ||
1920 | { | ||
1921 | struct sky2_port *sky2 = netdev_priv(dev); | ||
1922 | |||
1923 | sky2_intr(sky2->hw->pdev->irq, sky2->hw, NULL); | ||
1924 | } | ||
1925 | #endif | ||
1926 | |||
1927 | /* Chip internal frequency for clock calculations */ | ||
1928 | static inline u32 sky2_khz(const struct sky2_hw *hw) | ||
1929 | { | ||
1930 | switch (hw->chip_id) { | ||
1931 | case CHIP_ID_YUKON_EC: | ||
1932 | return 125000; /* 125 Mhz */ | ||
1933 | case CHIP_ID_YUKON_FE: | ||
1934 | return 100000; /* 100 Mhz */ | ||
1935 | default: /* YUKON_XL */ | ||
1936 | return 156000; /* 156 Mhz */ | ||
1937 | } | ||
1938 | } | ||
1939 | |||
1940 | static inline u32 sky2_ms2clk(const struct sky2_hw *hw, u32 ms) | ||
1941 | { | ||
1942 | return sky2_khz(hw) * ms; | ||
1943 | } | ||
1944 | |||
1945 | static inline u32 sky2_us2clk(const struct sky2_hw *hw, u32 us) | ||
1946 | { | ||
1947 | return (sky2_khz(hw) * us) / 1000; | ||
1948 | } | ||
1949 | |||
1950 | static int sky2_reset(struct sky2_hw *hw) | ||
1951 | { | ||
1952 | u32 ctst; | ||
1953 | u16 status; | ||
1954 | u8 t8, pmd_type; | ||
1955 | int i; | ||
1956 | |||
1957 | ctst = sky2_read32(hw, B0_CTST); | ||
1958 | |||
1959 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | ||
1960 | hw->chip_id = sky2_read8(hw, B2_CHIP_ID); | ||
1961 | if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { | ||
1962 | printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n", | ||
1963 | pci_name(hw->pdev), hw->chip_id); | ||
1964 | return -EOPNOTSUPP; | ||
1965 | } | ||
1966 | |||
1967 | /* ring for status responses */ | ||
1968 | hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES, | ||
1969 | &hw->st_dma); | ||
1970 | if (!hw->st_le) | ||
1971 | return -ENOMEM; | ||
1972 | |||
1973 | /* disable ASF */ | ||
1974 | if (hw->chip_id <= CHIP_ID_YUKON_EC) { | ||
1975 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); | ||
1976 | sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE); | ||
1977 | } | ||
1978 | |||
1979 | /* do a SW reset */ | ||
1980 | sky2_write8(hw, B0_CTST, CS_RST_SET); | ||
1981 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | ||
1982 | |||
1983 | /* clear PCI errors, if any */ | ||
1984 | pci_read_config_word(hw->pdev, PCI_STATUS, &status); | ||
1985 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
1986 | pci_write_config_word(hw->pdev, PCI_STATUS, | ||
1987 | status | PCI_STATUS_ERROR_BITS); | ||
1988 | |||
1989 | sky2_write8(hw, B0_CTST, CS_MRST_CLR); | ||
1990 | |||
1991 | /* clear any PEX errors */ | ||
1992 | if (is_pciex(hw)) { | ||
1993 | u16 lstat; | ||
1994 | pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT, | ||
1995 | 0xffffffffUL); | ||
1996 | pci_read_config_word(hw->pdev, PEX_LNK_STAT, &lstat); | ||
1997 | } | ||
1998 | |||
1999 | pmd_type = sky2_read8(hw, B2_PMD_TYP); | ||
2000 | hw->copper = !(pmd_type == 'L' || pmd_type == 'S'); | ||
2001 | |||
2002 | hw->ports = 1; | ||
2003 | t8 = sky2_read8(hw, B2_Y2_HW_RES); | ||
2004 | if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { | ||
2005 | if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC)) | ||
2006 | ++hw->ports; | ||
2007 | } | ||
2008 | hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; | ||
2009 | |||
2010 | sky2_set_power_state(hw, PCI_D0); | ||
2011 | |||
2012 | for (i = 0; i < hw->ports; i++) { | ||
2013 | sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); | ||
2014 | sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR); | ||
2015 | } | ||
2016 | |||
2017 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | ||
2018 | |||
2019 | /* Clear I2C IRQ noise */ | ||
2020 | sky2_write32(hw, B2_I2C_IRQ, 1); | ||
2021 | |||
2022 | /* turn off hardware timer (unused) */ | ||
2023 | sky2_write8(hw, B2_TI_CTRL, TIM_STOP); | ||
2024 | sky2_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ); | ||
2025 | |||
2026 | sky2_write8(hw, B0_Y2LED, LED_STAT_ON); | ||
2027 | |||
2028 | /* Turn on descriptor polling (every 75us) */ | ||
2029 | sky2_write32(hw, B28_DPT_INI, sky2_us2clk(hw, 75)); | ||
2030 | sky2_write8(hw, B28_DPT_CTRL, DPT_START); | ||
2031 | |||
2032 | /* Turn off receive timestamp */ | ||
2033 | sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_STOP); | ||
2034 | sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ); | ||
2035 | |||
2036 | /* enable the Tx Arbiters */ | ||
2037 | for (i = 0; i < hw->ports; i++) | ||
2038 | sky2_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB); | ||
2039 | |||
2040 | /* Initialize ram interface */ | ||
2041 | for (i = 0; i < hw->ports; i++) { | ||
2042 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_CTRL), RI_RST_CLR); | ||
2043 | |||
2044 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R1), SK_RI_TO_53); | ||
2045 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA1), SK_RI_TO_53); | ||
2046 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS1), SK_RI_TO_53); | ||
2047 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R1), SK_RI_TO_53); | ||
2048 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA1), SK_RI_TO_53); | ||
2049 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS1), SK_RI_TO_53); | ||
2050 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R2), SK_RI_TO_53); | ||
2051 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA2), SK_RI_TO_53); | ||
2052 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS2), SK_RI_TO_53); | ||
2053 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R2), SK_RI_TO_53); | ||
2054 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA2), SK_RI_TO_53); | ||
2055 | sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53); | ||
2056 | } | ||
2057 | |||
2058 | if (is_pciex(hw)) { | ||
2059 | u16 pctrl; | ||
2060 | |||
2061 | /* change Max. Read Request Size to 2048 bytes */ | ||
2062 | pci_read_config_word(hw->pdev, PEX_DEV_CTRL, &pctrl); | ||
2063 | pctrl &= ~PEX_DC_MAX_RRS_MSK; | ||
2064 | pctrl |= PEX_DC_MAX_RD_RQ_SIZE(4); | ||
2065 | |||
2066 | |||
2067 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
2068 | pci_write_config_word(hw->pdev, PEX_DEV_CTRL, pctrl); | ||
2069 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | ||
2070 | } | ||
2071 | |||
2072 | sky2_write32(hw, B0_HWE_IMSK, Y2_HWE_ALL_MASK); | ||
2073 | |||
2074 | spin_lock_bh(&hw->phy_lock); | ||
2075 | for (i = 0; i < hw->ports; i++) | ||
2076 | sky2_phy_reset(hw, i); | ||
2077 | spin_unlock_bh(&hw->phy_lock); | ||
2078 | |||
2079 | memset(hw->st_le, 0, STATUS_LE_BYTES); | ||
2080 | hw->st_idx = 0; | ||
2081 | |||
2082 | sky2_write32(hw, STAT_CTRL, SC_STAT_RST_SET); | ||
2083 | sky2_write32(hw, STAT_CTRL, SC_STAT_RST_CLR); | ||
2084 | |||
2085 | sky2_write32(hw, STAT_LIST_ADDR_LO, hw->st_dma); | ||
2086 | sky2_write32(hw, STAT_LIST_ADDR_HI, (u64) hw->st_dma >> 32); | ||
2087 | |||
2088 | /* Set the list last index */ | ||
2089 | sky2_write16(hw, STAT_LAST_IDX, STATUS_RING_SIZE - 1); | ||
2090 | |||
2091 | sky2_write32(hw, STAT_TX_TIMER_INI, sky2_ms2clk(hw, 10)); | ||
2092 | |||
2093 | /* These status setup values are copied from SysKonnect's driver */ | ||
2094 | if (is_ec_a1(hw)) { | ||
2095 | /* WA for dev. #4.3 */ | ||
2096 | sky2_write16(hw, STAT_TX_IDX_TH, 0xfff); /* Tx Threshold */ | ||
2097 | |||
2098 | /* set Status-FIFO watermark */ | ||
2099 | sky2_write8(hw, STAT_FIFO_WM, 0x21); /* WA for dev. #4.18 */ | ||
2100 | |||
2101 | /* set Status-FIFO ISR watermark */ | ||
2102 | sky2_write8(hw, STAT_FIFO_ISR_WM, 0x07); /* WA for dev. #4.18 */ | ||
2103 | |||
2104 | } else { | ||
2105 | sky2_write16(hw, STAT_TX_IDX_TH, 0x000a); | ||
2106 | |||
2107 | /* set Status-FIFO watermark */ | ||
2108 | sky2_write8(hw, STAT_FIFO_WM, 0x10); | ||
2109 | |||
2110 | /* set Status-FIFO ISR watermark */ | ||
2111 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0) | ||
2112 | sky2_write8(hw, STAT_FIFO_ISR_WM, 0x10); | ||
2113 | |||
2114 | else /* WA dev 4.109 */ | ||
2115 | sky2_write8(hw, STAT_FIFO_ISR_WM, 0x04); | ||
2116 | |||
2117 | sky2_write32(hw, STAT_ISR_TIMER_INI, 0x0190); | ||
2118 | } | ||
2119 | |||
2120 | /* enable status unit */ | ||
2121 | sky2_write32(hw, STAT_CTRL, SC_STAT_OP_ON); | ||
2122 | |||
2123 | sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); | ||
2124 | sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START); | ||
2125 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); | ||
2126 | |||
2127 | return 0; | ||
2128 | } | ||
2129 | |||
2130 | static inline u32 sky2_supported_modes(const struct sky2_hw *hw) | ||
2131 | { | ||
2132 | u32 modes; | ||
2133 | if (hw->copper) { | ||
2134 | modes = SUPPORTED_10baseT_Half | ||
2135 | | SUPPORTED_10baseT_Full | ||
2136 | | SUPPORTED_100baseT_Half | ||
2137 | | SUPPORTED_100baseT_Full | ||
2138 | | SUPPORTED_Autoneg | SUPPORTED_TP; | ||
2139 | |||
2140 | if (hw->chip_id != CHIP_ID_YUKON_FE) | ||
2141 | modes |= SUPPORTED_1000baseT_Half | ||
2142 | | SUPPORTED_1000baseT_Full; | ||
2143 | } else | ||
2144 | modes = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE | ||
2145 | | SUPPORTED_Autoneg; | ||
2146 | return modes; | ||
2147 | } | ||
2148 | |||
2149 | static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | ||
2150 | { | ||
2151 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2152 | struct sky2_hw *hw = sky2->hw; | ||
2153 | |||
2154 | ecmd->transceiver = XCVR_INTERNAL; | ||
2155 | ecmd->supported = sky2_supported_modes(hw); | ||
2156 | ecmd->phy_address = PHY_ADDR_MARV; | ||
2157 | if (hw->copper) { | ||
2158 | ecmd->supported = SUPPORTED_10baseT_Half | ||
2159 | | SUPPORTED_10baseT_Full | ||
2160 | | SUPPORTED_100baseT_Half | ||
2161 | | SUPPORTED_100baseT_Full | ||
2162 | | SUPPORTED_1000baseT_Half | ||
2163 | | SUPPORTED_1000baseT_Full | ||
2164 | | SUPPORTED_Autoneg | SUPPORTED_TP; | ||
2165 | ecmd->port = PORT_TP; | ||
2166 | } else | ||
2167 | ecmd->port = PORT_FIBRE; | ||
2168 | |||
2169 | ecmd->advertising = sky2->advertising; | ||
2170 | ecmd->autoneg = sky2->autoneg; | ||
2171 | ecmd->speed = sky2->speed; | ||
2172 | ecmd->duplex = sky2->duplex; | ||
2173 | return 0; | ||
2174 | } | ||
2175 | |||
2176 | static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | ||
2177 | { | ||
2178 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2179 | const struct sky2_hw *hw = sky2->hw; | ||
2180 | u32 supported = sky2_supported_modes(hw); | ||
2181 | |||
2182 | if (ecmd->autoneg == AUTONEG_ENABLE) { | ||
2183 | ecmd->advertising = supported; | ||
2184 | sky2->duplex = -1; | ||
2185 | sky2->speed = -1; | ||
2186 | } else { | ||
2187 | u32 setting; | ||
2188 | |||
2189 | switch (ecmd->speed) { | ||
2190 | case SPEED_1000: | ||
2191 | if (ecmd->duplex == DUPLEX_FULL) | ||
2192 | setting = SUPPORTED_1000baseT_Full; | ||
2193 | else if (ecmd->duplex == DUPLEX_HALF) | ||
2194 | setting = SUPPORTED_1000baseT_Half; | ||
2195 | else | ||
2196 | return -EINVAL; | ||
2197 | break; | ||
2198 | case SPEED_100: | ||
2199 | if (ecmd->duplex == DUPLEX_FULL) | ||
2200 | setting = SUPPORTED_100baseT_Full; | ||
2201 | else if (ecmd->duplex == DUPLEX_HALF) | ||
2202 | setting = SUPPORTED_100baseT_Half; | ||
2203 | else | ||
2204 | return -EINVAL; | ||
2205 | break; | ||
2206 | |||
2207 | case SPEED_10: | ||
2208 | if (ecmd->duplex == DUPLEX_FULL) | ||
2209 | setting = SUPPORTED_10baseT_Full; | ||
2210 | else if (ecmd->duplex == DUPLEX_HALF) | ||
2211 | setting = SUPPORTED_10baseT_Half; | ||
2212 | else | ||
2213 | return -EINVAL; | ||
2214 | break; | ||
2215 | default: | ||
2216 | return -EINVAL; | ||
2217 | } | ||
2218 | |||
2219 | if ((setting & supported) == 0) | ||
2220 | return -EINVAL; | ||
2221 | |||
2222 | sky2->speed = ecmd->speed; | ||
2223 | sky2->duplex = ecmd->duplex; | ||
2224 | } | ||
2225 | |||
2226 | sky2->autoneg = ecmd->autoneg; | ||
2227 | sky2->advertising = ecmd->advertising; | ||
2228 | |||
2229 | if (netif_running(dev)) { | ||
2230 | sky2_down(dev); | ||
2231 | sky2_up(dev); | ||
2232 | } | ||
2233 | |||
2234 | return 0; | ||
2235 | } | ||
2236 | |||
2237 | static void sky2_get_drvinfo(struct net_device *dev, | ||
2238 | struct ethtool_drvinfo *info) | ||
2239 | { | ||
2240 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2241 | |||
2242 | strcpy(info->driver, DRV_NAME); | ||
2243 | strcpy(info->version, DRV_VERSION); | ||
2244 | strcpy(info->fw_version, "N/A"); | ||
2245 | strcpy(info->bus_info, pci_name(sky2->hw->pdev)); | ||
2246 | } | ||
2247 | |||
2248 | static const struct sky2_stat { | ||
2249 | char name[ETH_GSTRING_LEN]; | ||
2250 | u16 offset; | ||
2251 | } sky2_stats[] = { | ||
2252 | { "tx_bytes", GM_TXO_OK_HI }, | ||
2253 | { "rx_bytes", GM_RXO_OK_HI }, | ||
2254 | { "tx_broadcast", GM_TXF_BC_OK }, | ||
2255 | { "rx_broadcast", GM_RXF_BC_OK }, | ||
2256 | { "tx_multicast", GM_TXF_MC_OK }, | ||
2257 | { "rx_multicast", GM_RXF_MC_OK }, | ||
2258 | { "tx_unicast", GM_TXF_UC_OK }, | ||
2259 | { "rx_unicast", GM_RXF_UC_OK }, | ||
2260 | { "tx_mac_pause", GM_TXF_MPAUSE }, | ||
2261 | { "rx_mac_pause", GM_RXF_MPAUSE }, | ||
2262 | { "collisions", GM_TXF_SNG_COL }, | ||
2263 | { "late_collision",GM_TXF_LAT_COL }, | ||
2264 | { "aborted", GM_TXF_ABO_COL }, | ||
2265 | { "multi_collisions", GM_TXF_MUL_COL }, | ||
2266 | { "fifo_underrun", GM_TXE_FIFO_UR }, | ||
2267 | { "fifo_overflow", GM_RXE_FIFO_OV }, | ||
2268 | { "rx_toolong", GM_RXF_LNG_ERR }, | ||
2269 | { "rx_jabber", GM_RXF_JAB_PKT }, | ||
2270 | { "rx_runt", GM_RXE_FRAG }, | ||
2271 | { "rx_too_long", GM_RXF_LNG_ERR }, | ||
2272 | { "rx_fcs_error", GM_RXF_FCS_ERR }, | ||
2273 | }; | ||
2274 | |||
2275 | static u32 sky2_get_rx_csum(struct net_device *dev) | ||
2276 | { | ||
2277 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2278 | |||
2279 | return sky2->rx_csum; | ||
2280 | } | ||
2281 | |||
2282 | static int sky2_set_rx_csum(struct net_device *dev, u32 data) | ||
2283 | { | ||
2284 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2285 | |||
2286 | sky2->rx_csum = data; | ||
2287 | |||
2288 | sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), | ||
2289 | data ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); | ||
2290 | |||
2291 | return 0; | ||
2292 | } | ||
2293 | |||
2294 | static u32 sky2_get_msglevel(struct net_device *netdev) | ||
2295 | { | ||
2296 | struct sky2_port *sky2 = netdev_priv(netdev); | ||
2297 | return sky2->msg_enable; | ||
2298 | } | ||
2299 | |||
2300 | static int sky2_nway_reset(struct net_device *dev) | ||
2301 | { | ||
2302 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2303 | struct sky2_hw *hw = sky2->hw; | ||
2304 | |||
2305 | if (sky2->autoneg != AUTONEG_ENABLE) | ||
2306 | return -EINVAL; | ||
2307 | |||
2308 | netif_stop_queue(dev); | ||
2309 | |||
2310 | spin_lock_irq(&hw->phy_lock); | ||
2311 | sky2_phy_reset(hw, sky2->port); | ||
2312 | sky2_phy_init(hw, sky2->port); | ||
2313 | spin_unlock_irq(&hw->phy_lock); | ||
2314 | |||
2315 | return 0; | ||
2316 | } | ||
2317 | |||
2318 | static void sky2_phy_stats(struct sky2_port *sky2, u64 * data, unsigned count) | ||
2319 | { | ||
2320 | struct sky2_hw *hw = sky2->hw; | ||
2321 | unsigned port = sky2->port; | ||
2322 | int i; | ||
2323 | |||
2324 | data[0] = (u64) gma_read32(hw, port, GM_TXO_OK_HI) << 32 | ||
2325 | | (u64) gma_read32(hw, port, GM_TXO_OK_LO); | ||
2326 | data[1] = (u64) gma_read32(hw, port, GM_RXO_OK_HI) << 32 | ||
2327 | | (u64) gma_read32(hw, port, GM_RXO_OK_LO); | ||
2328 | |||
2329 | for (i = 2; i < count; i++) | ||
2330 | data[i] = (u64) gma_read32(hw, port, sky2_stats[i].offset); | ||
2331 | } | ||
2332 | |||
2333 | static void sky2_set_msglevel(struct net_device *netdev, u32 value) | ||
2334 | { | ||
2335 | struct sky2_port *sky2 = netdev_priv(netdev); | ||
2336 | sky2->msg_enable = value; | ||
2337 | } | ||
2338 | |||
2339 | static int sky2_get_stats_count(struct net_device *dev) | ||
2340 | { | ||
2341 | return ARRAY_SIZE(sky2_stats); | ||
2342 | } | ||
2343 | |||
2344 | static void sky2_get_ethtool_stats(struct net_device *dev, | ||
2345 | struct ethtool_stats *stats, u64 * data) | ||
2346 | { | ||
2347 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2348 | |||
2349 | sky2_phy_stats(sky2, data, ARRAY_SIZE(sky2_stats)); | ||
2350 | } | ||
2351 | |||
2352 | static void sky2_get_strings(struct net_device *dev, u32 stringset, u8 * data) | ||
2353 | { | ||
2354 | int i; | ||
2355 | |||
2356 | switch (stringset) { | ||
2357 | case ETH_SS_STATS: | ||
2358 | for (i = 0; i < ARRAY_SIZE(sky2_stats); i++) | ||
2359 | memcpy(data + i * ETH_GSTRING_LEN, | ||
2360 | sky2_stats[i].name, ETH_GSTRING_LEN); | ||
2361 | break; | ||
2362 | } | ||
2363 | } | ||
2364 | |||
2365 | /* Use hardware MIB variables for critical path statistics and | ||
2366 | * transmit feedback not reported at interrupt. | ||
2367 | * Other errors are accounted for in interrupt handler. | ||
2368 | */ | ||
2369 | static struct net_device_stats *sky2_get_stats(struct net_device *dev) | ||
2370 | { | ||
2371 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2372 | u64 data[13]; | ||
2373 | |||
2374 | sky2_phy_stats(sky2, data, ARRAY_SIZE(data)); | ||
2375 | |||
2376 | sky2->net_stats.tx_bytes = data[0]; | ||
2377 | sky2->net_stats.rx_bytes = data[1]; | ||
2378 | sky2->net_stats.tx_packets = data[2] + data[4] + data[6]; | ||
2379 | sky2->net_stats.rx_packets = data[3] + data[5] + data[7]; | ||
2380 | sky2->net_stats.multicast = data[5] + data[7]; | ||
2381 | sky2->net_stats.collisions = data[10]; | ||
2382 | sky2->net_stats.tx_aborted_errors = data[12]; | ||
2383 | |||
2384 | return &sky2->net_stats; | ||
2385 | } | ||
2386 | |||
2387 | static int sky2_set_mac_address(struct net_device *dev, void *p) | ||
2388 | { | ||
2389 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2390 | struct sockaddr *addr = p; | ||
2391 | int err = 0; | ||
2392 | |||
2393 | if (!is_valid_ether_addr(addr->sa_data)) | ||
2394 | return -EADDRNOTAVAIL; | ||
2395 | |||
2396 | sky2_down(dev); | ||
2397 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | ||
2398 | memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8, | ||
2399 | dev->dev_addr, ETH_ALEN); | ||
2400 | memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8, | ||
2401 | dev->dev_addr, ETH_ALEN); | ||
2402 | if (dev->flags & IFF_UP) | ||
2403 | err = sky2_up(dev); | ||
2404 | return err; | ||
2405 | } | ||
2406 | |||
2407 | static void sky2_set_multicast(struct net_device *dev) | ||
2408 | { | ||
2409 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2410 | struct sky2_hw *hw = sky2->hw; | ||
2411 | unsigned port = sky2->port; | ||
2412 | struct dev_mc_list *list = dev->mc_list; | ||
2413 | u16 reg; | ||
2414 | u8 filter[8]; | ||
2415 | |||
2416 | memset(filter, 0, sizeof(filter)); | ||
2417 | |||
2418 | reg = gma_read16(hw, port, GM_RX_CTRL); | ||
2419 | reg |= GM_RXCR_UCF_ENA; | ||
2420 | |||
2421 | if (dev->flags & IFF_PROMISC) /* promiscuous */ | ||
2422 | reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); | ||
2423 | else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 16) /* all multicast */ | ||
2424 | memset(filter, 0xff, sizeof(filter)); | ||
2425 | else if (dev->mc_count == 0) /* no multicast */ | ||
2426 | reg &= ~GM_RXCR_MCF_ENA; | ||
2427 | else { | ||
2428 | int i; | ||
2429 | reg |= GM_RXCR_MCF_ENA; | ||
2430 | |||
2431 | for (i = 0; list && i < dev->mc_count; i++, list = list->next) { | ||
2432 | u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f; | ||
2433 | filter[bit / 8] |= 1 << (bit % 8); | ||
2434 | } | ||
2435 | } | ||
2436 | |||
2437 | gma_write16(hw, port, GM_MC_ADDR_H1, | ||
2438 | (u16) filter[0] | ((u16) filter[1] << 8)); | ||
2439 | gma_write16(hw, port, GM_MC_ADDR_H2, | ||
2440 | (u16) filter[2] | ((u16) filter[3] << 8)); | ||
2441 | gma_write16(hw, port, GM_MC_ADDR_H3, | ||
2442 | (u16) filter[4] | ((u16) filter[5] << 8)); | ||
2443 | gma_write16(hw, port, GM_MC_ADDR_H4, | ||
2444 | (u16) filter[6] | ((u16) filter[7] << 8)); | ||
2445 | |||
2446 | gma_write16(hw, port, GM_RX_CTRL, reg); | ||
2447 | } | ||
2448 | |||
2449 | /* Can have one global because blinking is controlled by | ||
2450 | * ethtool and that is always under RTNL mutex | ||
2451 | */ | ||
2452 | static inline void sky2_led(struct sky2_hw *hw, unsigned port, int on) | ||
2453 | { | ||
2454 | u16 pg; | ||
2455 | |||
2456 | spin_lock_bh(&hw->phy_lock); | ||
2457 | switch (hw->chip_id) { | ||
2458 | case CHIP_ID_YUKON_XL: | ||
2459 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | ||
2460 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | ||
2461 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, | ||
2462 | on ? (PHY_M_LEDC_LOS_CTRL(1) | | ||
2463 | PHY_M_LEDC_INIT_CTRL(7) | | ||
2464 | PHY_M_LEDC_STA1_CTRL(7) | | ||
2465 | PHY_M_LEDC_STA0_CTRL(7)) | ||
2466 | : 0); | ||
2467 | |||
2468 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | ||
2469 | break; | ||
2470 | |||
2471 | default: | ||
2472 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); | ||
2473 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, | ||
2474 | on ? PHY_M_LED_MO_DUP(MO_LED_ON) | | ||
2475 | PHY_M_LED_MO_10(MO_LED_ON) | | ||
2476 | PHY_M_LED_MO_100(MO_LED_ON) | | ||
2477 | PHY_M_LED_MO_1000(MO_LED_ON) | | ||
2478 | PHY_M_LED_MO_RX(MO_LED_ON) | ||
2479 | : PHY_M_LED_MO_DUP(MO_LED_OFF) | | ||
2480 | PHY_M_LED_MO_10(MO_LED_OFF) | | ||
2481 | PHY_M_LED_MO_100(MO_LED_OFF) | | ||
2482 | PHY_M_LED_MO_1000(MO_LED_OFF) | | ||
2483 | PHY_M_LED_MO_RX(MO_LED_OFF)); | ||
2484 | |||
2485 | } | ||
2486 | spin_unlock_bh(&hw->phy_lock); | ||
2487 | } | ||
2488 | |||
2489 | /* blink LED's for finding board */ | ||
2490 | static int sky2_phys_id(struct net_device *dev, u32 data) | ||
2491 | { | ||
2492 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2493 | struct sky2_hw *hw = sky2->hw; | ||
2494 | unsigned port = sky2->port; | ||
2495 | u16 ledctrl, ledover = 0; | ||
2496 | long ms; | ||
2497 | int onoff = 1; | ||
2498 | |||
2499 | if (!data || data > (u32) (MAX_SCHEDULE_TIMEOUT / HZ)) | ||
2500 | ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT); | ||
2501 | else | ||
2502 | ms = data * 1000; | ||
2503 | |||
2504 | /* save initial values */ | ||
2505 | spin_lock_bh(&hw->phy_lock); | ||
2506 | if (hw->chip_id == CHIP_ID_YUKON_XL) { | ||
2507 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | ||
2508 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | ||
2509 | ledctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | ||
2510 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | ||
2511 | } else { | ||
2512 | ledctrl = gm_phy_read(hw, port, PHY_MARV_LED_CTRL); | ||
2513 | ledover = gm_phy_read(hw, port, PHY_MARV_LED_OVER); | ||
2514 | } | ||
2515 | spin_unlock_bh(&hw->phy_lock); | ||
2516 | |||
2517 | while (ms > 0) { | ||
2518 | sky2_led(hw, port, onoff); | ||
2519 | onoff = !onoff; | ||
2520 | |||
2521 | if (msleep_interruptible(250)) | ||
2522 | break; /* interrupted */ | ||
2523 | ms -= 250; | ||
2524 | } | ||
2525 | |||
2526 | /* resume regularly scheduled programming */ | ||
2527 | spin_lock_bh(&hw->phy_lock); | ||
2528 | if (hw->chip_id == CHIP_ID_YUKON_XL) { | ||
2529 | u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); | ||
2530 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); | ||
2531 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ledctrl); | ||
2532 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | ||
2533 | } else { | ||
2534 | gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); | ||
2535 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); | ||
2536 | } | ||
2537 | spin_unlock_bh(&hw->phy_lock); | ||
2538 | |||
2539 | return 0; | ||
2540 | } | ||
2541 | |||
2542 | static void sky2_get_pauseparam(struct net_device *dev, | ||
2543 | struct ethtool_pauseparam *ecmd) | ||
2544 | { | ||
2545 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2546 | |||
2547 | ecmd->tx_pause = sky2->tx_pause; | ||
2548 | ecmd->rx_pause = sky2->rx_pause; | ||
2549 | ecmd->autoneg = sky2->autoneg; | ||
2550 | } | ||
2551 | |||
2552 | static int sky2_set_pauseparam(struct net_device *dev, | ||
2553 | struct ethtool_pauseparam *ecmd) | ||
2554 | { | ||
2555 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2556 | int err = 0; | ||
2557 | |||
2558 | sky2->autoneg = ecmd->autoneg; | ||
2559 | sky2->tx_pause = ecmd->tx_pause != 0; | ||
2560 | sky2->rx_pause = ecmd->rx_pause != 0; | ||
2561 | |||
2562 | if (netif_running(dev)) { | ||
2563 | sky2_down(dev); | ||
2564 | err = sky2_up(dev); | ||
2565 | } | ||
2566 | |||
2567 | return err; | ||
2568 | } | ||
2569 | |||
2570 | #ifdef CONFIG_PM | ||
2571 | static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
2572 | { | ||
2573 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2574 | |||
2575 | wol->supported = WAKE_MAGIC; | ||
2576 | wol->wolopts = sky2->wol ? WAKE_MAGIC : 0; | ||
2577 | } | ||
2578 | |||
2579 | static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | ||
2580 | { | ||
2581 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2582 | struct sky2_hw *hw = sky2->hw; | ||
2583 | |||
2584 | if (wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) | ||
2585 | return -EOPNOTSUPP; | ||
2586 | |||
2587 | sky2->wol = wol->wolopts == WAKE_MAGIC; | ||
2588 | |||
2589 | if (sky2->wol) { | ||
2590 | memcpy_toio(hw->regs + WOL_MAC_ADDR, dev->dev_addr, ETH_ALEN); | ||
2591 | |||
2592 | sky2_write16(hw, WOL_CTRL_STAT, | ||
2593 | WOL_CTL_ENA_PME_ON_MAGIC_PKT | | ||
2594 | WOL_CTL_ENA_MAGIC_PKT_UNIT); | ||
2595 | } else | ||
2596 | sky2_write16(hw, WOL_CTRL_STAT, WOL_CTL_DEFAULT); | ||
2597 | |||
2598 | return 0; | ||
2599 | } | ||
2600 | #endif | ||
2601 | |||
2602 | static void sky2_get_ringparam(struct net_device *dev, | ||
2603 | struct ethtool_ringparam *ering) | ||
2604 | { | ||
2605 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2606 | |||
2607 | ering->rx_max_pending = RX_MAX_PENDING; | ||
2608 | ering->rx_mini_max_pending = 0; | ||
2609 | ering->rx_jumbo_max_pending = 0; | ||
2610 | ering->tx_max_pending = TX_RING_SIZE - 1; | ||
2611 | |||
2612 | ering->rx_pending = sky2->rx_pending; | ||
2613 | ering->rx_mini_pending = 0; | ||
2614 | ering->rx_jumbo_pending = 0; | ||
2615 | ering->tx_pending = sky2->tx_pending; | ||
2616 | } | ||
2617 | |||
2618 | static int sky2_set_ringparam(struct net_device *dev, | ||
2619 | struct ethtool_ringparam *ering) | ||
2620 | { | ||
2621 | struct sky2_port *sky2 = netdev_priv(dev); | ||
2622 | int err = 0; | ||
2623 | |||
2624 | if (ering->rx_pending > RX_MAX_PENDING || | ||
2625 | ering->rx_pending < 8 || | ||
2626 | ering->tx_pending < MAX_SKB_TX_LE || | ||
2627 | ering->tx_pending > TX_RING_SIZE - 1) | ||
2628 | return -EINVAL; | ||
2629 | |||
2630 | if (netif_running(dev)) | ||
2631 | sky2_down(dev); | ||
2632 | |||
2633 | sky2->rx_pending = ering->rx_pending; | ||
2634 | sky2->tx_pending = ering->tx_pending; | ||
2635 | |||
2636 | if (netif_running(dev)) | ||
2637 | err = sky2_up(dev); | ||
2638 | |||
2639 | return err; | ||
2640 | } | ||
2641 | |||
2642 | static int sky2_get_regs_len(struct net_device *dev) | ||
2643 | { | ||
2644 | return 0x4000; | ||
2645 | } | ||
2646 | |||
2647 | /* | ||
2648 | * Returns copy of control register region | ||
2649 | * Note: access to the RAM address register set will cause timeouts. | ||
2650 | */ | ||
2651 | static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, | ||
2652 | void *p) | ||
2653 | { | ||
2654 | const struct sky2_port *sky2 = netdev_priv(dev); | ||
2655 | const void __iomem *io = sky2->hw->regs; | ||
2656 | |||
2657 | BUG_ON(regs->len < B3_RI_WTO_R1); | ||
2658 | regs->version = 1; | ||
2659 | memset(p, 0, regs->len); | ||
2660 | |||
2661 | memcpy_fromio(p, io, B3_RAM_ADDR); | ||
2662 | |||
2663 | memcpy_fromio(p + B3_RI_WTO_R1, | ||
2664 | io + B3_RI_WTO_R1, | ||
2665 | regs->len - B3_RI_WTO_R1); | ||
2666 | } | ||
2667 | |||
2668 | static struct ethtool_ops sky2_ethtool_ops = { | ||
2669 | .get_settings = sky2_get_settings, | ||
2670 | .set_settings = sky2_set_settings, | ||
2671 | .get_drvinfo = sky2_get_drvinfo, | ||
2672 | .get_msglevel = sky2_get_msglevel, | ||
2673 | .set_msglevel = sky2_set_msglevel, | ||
2674 | .nway_reset = sky2_nway_reset, | ||
2675 | .get_regs_len = sky2_get_regs_len, | ||
2676 | .get_regs = sky2_get_regs, | ||
2677 | .get_link = ethtool_op_get_link, | ||
2678 | .get_sg = ethtool_op_get_sg, | ||
2679 | .set_sg = ethtool_op_set_sg, | ||
2680 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
2681 | .set_tx_csum = ethtool_op_set_tx_csum, | ||
2682 | .get_tso = ethtool_op_get_tso, | ||
2683 | .set_tso = ethtool_op_set_tso, | ||
2684 | .get_rx_csum = sky2_get_rx_csum, | ||
2685 | .set_rx_csum = sky2_set_rx_csum, | ||
2686 | .get_strings = sky2_get_strings, | ||
2687 | .get_ringparam = sky2_get_ringparam, | ||
2688 | .set_ringparam = sky2_set_ringparam, | ||
2689 | .get_pauseparam = sky2_get_pauseparam, | ||
2690 | .set_pauseparam = sky2_set_pauseparam, | ||
2691 | #ifdef CONFIG_PM | ||
2692 | .get_wol = sky2_get_wol, | ||
2693 | .set_wol = sky2_set_wol, | ||
2694 | #endif | ||
2695 | .phys_id = sky2_phys_id, | ||
2696 | .get_stats_count = sky2_get_stats_count, | ||
2697 | .get_ethtool_stats = sky2_get_ethtool_stats, | ||
2698 | .get_perm_addr = ethtool_op_get_perm_addr, | ||
2699 | }; | ||
2700 | |||
2701 | /* Initialize network device */ | ||
2702 | static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, | ||
2703 | unsigned port, int highmem) | ||
2704 | { | ||
2705 | struct sky2_port *sky2; | ||
2706 | struct net_device *dev = alloc_etherdev(sizeof(*sky2)); | ||
2707 | |||
2708 | if (!dev) { | ||
2709 | printk(KERN_ERR "sky2 etherdev alloc failed"); | ||
2710 | return NULL; | ||
2711 | } | ||
2712 | |||
2713 | SET_MODULE_OWNER(dev); | ||
2714 | SET_NETDEV_DEV(dev, &hw->pdev->dev); | ||
2715 | dev->open = sky2_up; | ||
2716 | dev->stop = sky2_down; | ||
2717 | dev->hard_start_xmit = sky2_xmit_frame; | ||
2718 | dev->get_stats = sky2_get_stats; | ||
2719 | dev->set_multicast_list = sky2_set_multicast; | ||
2720 | dev->set_mac_address = sky2_set_mac_address; | ||
2721 | dev->change_mtu = sky2_change_mtu; | ||
2722 | SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops); | ||
2723 | dev->tx_timeout = sky2_tx_timeout; | ||
2724 | dev->watchdog_timeo = TX_WATCHDOG; | ||
2725 | if (port == 0) | ||
2726 | dev->poll = sky2_poll; | ||
2727 | dev->weight = NAPI_WEIGHT; | ||
2728 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
2729 | dev->poll_controller = sky2_netpoll; | ||
2730 | #endif | ||
2731 | |||
2732 | sky2 = netdev_priv(dev); | ||
2733 | sky2->netdev = dev; | ||
2734 | sky2->hw = hw; | ||
2735 | sky2->msg_enable = netif_msg_init(debug, default_msg); | ||
2736 | |||
2737 | spin_lock_init(&sky2->tx_lock); | ||
2738 | /* Auto speed and flow control */ | ||
2739 | sky2->autoneg = AUTONEG_ENABLE; | ||
2740 | sky2->tx_pause = 0; | ||
2741 | sky2->rx_pause = 1; | ||
2742 | sky2->duplex = -1; | ||
2743 | sky2->speed = -1; | ||
2744 | sky2->advertising = sky2_supported_modes(hw); | ||
2745 | sky2->rx_csum = 1; | ||
2746 | tasklet_init(&sky2->phy_task, sky2_phy_task, (unsigned long)sky2); | ||
2747 | sky2->tx_pending = TX_DEF_PENDING; | ||
2748 | sky2->rx_pending = is_ec_a1(hw) ? 8 : RX_DEF_PENDING; | ||
2749 | |||
2750 | hw->dev[port] = dev; | ||
2751 | |||
2752 | sky2->port = port; | ||
2753 | |||
2754 | dev->features |= NETIF_F_LLTX | NETIF_F_TSO; | ||
2755 | if (highmem) | ||
2756 | dev->features |= NETIF_F_HIGHDMA; | ||
2757 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | ||
2758 | |||
2759 | #ifdef SKY2_VLAN_TAG_USED | ||
2760 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | ||
2761 | dev->vlan_rx_register = sky2_vlan_rx_register; | ||
2762 | dev->vlan_rx_kill_vid = sky2_vlan_rx_kill_vid; | ||
2763 | #endif | ||
2764 | |||
2765 | /* read the mac address */ | ||
2766 | memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); | ||
2767 | memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); | ||
2768 | |||
2769 | /* device is off until link detection */ | ||
2770 | netif_carrier_off(dev); | ||
2771 | netif_stop_queue(dev); | ||
2772 | |||
2773 | return dev; | ||
2774 | } | ||
2775 | |||
2776 | static inline void sky2_show_addr(struct net_device *dev) | ||
2777 | { | ||
2778 | const struct sky2_port *sky2 = netdev_priv(dev); | ||
2779 | |||
2780 | if (netif_msg_probe(sky2)) | ||
2781 | printk(KERN_INFO PFX "%s: addr %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
2782 | dev->name, | ||
2783 | dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], | ||
2784 | dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); | ||
2785 | } | ||
2786 | |||
2787 | static int __devinit sky2_probe(struct pci_dev *pdev, | ||
2788 | const struct pci_device_id *ent) | ||
2789 | { | ||
2790 | struct net_device *dev, *dev1 = NULL; | ||
2791 | struct sky2_hw *hw; | ||
2792 | int err, pm_cap, using_dac = 0; | ||
2793 | |||
2794 | err = pci_enable_device(pdev); | ||
2795 | if (err) { | ||
2796 | printk(KERN_ERR PFX "%s cannot enable PCI device\n", | ||
2797 | pci_name(pdev)); | ||
2798 | goto err_out; | ||
2799 | } | ||
2800 | |||
2801 | err = pci_request_regions(pdev, DRV_NAME); | ||
2802 | if (err) { | ||
2803 | printk(KERN_ERR PFX "%s cannot obtain PCI resources\n", | ||
2804 | pci_name(pdev)); | ||
2805 | goto err_out; | ||
2806 | } | ||
2807 | |||
2808 | pci_set_master(pdev); | ||
2809 | |||
2810 | /* Find power-management capability. */ | ||
2811 | pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); | ||
2812 | if (pm_cap == 0) { | ||
2813 | printk(KERN_ERR PFX "Cannot find PowerManagement capability, " | ||
2814 | "aborting.\n"); | ||
2815 | err = -EIO; | ||
2816 | goto err_out_free_regions; | ||
2817 | } | ||
2818 | |||
2819 | if (sizeof(dma_addr_t) > sizeof(u32)) { | ||
2820 | err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); | ||
2821 | if (!err) | ||
2822 | using_dac = 1; | ||
2823 | } | ||
2824 | |||
2825 | if (!using_dac) { | ||
2826 | err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | ||
2827 | if (err) { | ||
2828 | printk(KERN_ERR PFX "%s no usable DMA configuration\n", | ||
2829 | pci_name(pdev)); | ||
2830 | goto err_out_free_regions; | ||
2831 | } | ||
2832 | } | ||
2833 | #ifdef __BIG_ENDIAN | ||
2834 | /* byte swap descriptors in hardware */ | ||
2835 | { | ||
2836 | u32 reg; | ||
2837 | |||
2838 | pci_read_config_dword(pdev, PCI_DEV_REG2, ®); | ||
2839 | reg |= PCI_REV_DESC; | ||
2840 | pci_write_config_dword(pdev, PCI_DEV_REG2, reg); | ||
2841 | } | ||
2842 | #endif | ||
2843 | |||
2844 | err = -ENOMEM; | ||
2845 | hw = kmalloc(sizeof(*hw), GFP_KERNEL); | ||
2846 | if (!hw) { | ||
2847 | printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n", | ||
2848 | pci_name(pdev)); | ||
2849 | goto err_out_free_regions; | ||
2850 | } | ||
2851 | |||
2852 | memset(hw, 0, sizeof(*hw)); | ||
2853 | hw->pdev = pdev; | ||
2854 | spin_lock_init(&hw->phy_lock); | ||
2855 | |||
2856 | hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); | ||
2857 | if (!hw->regs) { | ||
2858 | printk(KERN_ERR PFX "%s: cannot map device registers\n", | ||
2859 | pci_name(pdev)); | ||
2860 | goto err_out_free_hw; | ||
2861 | } | ||
2862 | hw->pm_cap = pm_cap; | ||
2863 | |||
2864 | err = sky2_reset(hw); | ||
2865 | if (err) | ||
2866 | goto err_out_iounmap; | ||
2867 | |||
2868 | printk(KERN_INFO PFX "addr 0x%lx irq %d Yukon-%s (0x%x) rev %d\n", | ||
2869 | pci_resource_start(pdev, 0), pdev->irq, | ||
2870 | yukon_name[hw->chip_id - CHIP_ID_YUKON], | ||
2871 | hw->chip_id, hw->chip_rev); | ||
2872 | |||
2873 | dev = sky2_init_netdev(hw, 0, using_dac); | ||
2874 | if (!dev) | ||
2875 | goto err_out_free_pci; | ||
2876 | |||
2877 | err = register_netdev(dev); | ||
2878 | if (err) { | ||
2879 | printk(KERN_ERR PFX "%s: cannot register net device\n", | ||
2880 | pci_name(pdev)); | ||
2881 | goto err_out_free_netdev; | ||
2882 | } | ||
2883 | |||
2884 | sky2_show_addr(dev); | ||
2885 | |||
2886 | if (hw->ports > 1 && (dev1 = sky2_init_netdev(hw, 1, using_dac))) { | ||
2887 | if (register_netdev(dev1) == 0) | ||
2888 | sky2_show_addr(dev1); | ||
2889 | else { | ||
2890 | /* Failure to register second port need not be fatal */ | ||
2891 | printk(KERN_WARNING PFX | ||
2892 | "register of second port failed\n"); | ||
2893 | hw->dev[1] = NULL; | ||
2894 | free_netdev(dev1); | ||
2895 | } | ||
2896 | } | ||
2897 | |||
2898 | err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw); | ||
2899 | if (err) { | ||
2900 | printk(KERN_ERR PFX "%s: cannot assign irq %d\n", | ||
2901 | pci_name(pdev), pdev->irq); | ||
2902 | goto err_out_unregister; | ||
2903 | } | ||
2904 | |||
2905 | hw->intr_mask = Y2_IS_BASE; | ||
2906 | sky2_write32(hw, B0_IMSK, hw->intr_mask); | ||
2907 | |||
2908 | pci_set_drvdata(pdev, hw); | ||
2909 | |||
2910 | return 0; | ||
2911 | |||
2912 | err_out_unregister: | ||
2913 | if (dev1) { | ||
2914 | unregister_netdev(dev1); | ||
2915 | free_netdev(dev1); | ||
2916 | } | ||
2917 | unregister_netdev(dev); | ||
2918 | err_out_free_netdev: | ||
2919 | free_netdev(dev); | ||
2920 | err_out_free_pci: | ||
2921 | sky2_write8(hw, B0_CTST, CS_RST_SET); | ||
2922 | pci_free_consistent(hw->pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); | ||
2923 | err_out_iounmap: | ||
2924 | iounmap(hw->regs); | ||
2925 | err_out_free_hw: | ||
2926 | kfree(hw); | ||
2927 | err_out_free_regions: | ||
2928 | pci_release_regions(pdev); | ||
2929 | pci_disable_device(pdev); | ||
2930 | err_out: | ||
2931 | return err; | ||
2932 | } | ||
2933 | |||
2934 | static void __devexit sky2_remove(struct pci_dev *pdev) | ||
2935 | { | ||
2936 | struct sky2_hw *hw = pci_get_drvdata(pdev); | ||
2937 | struct net_device *dev0, *dev1; | ||
2938 | |||
2939 | if (!hw) | ||
2940 | return; | ||
2941 | |||
2942 | dev0 = hw->dev[0]; | ||
2943 | dev1 = hw->dev[1]; | ||
2944 | if (dev1) | ||
2945 | unregister_netdev(dev1); | ||
2946 | unregister_netdev(dev0); | ||
2947 | |||
2948 | sky2_write32(hw, B0_IMSK, 0); | ||
2949 | sky2_set_power_state(hw, PCI_D3hot); | ||
2950 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | ||
2951 | sky2_write8(hw, B0_CTST, CS_RST_SET); | ||
2952 | sky2_read8(hw, B0_CTST); | ||
2953 | |||
2954 | free_irq(pdev->irq, hw); | ||
2955 | pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); | ||
2956 | pci_release_regions(pdev); | ||
2957 | pci_disable_device(pdev); | ||
2958 | |||
2959 | if (dev1) | ||
2960 | free_netdev(dev1); | ||
2961 | free_netdev(dev0); | ||
2962 | iounmap(hw->regs); | ||
2963 | kfree(hw); | ||
2964 | |||
2965 | pci_set_drvdata(pdev, NULL); | ||
2966 | } | ||
2967 | |||
2968 | #ifdef CONFIG_PM | ||
2969 | static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | ||
2970 | { | ||
2971 | struct sky2_hw *hw = pci_get_drvdata(pdev); | ||
2972 | int i; | ||
2973 | |||
2974 | for (i = 0; i < 2; i++) { | ||
2975 | struct net_device *dev = hw->dev[i]; | ||
2976 | |||
2977 | if (dev) { | ||
2978 | if (!netif_running(dev)) | ||
2979 | continue; | ||
2980 | |||
2981 | sky2_down(dev); | ||
2982 | netif_device_detach(dev); | ||
2983 | } | ||
2984 | } | ||
2985 | |||
2986 | return sky2_set_power_state(hw, pci_choose_state(pdev, state)); | ||
2987 | } | ||
2988 | |||
2989 | static int sky2_resume(struct pci_dev *pdev) | ||
2990 | { | ||
2991 | struct sky2_hw *hw = pci_get_drvdata(pdev); | ||
2992 | int i; | ||
2993 | |||
2994 | pci_restore_state(pdev); | ||
2995 | pci_enable_wake(pdev, PCI_D0, 0); | ||
2996 | sky2_set_power_state(hw, PCI_D0); | ||
2997 | |||
2998 | sky2_reset(hw); | ||
2999 | |||
3000 | for (i = 0; i < 2; i++) { | ||
3001 | struct net_device *dev = hw->dev[i]; | ||
3002 | if (dev) { | ||
3003 | if (netif_running(dev)) { | ||
3004 | netif_device_attach(dev); | ||
3005 | sky2_up(dev); | ||
3006 | } | ||
3007 | } | ||
3008 | } | ||
3009 | return 0; | ||
3010 | } | ||
3011 | #endif | ||
3012 | |||
3013 | static struct pci_driver sky2_driver = { | ||
3014 | .name = DRV_NAME, | ||
3015 | .id_table = sky2_id_table, | ||
3016 | .probe = sky2_probe, | ||
3017 | .remove = __devexit_p(sky2_remove), | ||
3018 | #ifdef CONFIG_PM | ||
3019 | .suspend = sky2_suspend, | ||
3020 | .resume = sky2_resume, | ||
3021 | #endif | ||
3022 | }; | ||
3023 | |||
3024 | static int __init sky2_init_module(void) | ||
3025 | { | ||
3026 | return pci_module_init(&sky2_driver); | ||
3027 | } | ||
3028 | |||
3029 | static void __exit sky2_cleanup_module(void) | ||
3030 | { | ||
3031 | pci_unregister_driver(&sky2_driver); | ||
3032 | } | ||
3033 | |||
3034 | module_init(sky2_init_module); | ||
3035 | module_exit(sky2_cleanup_module); | ||
3036 | |||
3037 | MODULE_DESCRIPTION("Marvell Yukon 2 Gigabit Ethernet driver"); | ||
3038 | MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>"); | ||
3039 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h new file mode 100644 index 000000000000..629d08f170fd --- /dev/null +++ b/drivers/net/sky2.h | |||
@@ -0,0 +1,1910 @@ | |||
1 | /* | ||
2 | * Definitions for the new Marvell Yukon 2 driver. | ||
3 | */ | ||
4 | #ifndef _SKY2_H | ||
5 | #define _SKY2_H | ||
6 | |||
7 | /* PCI config registers */ | ||
8 | #define PCI_DEV_REG1 0x40 | ||
9 | #define PCI_DEV_REG2 0x44 | ||
10 | #define PCI_DEV_STATUS 0x7c | ||
11 | #define PCI_OS_PCI_X (1<<26) | ||
12 | |||
13 | #define PEX_LNK_STAT 0xf2 | ||
14 | #define PEX_UNC_ERR_STAT 0x104 | ||
15 | #define PEX_DEV_CTRL 0xe8 | ||
16 | |||
17 | /* Yukon-2 */ | ||
18 | enum pci_dev_reg_1 { | ||
19 | PCI_Y2_PIG_ENA = 1<<31, /* Enable Plug-in-Go (YUKON-2) */ | ||
20 | PCI_Y2_DLL_DIS = 1<<30, /* Disable PCI DLL (YUKON-2) */ | ||
21 | PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */ | ||
22 | PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */ | ||
23 | PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */ | ||
24 | PCI_Y2_PHY1_POWD = 1<<26, /* Set PHY 1 to Power Down (YUKON-2) */ | ||
25 | }; | ||
26 | |||
27 | enum pci_dev_reg_2 { | ||
28 | PCI_VPD_WR_THR = 0xffL<<24, /* Bit 31..24: VPD Write Threshold */ | ||
29 | PCI_DEV_SEL = 0x7fL<<17, /* Bit 23..17: EEPROM Device Select */ | ||
30 | PCI_VPD_ROM_SZ = 7L<<14, /* Bit 16..14: VPD ROM Size */ | ||
31 | |||
32 | PCI_PATCH_DIR = 0xfL<<8, /* Bit 11.. 8: Ext Patches dir 3..0 */ | ||
33 | PCI_EXT_PATCHS = 0xfL<<4, /* Bit 7.. 4: Extended Patches 3..0 */ | ||
34 | PCI_EN_DUMMY_RD = 1<<3, /* Enable Dummy Read */ | ||
35 | PCI_REV_DESC = 1<<2, /* Reverse Desc. Bytes */ | ||
36 | |||
37 | PCI_USEDATA64 = 1<<0, /* Use 64Bit Data bus ext */ | ||
38 | }; | ||
39 | |||
40 | |||
41 | #define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ | ||
42 | PCI_STATUS_SIG_SYSTEM_ERROR | \ | ||
43 | PCI_STATUS_REC_MASTER_ABORT | \ | ||
44 | PCI_STATUS_REC_TARGET_ABORT | \ | ||
45 | PCI_STATUS_PARITY) | ||
46 | |||
47 | enum pex_dev_ctrl { | ||
48 | PEX_DC_MAX_RRS_MSK = 7<<12, /* Bit 14..12: Max. Read Request Size */ | ||
49 | PEX_DC_EN_NO_SNOOP = 1<<11,/* Enable No Snoop */ | ||
50 | PEX_DC_EN_AUX_POW = 1<<10,/* Enable AUX Power */ | ||
51 | PEX_DC_EN_PHANTOM = 1<<9, /* Enable Phantom Functions */ | ||
52 | PEX_DC_EN_EXT_TAG = 1<<8, /* Enable Extended Tag Field */ | ||
53 | PEX_DC_MAX_PLS_MSK = 7<<5, /* Bit 7.. 5: Max. Payload Size Mask */ | ||
54 | PEX_DC_EN_REL_ORD = 1<<4, /* Enable Relaxed Ordering */ | ||
55 | PEX_DC_EN_UNS_RQ_RP = 1<<3, /* Enable Unsupported Request Reporting */ | ||
56 | PEX_DC_EN_FAT_ER_RP = 1<<2, /* Enable Fatal Error Reporting */ | ||
57 | PEX_DC_EN_NFA_ER_RP = 1<<1, /* Enable Non-Fatal Error Reporting */ | ||
58 | PEX_DC_EN_COR_ER_RP = 1<<0, /* Enable Correctable Error Reporting */ | ||
59 | }; | ||
60 | #define PEX_DC_MAX_RD_RQ_SIZE(x) (((x)<<12) & PEX_DC_MAX_RRS_MSK) | ||
61 | |||
62 | /* PEX_UNC_ERR_STAT PEX Uncorrectable Errors Status Register (Yukon-2) */ | ||
63 | enum pex_err { | ||
64 | PEX_UNSUP_REQ = 1<<20, /* Unsupported Request Error */ | ||
65 | |||
66 | PEX_MALFOR_TLP = 1<<18, /* Malformed TLP */ | ||
67 | |||
68 | PEX_UNEXP_COMP = 1<<16, /* Unexpected Completion */ | ||
69 | |||
70 | PEX_COMP_TO = 1<<14, /* Completion Timeout */ | ||
71 | PEX_FLOW_CTRL_P = 1<<13, /* Flow Control Protocol Error */ | ||
72 | PEX_POIS_TLP = 1<<12, /* Poisoned TLP */ | ||
73 | |||
74 | PEX_DATA_LINK_P = 1<<4, /* Data Link Protocol Error */ | ||
75 | PEX_FATAL_ERRORS= (PEX_MALFOR_TLP | PEX_FLOW_CTRL_P | PEX_DATA_LINK_P), | ||
76 | }; | ||
77 | |||
78 | |||
79 | enum csr_regs { | ||
80 | B0_RAP = 0x0000, | ||
81 | B0_CTST = 0x0004, | ||
82 | B0_Y2LED = 0x0005, | ||
83 | B0_POWER_CTRL = 0x0007, | ||
84 | B0_ISRC = 0x0008, | ||
85 | B0_IMSK = 0x000c, | ||
86 | B0_HWE_ISRC = 0x0010, | ||
87 | B0_HWE_IMSK = 0x0014, | ||
88 | |||
89 | /* Special ISR registers (Yukon-2 only) */ | ||
90 | B0_Y2_SP_ISRC2 = 0x001c, | ||
91 | B0_Y2_SP_ISRC3 = 0x0020, | ||
92 | B0_Y2_SP_EISR = 0x0024, | ||
93 | B0_Y2_SP_LISR = 0x0028, | ||
94 | B0_Y2_SP_ICR = 0x002c, | ||
95 | |||
96 | B2_MAC_1 = 0x0100, | ||
97 | B2_MAC_2 = 0x0108, | ||
98 | B2_MAC_3 = 0x0110, | ||
99 | B2_CONN_TYP = 0x0118, | ||
100 | B2_PMD_TYP = 0x0119, | ||
101 | B2_MAC_CFG = 0x011a, | ||
102 | B2_CHIP_ID = 0x011b, | ||
103 | B2_E_0 = 0x011c, | ||
104 | |||
105 | B2_Y2_CLK_GATE = 0x011d, | ||
106 | B2_Y2_HW_RES = 0x011e, | ||
107 | B2_E_3 = 0x011f, | ||
108 | B2_Y2_CLK_CTRL = 0x0120, | ||
109 | |||
110 | B2_TI_INI = 0x0130, | ||
111 | B2_TI_VAL = 0x0134, | ||
112 | B2_TI_CTRL = 0x0138, | ||
113 | B2_TI_TEST = 0x0139, | ||
114 | |||
115 | B2_TST_CTRL1 = 0x0158, | ||
116 | B2_TST_CTRL2 = 0x0159, | ||
117 | B2_GP_IO = 0x015c, | ||
118 | |||
119 | B2_I2C_CTRL = 0x0160, | ||
120 | B2_I2C_DATA = 0x0164, | ||
121 | B2_I2C_IRQ = 0x0168, | ||
122 | B2_I2C_SW = 0x016c, | ||
123 | |||
124 | B3_RAM_ADDR = 0x0180, | ||
125 | B3_RAM_DATA_LO = 0x0184, | ||
126 | B3_RAM_DATA_HI = 0x0188, | ||
127 | |||
128 | /* RAM Interface Registers */ | ||
129 | /* Yukon-2: use RAM_BUFFER() to access the RAM buffer */ | ||
130 | /* | ||
131 | * The HW-Spec. calls this registers Timeout Value 0..11. But this names are | ||
132 | * not usable in SW. Please notice these are NOT real timeouts, these are | ||
133 | * the number of qWords transferred continuously. | ||
134 | */ | ||
135 | #define RAM_BUFFER(port, reg) (reg | (port <<6)) | ||
136 | |||
137 | B3_RI_WTO_R1 = 0x0190, | ||
138 | B3_RI_WTO_XA1 = 0x0191, | ||
139 | B3_RI_WTO_XS1 = 0x0192, | ||
140 | B3_RI_RTO_R1 = 0x0193, | ||
141 | B3_RI_RTO_XA1 = 0x0194, | ||
142 | B3_RI_RTO_XS1 = 0x0195, | ||
143 | B3_RI_WTO_R2 = 0x0196, | ||
144 | B3_RI_WTO_XA2 = 0x0197, | ||
145 | B3_RI_WTO_XS2 = 0x0198, | ||
146 | B3_RI_RTO_R2 = 0x0199, | ||
147 | B3_RI_RTO_XA2 = 0x019a, | ||
148 | B3_RI_RTO_XS2 = 0x019b, | ||
149 | B3_RI_TO_VAL = 0x019c, | ||
150 | B3_RI_CTRL = 0x01a0, | ||
151 | B3_RI_TEST = 0x01a2, | ||
152 | B3_MA_TOINI_RX1 = 0x01b0, | ||
153 | B3_MA_TOINI_RX2 = 0x01b1, | ||
154 | B3_MA_TOINI_TX1 = 0x01b2, | ||
155 | B3_MA_TOINI_TX2 = 0x01b3, | ||
156 | B3_MA_TOVAL_RX1 = 0x01b4, | ||
157 | B3_MA_TOVAL_RX2 = 0x01b5, | ||
158 | B3_MA_TOVAL_TX1 = 0x01b6, | ||
159 | B3_MA_TOVAL_TX2 = 0x01b7, | ||
160 | B3_MA_TO_CTRL = 0x01b8, | ||
161 | B3_MA_TO_TEST = 0x01ba, | ||
162 | B3_MA_RCINI_RX1 = 0x01c0, | ||
163 | B3_MA_RCINI_RX2 = 0x01c1, | ||
164 | B3_MA_RCINI_TX1 = 0x01c2, | ||
165 | B3_MA_RCINI_TX2 = 0x01c3, | ||
166 | B3_MA_RCVAL_RX1 = 0x01c4, | ||
167 | B3_MA_RCVAL_RX2 = 0x01c5, | ||
168 | B3_MA_RCVAL_TX1 = 0x01c6, | ||
169 | B3_MA_RCVAL_TX2 = 0x01c7, | ||
170 | B3_MA_RC_CTRL = 0x01c8, | ||
171 | B3_MA_RC_TEST = 0x01ca, | ||
172 | B3_PA_TOINI_RX1 = 0x01d0, | ||
173 | B3_PA_TOINI_RX2 = 0x01d4, | ||
174 | B3_PA_TOINI_TX1 = 0x01d8, | ||
175 | B3_PA_TOINI_TX2 = 0x01dc, | ||
176 | B3_PA_TOVAL_RX1 = 0x01e0, | ||
177 | B3_PA_TOVAL_RX2 = 0x01e4, | ||
178 | B3_PA_TOVAL_TX1 = 0x01e8, | ||
179 | B3_PA_TOVAL_TX2 = 0x01ec, | ||
180 | B3_PA_CTRL = 0x01f0, | ||
181 | B3_PA_TEST = 0x01f2, | ||
182 | |||
183 | Y2_CFG_SPC = 0x1c00, | ||
184 | }; | ||
185 | |||
186 | /* B0_CTST 16 bit Control/Status register */ | ||
187 | enum { | ||
188 | Y2_VMAIN_AVAIL = 1<<17,/* VMAIN available (YUKON-2 only) */ | ||
189 | Y2_VAUX_AVAIL = 1<<16,/* VAUX available (YUKON-2 only) */ | ||
190 | Y2_ASF_ENABLE = 1<<13,/* ASF Unit Enable (YUKON-2 only) */ | ||
191 | Y2_ASF_DISABLE = 1<<12,/* ASF Unit Disable (YUKON-2 only) */ | ||
192 | Y2_CLK_RUN_ENA = 1<<11,/* CLK_RUN Enable (YUKON-2 only) */ | ||
193 | Y2_CLK_RUN_DIS = 1<<10,/* CLK_RUN Disable (YUKON-2 only) */ | ||
194 | Y2_LED_STAT_ON = 1<<9, /* Status LED On (YUKON-2 only) */ | ||
195 | Y2_LED_STAT_OFF = 1<<8, /* Status LED Off (YUKON-2 only) */ | ||
196 | |||
197 | CS_ST_SW_IRQ = 1<<7, /* Set IRQ SW Request */ | ||
198 | CS_CL_SW_IRQ = 1<<6, /* Clear IRQ SW Request */ | ||
199 | CS_STOP_DONE = 1<<5, /* Stop Master is finished */ | ||
200 | CS_STOP_MAST = 1<<4, /* Command Bit to stop the master */ | ||
201 | CS_MRST_CLR = 1<<3, /* Clear Master reset */ | ||
202 | CS_MRST_SET = 1<<2, /* Set Master reset */ | ||
203 | CS_RST_CLR = 1<<1, /* Clear Software reset */ | ||
204 | CS_RST_SET = 1, /* Set Software reset */ | ||
205 | }; | ||
206 | |||
207 | /* B0_LED 8 Bit LED register */ | ||
208 | enum { | ||
209 | /* Bit 7.. 2: reserved */ | ||
210 | LED_STAT_ON = 1<<1, /* Status LED on */ | ||
211 | LED_STAT_OFF = 1, /* Status LED off */ | ||
212 | }; | ||
213 | |||
214 | /* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */ | ||
215 | enum { | ||
216 | PC_VAUX_ENA = 1<<7, /* Switch VAUX Enable */ | ||
217 | PC_VAUX_DIS = 1<<6, /* Switch VAUX Disable */ | ||
218 | PC_VCC_ENA = 1<<5, /* Switch VCC Enable */ | ||
219 | PC_VCC_DIS = 1<<4, /* Switch VCC Disable */ | ||
220 | PC_VAUX_ON = 1<<3, /* Switch VAUX On */ | ||
221 | PC_VAUX_OFF = 1<<2, /* Switch VAUX Off */ | ||
222 | PC_VCC_ON = 1<<1, /* Switch VCC On */ | ||
223 | PC_VCC_OFF = 1<<0, /* Switch VCC Off */ | ||
224 | }; | ||
225 | |||
226 | /* B2_IRQM_MSK 32 bit IRQ Moderation Mask */ | ||
227 | |||
228 | /* B0_Y2_SP_ISRC2 32 bit Special Interrupt Source Reg 2 */ | ||
229 | /* B0_Y2_SP_ISRC3 32 bit Special Interrupt Source Reg 3 */ | ||
230 | /* B0_Y2_SP_EISR 32 bit Enter ISR Reg */ | ||
231 | /* B0_Y2_SP_LISR 32 bit Leave ISR Reg */ | ||
232 | enum { | ||
233 | Y2_IS_HW_ERR = 1<<31, /* Interrupt HW Error */ | ||
234 | Y2_IS_STAT_BMU = 1<<30, /* Status BMU Interrupt */ | ||
235 | Y2_IS_ASF = 1<<29, /* ASF subsystem Interrupt */ | ||
236 | |||
237 | Y2_IS_POLL_CHK = 1<<27, /* Check IRQ from polling unit */ | ||
238 | Y2_IS_TWSI_RDY = 1<<26, /* IRQ on end of TWSI Tx */ | ||
239 | Y2_IS_IRQ_SW = 1<<25, /* SW forced IRQ */ | ||
240 | Y2_IS_TIMINT = 1<<24, /* IRQ from Timer */ | ||
241 | |||
242 | Y2_IS_IRQ_PHY2 = 1<<12, /* Interrupt from PHY 2 */ | ||
243 | Y2_IS_IRQ_MAC2 = 1<<11, /* Interrupt from MAC 2 */ | ||
244 | Y2_IS_CHK_RX2 = 1<<10, /* Descriptor error Rx 2 */ | ||
245 | Y2_IS_CHK_TXS2 = 1<<9, /* Descriptor error TXS 2 */ | ||
246 | Y2_IS_CHK_TXA2 = 1<<8, /* Descriptor error TXA 2 */ | ||
247 | |||
248 | Y2_IS_IRQ_PHY1 = 1<<4, /* Interrupt from PHY 1 */ | ||
249 | Y2_IS_IRQ_MAC1 = 1<<3, /* Interrupt from MAC 1 */ | ||
250 | Y2_IS_CHK_RX1 = 1<<2, /* Descriptor error Rx 1 */ | ||
251 | Y2_IS_CHK_TXS1 = 1<<1, /* Descriptor error TXS 1 */ | ||
252 | Y2_IS_CHK_TXA1 = 1<<0, /* Descriptor error TXA 1 */ | ||
253 | |||
254 | Y2_IS_BASE = Y2_IS_HW_ERR | Y2_IS_STAT_BMU | | ||
255 | Y2_IS_POLL_CHK | Y2_IS_TWSI_RDY | | ||
256 | Y2_IS_IRQ_SW | Y2_IS_TIMINT, | ||
257 | Y2_IS_PORT_1 = Y2_IS_IRQ_PHY1 | Y2_IS_IRQ_MAC1 | | ||
258 | Y2_IS_CHK_RX1 | Y2_IS_CHK_TXA1 | Y2_IS_CHK_TXS1, | ||
259 | Y2_IS_PORT_2 = Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2 | | ||
260 | Y2_IS_CHK_RX2 | Y2_IS_CHK_TXA2 | Y2_IS_CHK_TXS2, | ||
261 | }; | ||
262 | |||
263 | /* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ | ||
264 | enum { | ||
265 | IS_ERR_MSK = 0x00003fff,/* All Error bits */ | ||
266 | |||
267 | IS_IRQ_TIST_OV = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */ | ||
268 | IS_IRQ_SENSOR = 1<<12, /* IRQ from Sensor (YUKON only) */ | ||
269 | IS_IRQ_MST_ERR = 1<<11, /* IRQ master error detected */ | ||
270 | IS_IRQ_STAT = 1<<10, /* IRQ status exception */ | ||
271 | IS_NO_STAT_M1 = 1<<9, /* No Rx Status from MAC 1 */ | ||
272 | IS_NO_STAT_M2 = 1<<8, /* No Rx Status from MAC 2 */ | ||
273 | IS_NO_TIST_M1 = 1<<7, /* No Time Stamp from MAC 1 */ | ||
274 | IS_NO_TIST_M2 = 1<<6, /* No Time Stamp from MAC 2 */ | ||
275 | IS_RAM_RD_PAR = 1<<5, /* RAM Read Parity Error */ | ||
276 | IS_RAM_WR_PAR = 1<<4, /* RAM Write Parity Error */ | ||
277 | IS_M1_PAR_ERR = 1<<3, /* MAC 1 Parity Error */ | ||
278 | IS_M2_PAR_ERR = 1<<2, /* MAC 2 Parity Error */ | ||
279 | IS_R1_PAR_ERR = 1<<1, /* Queue R1 Parity Error */ | ||
280 | IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */ | ||
281 | }; | ||
282 | |||
283 | /* Hardware error interrupt mask for Yukon 2 */ | ||
284 | enum { | ||
285 | Y2_IS_TIST_OV = 1<<29,/* Time Stamp Timer overflow interrupt */ | ||
286 | Y2_IS_SENSOR = 1<<28, /* Sensor interrupt */ | ||
287 | Y2_IS_MST_ERR = 1<<27, /* Master error interrupt */ | ||
288 | Y2_IS_IRQ_STAT = 1<<26, /* Status exception interrupt */ | ||
289 | Y2_IS_PCI_EXP = 1<<25, /* PCI-Express interrupt */ | ||
290 | Y2_IS_PCI_NEXP = 1<<24, /* PCI-Express error similar to PCI error */ | ||
291 | /* Link 2 */ | ||
292 | Y2_IS_PAR_RD2 = 1<<13, /* Read RAM parity error interrupt */ | ||
293 | Y2_IS_PAR_WR2 = 1<<12, /* Write RAM parity error interrupt */ | ||
294 | Y2_IS_PAR_MAC2 = 1<<11, /* MAC hardware fault interrupt */ | ||
295 | Y2_IS_PAR_RX2 = 1<<10, /* Parity Error Rx Queue 2 */ | ||
296 | Y2_IS_TCP_TXS2 = 1<<9, /* TCP length mismatch sync Tx queue IRQ */ | ||
297 | Y2_IS_TCP_TXA2 = 1<<8, /* TCP length mismatch async Tx queue IRQ */ | ||
298 | /* Link 1 */ | ||
299 | Y2_IS_PAR_RD1 = 1<<5, /* Read RAM parity error interrupt */ | ||
300 | Y2_IS_PAR_WR1 = 1<<4, /* Write RAM parity error interrupt */ | ||
301 | Y2_IS_PAR_MAC1 = 1<<3, /* MAC hardware fault interrupt */ | ||
302 | Y2_IS_PAR_RX1 = 1<<2, /* Parity Error Rx Queue 1 */ | ||
303 | Y2_IS_TCP_TXS1 = 1<<1, /* TCP length mismatch sync Tx queue IRQ */ | ||
304 | Y2_IS_TCP_TXA1 = 1<<0, /* TCP length mismatch async Tx queue IRQ */ | ||
305 | |||
306 | Y2_HWE_L1_MASK = Y2_IS_PAR_RD1 | Y2_IS_PAR_WR1 | Y2_IS_PAR_MAC1 | | ||
307 | Y2_IS_PAR_RX1 | Y2_IS_TCP_TXS1| Y2_IS_TCP_TXA1, | ||
308 | Y2_HWE_L2_MASK = Y2_IS_PAR_RD2 | Y2_IS_PAR_WR2 | Y2_IS_PAR_MAC2 | | ||
309 | Y2_IS_PAR_RX2 | Y2_IS_TCP_TXS2| Y2_IS_TCP_TXA2, | ||
310 | |||
311 | Y2_HWE_ALL_MASK = Y2_IS_TIST_OV | Y2_IS_MST_ERR | Y2_IS_IRQ_STAT | | ||
312 | Y2_IS_PCI_EXP | Y2_IS_PCI_NEXP | | ||
313 | Y2_HWE_L1_MASK | Y2_HWE_L2_MASK, | ||
314 | }; | ||
315 | |||
316 | /* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */ | ||
317 | enum { | ||
318 | DPT_START = 1<<1, | ||
319 | DPT_STOP = 1<<0, | ||
320 | }; | ||
321 | |||
322 | /* B2_TST_CTRL1 8 bit Test Control Register 1 */ | ||
323 | enum { | ||
324 | TST_FRC_DPERR_MR = 1<<7, /* force DATAPERR on MST RD */ | ||
325 | TST_FRC_DPERR_MW = 1<<6, /* force DATAPERR on MST WR */ | ||
326 | TST_FRC_DPERR_TR = 1<<5, /* force DATAPERR on TRG RD */ | ||
327 | TST_FRC_DPERR_TW = 1<<4, /* force DATAPERR on TRG WR */ | ||
328 | TST_FRC_APERR_M = 1<<3, /* force ADDRPERR on MST */ | ||
329 | TST_FRC_APERR_T = 1<<2, /* force ADDRPERR on TRG */ | ||
330 | TST_CFG_WRITE_ON = 1<<1, /* Enable Config Reg WR */ | ||
331 | TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */ | ||
332 | }; | ||
333 | |||
334 | /* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ | ||
335 | enum { | ||
336 | CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */ | ||
337 | /* Bit 3.. 2: reserved */ | ||
338 | CFG_DIS_M2_CLK = 1<<1, /* Disable Clock for 2nd MAC */ | ||
339 | CFG_SNG_MAC = 1<<0, /* MAC Config: 0=2 MACs / 1=1 MAC*/ | ||
340 | }; | ||
341 | |||
342 | /* B2_CHIP_ID 8 bit Chip Identification Number */ | ||
343 | enum { | ||
344 | CHIP_ID_GENESIS = 0x0a, /* Chip ID for GENESIS */ | ||
345 | CHIP_ID_YUKON = 0xb0, /* Chip ID for YUKON */ | ||
346 | CHIP_ID_YUKON_LITE = 0xb1, /* Chip ID for YUKON-Lite (Rev. A1-A3) */ | ||
347 | CHIP_ID_YUKON_LP = 0xb2, /* Chip ID for YUKON-LP */ | ||
348 | CHIP_ID_YUKON_XL = 0xb3, /* Chip ID for YUKON-2 XL */ | ||
349 | CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */ | ||
350 | CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */ | ||
351 | |||
352 | CHIP_REV_YU_EC_A1 = 0, /* Chip Rev. for Yukon-EC A1/A0 */ | ||
353 | CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */ | ||
354 | CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */ | ||
355 | }; | ||
356 | |||
357 | /* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */ | ||
358 | enum { | ||
359 | Y2_STATUS_LNK2_INAC = 1<<7, /* Status Link 2 inactive (0 = active) */ | ||
360 | Y2_CLK_GAT_LNK2_DIS = 1<<6, /* Disable clock gating Link 2 */ | ||
361 | Y2_COR_CLK_LNK2_DIS = 1<<5, /* Disable Core clock Link 2 */ | ||
362 | Y2_PCI_CLK_LNK2_DIS = 1<<4, /* Disable PCI clock Link 2 */ | ||
363 | Y2_STATUS_LNK1_INAC = 1<<3, /* Status Link 1 inactive (0 = active) */ | ||
364 | Y2_CLK_GAT_LNK1_DIS = 1<<2, /* Disable clock gating Link 1 */ | ||
365 | Y2_COR_CLK_LNK1_DIS = 1<<1, /* Disable Core clock Link 1 */ | ||
366 | Y2_PCI_CLK_LNK1_DIS = 1<<0, /* Disable PCI clock Link 1 */ | ||
367 | }; | ||
368 | |||
369 | /* B2_Y2_HW_RES 8 bit HW Resources (Yukon-2 only) */ | ||
370 | enum { | ||
371 | CFG_LED_MODE_MSK = 7<<2, /* Bit 4.. 2: LED Mode Mask */ | ||
372 | CFG_LINK_2_AVAIL = 1<<1, /* Link 2 available */ | ||
373 | CFG_LINK_1_AVAIL = 1<<0, /* Link 1 available */ | ||
374 | }; | ||
375 | #define CFG_LED_MODE(x) (((x) & CFG_LED_MODE_MSK) >> 2) | ||
376 | #define CFG_DUAL_MAC_MSK (CFG_LINK_2_AVAIL | CFG_LINK_1_AVAIL) | ||
377 | |||
378 | |||
379 | /* B2_Y2_CLK_CTRL 32 bit Clock Frequency Control Register (Yukon-2/EC) */ | ||
380 | enum { | ||
381 | Y2_CLK_DIV_VAL_MSK = 0xff<<16,/* Bit 23..16: Clock Divisor Value */ | ||
382 | #define Y2_CLK_DIV_VAL(x) (((x)<<16) & Y2_CLK_DIV_VAL_MSK) | ||
383 | Y2_CLK_DIV_VAL2_MSK = 7<<21, /* Bit 23..21: Clock Divisor Value */ | ||
384 | Y2_CLK_SELECT2_MSK = 0x1f<<16,/* Bit 20..16: Clock Select */ | ||
385 | #define Y2_CLK_DIV_VAL_2(x) (((x)<<21) & Y2_CLK_DIV_VAL2_MSK) | ||
386 | #define Y2_CLK_SEL_VAL_2(x) (((x)<<16) & Y2_CLK_SELECT2_MSK) | ||
387 | Y2_CLK_DIV_ENA = 1<<1, /* Enable Core Clock Division */ | ||
388 | Y2_CLK_DIV_DIS = 1<<0, /* Disable Core Clock Division */ | ||
389 | }; | ||
390 | |||
391 | /* B2_TI_CTRL 8 bit Timer control */ | ||
392 | /* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */ | ||
393 | enum { | ||
394 | TIM_START = 1<<2, /* Start Timer */ | ||
395 | TIM_STOP = 1<<1, /* Stop Timer */ | ||
396 | TIM_CLR_IRQ = 1<<0, /* Clear Timer IRQ (!IRQM) */ | ||
397 | }; | ||
398 | |||
399 | /* B2_TI_TEST 8 Bit Timer Test */ | ||
400 | /* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */ | ||
401 | /* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ | ||
402 | enum { | ||
403 | TIM_T_ON = 1<<2, /* Test mode on */ | ||
404 | TIM_T_OFF = 1<<1, /* Test mode off */ | ||
405 | TIM_T_STEP = 1<<0, /* Test step */ | ||
406 | }; | ||
407 | |||
408 | /* B3_RAM_ADDR 32 bit RAM Address, to read or write */ | ||
409 | /* Bit 31..19: reserved */ | ||
410 | #define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */ | ||
411 | /* RAM Interface Registers */ | ||
412 | |||
413 | /* B3_RI_CTRL 16 bit RAM Interface Control Register */ | ||
414 | enum { | ||
415 | RI_CLR_RD_PERR = 1<<9, /* Clear IRQ RAM Read Parity Err */ | ||
416 | RI_CLR_WR_PERR = 1<<8, /* Clear IRQ RAM Write Parity Err*/ | ||
417 | |||
418 | RI_RST_CLR = 1<<1, /* Clear RAM Interface Reset */ | ||
419 | RI_RST_SET = 1<<0, /* Set RAM Interface Reset */ | ||
420 | }; | ||
421 | |||
422 | #define SK_RI_TO_53 36 /* RAM interface timeout */ | ||
423 | |||
424 | |||
425 | /* Port related registers FIFO, and Arbiter */ | ||
426 | #define SK_REG(port,reg) (((port)<<7)+(reg)) | ||
427 | |||
428 | /* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */ | ||
429 | /* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ | ||
430 | /* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ | ||
431 | /* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ | ||
432 | /* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ | ||
433 | |||
434 | #define TXA_MAX_VAL 0x00ffffffUL /* Bit 23.. 0: Max TXA Timer/Cnt Val */ | ||
435 | |||
436 | /* TXA_CTRL 8 bit Tx Arbiter Control Register */ | ||
437 | enum { | ||
438 | TXA_ENA_FSYNC = 1<<7, /* Enable force of sync Tx queue */ | ||
439 | TXA_DIS_FSYNC = 1<<6, /* Disable force of sync Tx queue */ | ||
440 | TXA_ENA_ALLOC = 1<<5, /* Enable alloc of free bandwidth */ | ||
441 | TXA_DIS_ALLOC = 1<<4, /* Disable alloc of free bandwidth */ | ||
442 | TXA_START_RC = 1<<3, /* Start sync Rate Control */ | ||
443 | TXA_STOP_RC = 1<<2, /* Stop sync Rate Control */ | ||
444 | TXA_ENA_ARB = 1<<1, /* Enable Tx Arbiter */ | ||
445 | TXA_DIS_ARB = 1<<0, /* Disable Tx Arbiter */ | ||
446 | }; | ||
447 | |||
448 | /* | ||
449 | * Bank 4 - 5 | ||
450 | */ | ||
451 | /* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */ | ||
452 | enum { | ||
453 | TXA_ITI_INI = 0x0200,/* 32 bit Tx Arb Interval Timer Init Val*/ | ||
454 | TXA_ITI_VAL = 0x0204,/* 32 bit Tx Arb Interval Timer Value */ | ||
455 | TXA_LIM_INI = 0x0208,/* 32 bit Tx Arb Limit Counter Init Val */ | ||
456 | TXA_LIM_VAL = 0x020c,/* 32 bit Tx Arb Limit Counter Value */ | ||
457 | TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */ | ||
458 | TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */ | ||
459 | TXA_STAT = 0x0212,/* 8 bit Tx Arbiter Status Register */ | ||
460 | }; | ||
461 | |||
462 | |||
463 | enum { | ||
464 | B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */ | ||
465 | B7_CFG_SPC = 0x0380,/* copy of the Configuration register */ | ||
466 | B8_RQ1_REGS = 0x0400,/* Receive Queue 1 */ | ||
467 | B8_RQ2_REGS = 0x0480,/* Receive Queue 2 */ | ||
468 | B8_TS1_REGS = 0x0600,/* Transmit sync queue 1 */ | ||
469 | B8_TA1_REGS = 0x0680,/* Transmit async queue 1 */ | ||
470 | B8_TS2_REGS = 0x0700,/* Transmit sync queue 2 */ | ||
471 | B8_TA2_REGS = 0x0780,/* Transmit sync queue 2 */ | ||
472 | B16_RAM_REGS = 0x0800,/* RAM Buffer Registers */ | ||
473 | }; | ||
474 | |||
475 | /* Queue Register Offsets, use Q_ADDR() to access */ | ||
476 | enum { | ||
477 | B8_Q_REGS = 0x0400, /* base of Queue registers */ | ||
478 | Q_D = 0x00, /* 8*32 bit Current Descriptor */ | ||
479 | Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */ | ||
480 | Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */ | ||
481 | Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */ | ||
482 | Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */ | ||
483 | Q_BC = 0x30, /* 32 bit Current Byte Counter */ | ||
484 | Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */ | ||
485 | Q_F = 0x38, /* 32 bit Flag Register */ | ||
486 | Q_T1 = 0x3c, /* 32 bit Test Register 1 */ | ||
487 | Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */ | ||
488 | Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */ | ||
489 | Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */ | ||
490 | Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */ | ||
491 | Q_T2 = 0x40, /* 32 bit Test Register 2 */ | ||
492 | Q_T3 = 0x44, /* 32 bit Test Register 3 */ | ||
493 | |||
494 | /* Yukon-2 */ | ||
495 | Q_DONE = 0x24, /* 16 bit Done Index (Yukon-2 only) */ | ||
496 | Q_WM = 0x40, /* 16 bit FIFO Watermark */ | ||
497 | Q_AL = 0x42, /* 8 bit FIFO Alignment */ | ||
498 | Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */ | ||
499 | Q_RSL = 0x46, /* 8 bit FIFO Read Shadow Level */ | ||
500 | Q_RP = 0x48, /* 8 bit FIFO Read Pointer */ | ||
501 | Q_RL = 0x4a, /* 8 bit FIFO Read Level */ | ||
502 | Q_WP = 0x4c, /* 8 bit FIFO Write Pointer */ | ||
503 | Q_WSP = 0x4d, /* 8 bit FIFO Write Shadow Pointer */ | ||
504 | Q_WL = 0x4e, /* 8 bit FIFO Write Level */ | ||
505 | Q_WSL = 0x4f, /* 8 bit FIFO Write Shadow Level */ | ||
506 | }; | ||
507 | #define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs)) | ||
508 | |||
509 | |||
510 | /* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/ | ||
511 | enum { | ||
512 | Y2_B8_PREF_REGS = 0x0450, | ||
513 | |||
514 | PREF_UNIT_CTRL = 0x00, /* 32 bit Control register */ | ||
515 | PREF_UNIT_LAST_IDX = 0x04, /* 16 bit Last Index */ | ||
516 | PREF_UNIT_ADDR_LO = 0x08, /* 32 bit List start addr, low part */ | ||
517 | PREF_UNIT_ADDR_HI = 0x0c, /* 32 bit List start addr, high part*/ | ||
518 | PREF_UNIT_GET_IDX = 0x10, /* 16 bit Get Index */ | ||
519 | PREF_UNIT_PUT_IDX = 0x14, /* 16 bit Put Index */ | ||
520 | PREF_UNIT_FIFO_WP = 0x20, /* 8 bit FIFO write pointer */ | ||
521 | PREF_UNIT_FIFO_RP = 0x24, /* 8 bit FIFO read pointer */ | ||
522 | PREF_UNIT_FIFO_WM = 0x28, /* 8 bit FIFO watermark */ | ||
523 | PREF_UNIT_FIFO_LEV = 0x2c, /* 8 bit FIFO level */ | ||
524 | |||
525 | PREF_UNIT_MASK_IDX = 0x0fff, | ||
526 | }; | ||
527 | #define Y2_QADDR(q,reg) (Y2_B8_PREF_REGS + (q) + (reg)) | ||
528 | |||
529 | /* RAM Buffer Register Offsets */ | ||
530 | enum { | ||
531 | |||
532 | RB_START = 0x00,/* 32 bit RAM Buffer Start Address */ | ||
533 | RB_END = 0x04,/* 32 bit RAM Buffer End Address */ | ||
534 | RB_WP = 0x08,/* 32 bit RAM Buffer Write Pointer */ | ||
535 | RB_RP = 0x0c,/* 32 bit RAM Buffer Read Pointer */ | ||
536 | RB_RX_UTPP = 0x10,/* 32 bit Rx Upper Threshold, Pause Packet */ | ||
537 | RB_RX_LTPP = 0x14,/* 32 bit Rx Lower Threshold, Pause Packet */ | ||
538 | RB_RX_UTHP = 0x18,/* 32 bit Rx Upper Threshold, High Prio */ | ||
539 | RB_RX_LTHP = 0x1c,/* 32 bit Rx Lower Threshold, High Prio */ | ||
540 | /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */ | ||
541 | RB_PC = 0x20,/* 32 bit RAM Buffer Packet Counter */ | ||
542 | RB_LEV = 0x24,/* 32 bit RAM Buffer Level Register */ | ||
543 | RB_CTRL = 0x28,/* 32 bit RAM Buffer Control Register */ | ||
544 | RB_TST1 = 0x29,/* 8 bit RAM Buffer Test Register 1 */ | ||
545 | RB_TST2 = 0x2a,/* 8 bit RAM Buffer Test Register 2 */ | ||
546 | }; | ||
547 | |||
548 | /* Receive and Transmit Queues */ | ||
549 | enum { | ||
550 | Q_R1 = 0x0000, /* Receive Queue 1 */ | ||
551 | Q_R2 = 0x0080, /* Receive Queue 2 */ | ||
552 | Q_XS1 = 0x0200, /* Synchronous Transmit Queue 1 */ | ||
553 | Q_XA1 = 0x0280, /* Asynchronous Transmit Queue 1 */ | ||
554 | Q_XS2 = 0x0300, /* Synchronous Transmit Queue 2 */ | ||
555 | Q_XA2 = 0x0380, /* Asynchronous Transmit Queue 2 */ | ||
556 | }; | ||
557 | |||
558 | /* Different PHY Types */ | ||
559 | enum { | ||
560 | PHY_ADDR_MARV = 0, | ||
561 | }; | ||
562 | |||
563 | #define RB_ADDR(offs, queue) (B16_RAM_REGS + (queue) + (offs)) | ||
564 | |||
565 | |||
566 | enum { | ||
567 | LNK_SYNC_INI = 0x0c30,/* 32 bit Link Sync Cnt Init Value */ | ||
568 | LNK_SYNC_VAL = 0x0c34,/* 32 bit Link Sync Cnt Current Value */ | ||
569 | LNK_SYNC_CTRL = 0x0c38,/* 8 bit Link Sync Cnt Control Register */ | ||
570 | LNK_SYNC_TST = 0x0c39,/* 8 bit Link Sync Cnt Test Register */ | ||
571 | |||
572 | LNK_LED_REG = 0x0c3c,/* 8 bit Link LED Register */ | ||
573 | |||
574 | /* Receive GMAC FIFO (YUKON and Yukon-2) */ | ||
575 | |||
576 | RX_GMF_EA = 0x0c40,/* 32 bit Rx GMAC FIFO End Address */ | ||
577 | RX_GMF_AF_THR = 0x0c44,/* 32 bit Rx GMAC FIFO Almost Full Thresh. */ | ||
578 | RX_GMF_CTRL_T = 0x0c48,/* 32 bit Rx GMAC FIFO Control/Test */ | ||
579 | RX_GMF_FL_MSK = 0x0c4c,/* 32 bit Rx GMAC FIFO Flush Mask */ | ||
580 | RX_GMF_FL_THR = 0x0c50,/* 32 bit Rx GMAC FIFO Flush Threshold */ | ||
581 | RX_GMF_TR_THR = 0x0c54,/* 32 bit Rx Truncation Threshold (Yukon-2) */ | ||
582 | |||
583 | RX_GMF_VLAN = 0x0c5c,/* 32 bit Rx VLAN Type Register (Yukon-2) */ | ||
584 | RX_GMF_WP = 0x0c60,/* 32 bit Rx GMAC FIFO Write Pointer */ | ||
585 | |||
586 | RX_GMF_WLEV = 0x0c68,/* 32 bit Rx GMAC FIFO Write Level */ | ||
587 | |||
588 | RX_GMF_RP = 0x0c70,/* 32 bit Rx GMAC FIFO Read Pointer */ | ||
589 | |||
590 | RX_GMF_RLEV = 0x0c78,/* 32 bit Rx GMAC FIFO Read Level */ | ||
591 | }; | ||
592 | |||
593 | |||
594 | /* Q_BC 32 bit Current Byte Counter */ | ||
595 | |||
596 | /* BMU Control Status Registers */ | ||
597 | /* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ | ||
598 | /* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ | ||
599 | /* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ | ||
600 | /* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ | ||
601 | /* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ | ||
602 | /* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ | ||
603 | /* Q_CSR 32 bit BMU Control/Status Register */ | ||
604 | |||
605 | /* Rx BMU Control / Status Registers (Yukon-2) */ | ||
606 | enum { | ||
607 | BMU_IDLE = 1<<31, /* BMU Idle State */ | ||
608 | BMU_RX_TCP_PKT = 1<<30, /* Rx TCP Packet (when RSS Hash enabled) */ | ||
609 | BMU_RX_IP_PKT = 1<<29, /* Rx IP Packet (when RSS Hash enabled) */ | ||
610 | |||
611 | BMU_ENA_RX_RSS_HASH = 1<<15, /* Enable Rx RSS Hash */ | ||
612 | BMU_DIS_RX_RSS_HASH = 1<<14, /* Disable Rx RSS Hash */ | ||
613 | BMU_ENA_RX_CHKSUM = 1<<13, /* Enable Rx TCP/IP Checksum Check */ | ||
614 | BMU_DIS_RX_CHKSUM = 1<<12, /* Disable Rx TCP/IP Checksum Check */ | ||
615 | BMU_CLR_IRQ_PAR = 1<<11, /* Clear IRQ on Parity errors (Rx) */ | ||
616 | BMU_CLR_IRQ_TCP = 1<<11, /* Clear IRQ on TCP segment. error (Tx) */ | ||
617 | BMU_CLR_IRQ_CHK = 1<<10, /* Clear IRQ Check */ | ||
618 | BMU_STOP = 1<<9, /* Stop Rx/Tx Queue */ | ||
619 | BMU_START = 1<<8, /* Start Rx/Tx Queue */ | ||
620 | BMU_FIFO_OP_ON = 1<<7, /* FIFO Operational On */ | ||
621 | BMU_FIFO_OP_OFF = 1<<6, /* FIFO Operational Off */ | ||
622 | BMU_FIFO_ENA = 1<<5, /* Enable FIFO */ | ||
623 | BMU_FIFO_RST = 1<<4, /* Reset FIFO */ | ||
624 | BMU_OP_ON = 1<<3, /* BMU Operational On */ | ||
625 | BMU_OP_OFF = 1<<2, /* BMU Operational Off */ | ||
626 | BMU_RST_CLR = 1<<1, /* Clear BMU Reset (Enable) */ | ||
627 | BMU_RST_SET = 1<<0, /* Set BMU Reset */ | ||
628 | |||
629 | BMU_CLR_RESET = BMU_FIFO_RST | BMU_OP_OFF | BMU_RST_CLR, | ||
630 | BMU_OPER_INIT = BMU_CLR_IRQ_PAR | BMU_CLR_IRQ_CHK | BMU_START | | ||
631 | BMU_FIFO_ENA | BMU_OP_ON, | ||
632 | }; | ||
633 | |||
634 | /* Tx BMU Control / Status Registers (Yukon-2) */ | ||
635 | /* Bit 31: same as for Rx */ | ||
636 | enum { | ||
637 | BMU_TX_IPIDINCR_ON = 1<<13, /* Enable IP ID Increment */ | ||
638 | BMU_TX_IPIDINCR_OFF = 1<<12, /* Disable IP ID Increment */ | ||
639 | BMU_TX_CLR_IRQ_TCP = 1<<11, /* Clear IRQ on TCP segment length mismatch */ | ||
640 | }; | ||
641 | |||
642 | /* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/ | ||
643 | /* PREF_UNIT_CTRL 32 bit Prefetch Control register */ | ||
644 | enum { | ||
645 | PREF_UNIT_OP_ON = 1<<3, /* prefetch unit operational */ | ||
646 | PREF_UNIT_OP_OFF = 1<<2, /* prefetch unit not operational */ | ||
647 | PREF_UNIT_RST_CLR = 1<<1, /* Clear Prefetch Unit Reset */ | ||
648 | PREF_UNIT_RST_SET = 1<<0, /* Set Prefetch Unit Reset */ | ||
649 | }; | ||
650 | |||
651 | /* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */ | ||
652 | /* RB_START 32 bit RAM Buffer Start Address */ | ||
653 | /* RB_END 32 bit RAM Buffer End Address */ | ||
654 | /* RB_WP 32 bit RAM Buffer Write Pointer */ | ||
655 | /* RB_RP 32 bit RAM Buffer Read Pointer */ | ||
656 | /* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ | ||
657 | /* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ | ||
658 | /* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ | ||
659 | /* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ | ||
660 | /* RB_PC 32 bit RAM Buffer Packet Counter */ | ||
661 | /* RB_LEV 32 bit RAM Buffer Level Register */ | ||
662 | |||
663 | #define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */ | ||
664 | /* RB_TST2 8 bit RAM Buffer Test Register 2 */ | ||
665 | /* RB_TST1 8 bit RAM Buffer Test Register 1 */ | ||
666 | |||
667 | /* RB_CTRL 8 bit RAM Buffer Control Register */ | ||
668 | enum { | ||
669 | RB_ENA_STFWD = 1<<5, /* Enable Store & Forward */ | ||
670 | RB_DIS_STFWD = 1<<4, /* Disable Store & Forward */ | ||
671 | RB_ENA_OP_MD = 1<<3, /* Enable Operation Mode */ | ||
672 | RB_DIS_OP_MD = 1<<2, /* Disable Operation Mode */ | ||
673 | RB_RST_CLR = 1<<1, /* Clear RAM Buf STM Reset */ | ||
674 | RB_RST_SET = 1<<0, /* Set RAM Buf STM Reset */ | ||
675 | }; | ||
676 | |||
677 | |||
678 | /* Transmit GMAC FIFO (YUKON only) */ | ||
679 | enum { | ||
680 | TX_GMF_EA = 0x0d40,/* 32 bit Tx GMAC FIFO End Address */ | ||
681 | TX_GMF_AE_THR = 0x0d44,/* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ | ||
682 | TX_GMF_CTRL_T = 0x0d48,/* 32 bit Tx GMAC FIFO Control/Test */ | ||
683 | |||
684 | TX_GMF_WP = 0x0d60,/* 32 bit Tx GMAC FIFO Write Pointer */ | ||
685 | TX_GMF_WSP = 0x0d64,/* 32 bit Tx GMAC FIFO Write Shadow Ptr. */ | ||
686 | TX_GMF_WLEV = 0x0d68,/* 32 bit Tx GMAC FIFO Write Level */ | ||
687 | |||
688 | TX_GMF_RP = 0x0d70,/* 32 bit Tx GMAC FIFO Read Pointer */ | ||
689 | TX_GMF_RSTP = 0x0d74,/* 32 bit Tx GMAC FIFO Restart Pointer */ | ||
690 | TX_GMF_RLEV = 0x0d78,/* 32 bit Tx GMAC FIFO Read Level */ | ||
691 | }; | ||
692 | |||
693 | /* Descriptor Poll Timer Registers */ | ||
694 | enum { | ||
695 | B28_DPT_INI = 0x0e00,/* 24 bit Descriptor Poll Timer Init Val */ | ||
696 | B28_DPT_VAL = 0x0e04,/* 24 bit Descriptor Poll Timer Curr Val */ | ||
697 | B28_DPT_CTRL = 0x0e08,/* 8 bit Descriptor Poll Timer Ctrl Reg */ | ||
698 | |||
699 | B28_DPT_TST = 0x0e0a,/* 8 bit Descriptor Poll Timer Test Reg */ | ||
700 | }; | ||
701 | |||
702 | /* Time Stamp Timer Registers (YUKON only) */ | ||
703 | enum { | ||
704 | GMAC_TI_ST_VAL = 0x0e14,/* 32 bit Time Stamp Timer Curr Val */ | ||
705 | GMAC_TI_ST_CTRL = 0x0e18,/* 8 bit Time Stamp Timer Ctrl Reg */ | ||
706 | GMAC_TI_ST_TST = 0x0e1a,/* 8 bit Time Stamp Timer Test Reg */ | ||
707 | }; | ||
708 | |||
709 | /* Polling Unit Registers (Yukon-2 only) */ | ||
710 | enum { | ||
711 | POLL_CTRL = 0x0e20, /* 32 bit Polling Unit Control Reg */ | ||
712 | POLL_LAST_IDX = 0x0e24,/* 16 bit Polling Unit List Last Index */ | ||
713 | |||
714 | POLL_LIST_ADDR_LO= 0x0e28,/* 32 bit Poll. List Start Addr (low) */ | ||
715 | POLL_LIST_ADDR_HI= 0x0e2c,/* 32 bit Poll. List Start Addr (high) */ | ||
716 | }; | ||
717 | |||
718 | /* ASF Subsystem Registers (Yukon-2 only) */ | ||
719 | enum { | ||
720 | B28_Y2_SMB_CONFIG = 0x0e40,/* 32 bit ASF SMBus Config Register */ | ||
721 | B28_Y2_SMB_CSD_REG = 0x0e44,/* 32 bit ASF SMB Control/Status/Data */ | ||
722 | B28_Y2_ASF_IRQ_V_BASE=0x0e60,/* 32 bit ASF IRQ Vector Base */ | ||
723 | |||
724 | B28_Y2_ASF_STAT_CMD= 0x0e68,/* 32 bit ASF Status and Command Reg */ | ||
725 | B28_Y2_ASF_HOST_COM= 0x0e6c,/* 32 bit ASF Host Communication Reg */ | ||
726 | B28_Y2_DATA_REG_1 = 0x0e70,/* 32 bit ASF/Host Data Register 1 */ | ||
727 | B28_Y2_DATA_REG_2 = 0x0e74,/* 32 bit ASF/Host Data Register 2 */ | ||
728 | B28_Y2_DATA_REG_3 = 0x0e78,/* 32 bit ASF/Host Data Register 3 */ | ||
729 | B28_Y2_DATA_REG_4 = 0x0e7c,/* 32 bit ASF/Host Data Register 4 */ | ||
730 | }; | ||
731 | |||
732 | /* Status BMU Registers (Yukon-2 only)*/ | ||
733 | enum { | ||
734 | STAT_CTRL = 0x0e80,/* 32 bit Status BMU Control Reg */ | ||
735 | STAT_LAST_IDX = 0x0e84,/* 16 bit Status BMU Last Index */ | ||
736 | |||
737 | STAT_LIST_ADDR_LO= 0x0e88,/* 32 bit Status List Start Addr (low) */ | ||
738 | STAT_LIST_ADDR_HI= 0x0e8c,/* 32 bit Status List Start Addr (high) */ | ||
739 | STAT_TXA1_RIDX = 0x0e90,/* 16 bit Status TxA1 Report Index Reg */ | ||
740 | STAT_TXS1_RIDX = 0x0e92,/* 16 bit Status TxS1 Report Index Reg */ | ||
741 | STAT_TXA2_RIDX = 0x0e94,/* 16 bit Status TxA2 Report Index Reg */ | ||
742 | STAT_TXS2_RIDX = 0x0e96,/* 16 bit Status TxS2 Report Index Reg */ | ||
743 | STAT_TX_IDX_TH = 0x0e98,/* 16 bit Status Tx Index Threshold Reg */ | ||
744 | STAT_PUT_IDX = 0x0e9c,/* 16 bit Status Put Index Reg */ | ||
745 | |||
746 | /* FIFO Control/Status Registers (Yukon-2 only)*/ | ||
747 | STAT_FIFO_WP = 0x0ea0,/* 8 bit Status FIFO Write Pointer Reg */ | ||
748 | STAT_FIFO_RP = 0x0ea4,/* 8 bit Status FIFO Read Pointer Reg */ | ||
749 | STAT_FIFO_RSP = 0x0ea6,/* 8 bit Status FIFO Read Shadow Ptr */ | ||
750 | STAT_FIFO_LEVEL = 0x0ea8,/* 8 bit Status FIFO Level Reg */ | ||
751 | STAT_FIFO_SHLVL = 0x0eaa,/* 8 bit Status FIFO Shadow Level Reg */ | ||
752 | STAT_FIFO_WM = 0x0eac,/* 8 bit Status FIFO Watermark Reg */ | ||
753 | STAT_FIFO_ISR_WM= 0x0ead,/* 8 bit Status FIFO ISR Watermark Reg */ | ||
754 | |||
755 | /* Level and ISR Timer Registers (Yukon-2 only)*/ | ||
756 | STAT_LEV_TIMER_INI= 0x0eb0,/* 32 bit Level Timer Init. Value Reg */ | ||
757 | STAT_LEV_TIMER_CNT= 0x0eb4,/* 32 bit Level Timer Counter Reg */ | ||
758 | STAT_LEV_TIMER_CTRL= 0x0eb8,/* 8 bit Level Timer Control Reg */ | ||
759 | STAT_LEV_TIMER_TEST= 0x0eb9,/* 8 bit Level Timer Test Reg */ | ||
760 | STAT_TX_TIMER_INI = 0x0ec0,/* 32 bit Tx Timer Init. Value Reg */ | ||
761 | STAT_TX_TIMER_CNT = 0x0ec4,/* 32 bit Tx Timer Counter Reg */ | ||
762 | STAT_TX_TIMER_CTRL = 0x0ec8,/* 8 bit Tx Timer Control Reg */ | ||
763 | STAT_TX_TIMER_TEST = 0x0ec9,/* 8 bit Tx Timer Test Reg */ | ||
764 | STAT_ISR_TIMER_INI = 0x0ed0,/* 32 bit ISR Timer Init. Value Reg */ | ||
765 | STAT_ISR_TIMER_CNT = 0x0ed4,/* 32 bit ISR Timer Counter Reg */ | ||
766 | STAT_ISR_TIMER_CTRL= 0x0ed8,/* 8 bit ISR Timer Control Reg */ | ||
767 | STAT_ISR_TIMER_TEST= 0x0ed9,/* 8 bit ISR Timer Test Reg */ | ||
768 | }; | ||
769 | |||
770 | enum { | ||
771 | LINKLED_OFF = 0x01, | ||
772 | LINKLED_ON = 0x02, | ||
773 | LINKLED_LINKSYNC_OFF = 0x04, | ||
774 | LINKLED_LINKSYNC_ON = 0x08, | ||
775 | LINKLED_BLINK_OFF = 0x10, | ||
776 | LINKLED_BLINK_ON = 0x20, | ||
777 | }; | ||
778 | |||
779 | /* GMAC and GPHY Control Registers (YUKON only) */ | ||
780 | enum { | ||
781 | GMAC_CTRL = 0x0f00,/* 32 bit GMAC Control Reg */ | ||
782 | GPHY_CTRL = 0x0f04,/* 32 bit GPHY Control Reg */ | ||
783 | GMAC_IRQ_SRC = 0x0f08,/* 8 bit GMAC Interrupt Source Reg */ | ||
784 | GMAC_IRQ_MSK = 0x0f0c,/* 8 bit GMAC Interrupt Mask Reg */ | ||
785 | GMAC_LINK_CTRL = 0x0f10,/* 16 bit Link Control Reg */ | ||
786 | |||
787 | /* Wake-up Frame Pattern Match Control Registers (YUKON only) */ | ||
788 | |||
789 | WOL_REG_OFFS = 0x20,/* HW-Bug: Address is + 0x20 against spec. */ | ||
790 | |||
791 | WOL_CTRL_STAT = 0x0f20,/* 16 bit WOL Control/Status Reg */ | ||
792 | WOL_MATCH_CTL = 0x0f22,/* 8 bit WOL Match Control Reg */ | ||
793 | WOL_MATCH_RES = 0x0f23,/* 8 bit WOL Match Result Reg */ | ||
794 | WOL_MAC_ADDR = 0x0f24,/* 32 bit WOL MAC Address */ | ||
795 | WOL_PATT_PME = 0x0f2a,/* 8 bit WOL PME Match Enable (Yukon-2) */ | ||
796 | WOL_PATT_ASFM = 0x0f2b,/* 8 bit WOL ASF Match Enable (Yukon-2) */ | ||
797 | WOL_PATT_RPTR = 0x0f2c,/* 8 bit WOL Pattern Read Pointer */ | ||
798 | |||
799 | /* WOL Pattern Length Registers (YUKON only) */ | ||
800 | |||
801 | WOL_PATT_LEN_LO = 0x0f30,/* 32 bit WOL Pattern Length 3..0 */ | ||
802 | WOL_PATT_LEN_HI = 0x0f34,/* 24 bit WOL Pattern Length 6..4 */ | ||
803 | |||
804 | /* WOL Pattern Counter Registers (YUKON only) */ | ||
805 | |||
806 | |||
807 | WOL_PATT_CNT_0 = 0x0f38,/* 32 bit WOL Pattern Counter 3..0 */ | ||
808 | WOL_PATT_CNT_4 = 0x0f3c,/* 24 bit WOL Pattern Counter 6..4 */ | ||
809 | }; | ||
810 | |||
811 | enum { | ||
812 | WOL_PATT_RAM_1 = 0x1000,/* WOL Pattern RAM Link 1 */ | ||
813 | WOL_PATT_RAM_2 = 0x1400,/* WOL Pattern RAM Link 2 */ | ||
814 | }; | ||
815 | |||
816 | enum { | ||
817 | BASE_GMAC_1 = 0x2800,/* GMAC 1 registers */ | ||
818 | BASE_GMAC_2 = 0x3800,/* GMAC 2 registers */ | ||
819 | }; | ||
820 | |||
821 | /* | ||
822 | * Marvel-PHY Registers, indirect addressed over GMAC | ||
823 | */ | ||
824 | enum { | ||
825 | PHY_MARV_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ | ||
826 | PHY_MARV_STAT = 0x01,/* 16 bit r/o PHY Status Register */ | ||
827 | PHY_MARV_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ | ||
828 | PHY_MARV_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ | ||
829 | PHY_MARV_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ | ||
830 | PHY_MARV_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */ | ||
831 | PHY_MARV_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ | ||
832 | PHY_MARV_NEPG = 0x07,/* 16 bit r/w Next Page Register */ | ||
833 | PHY_MARV_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */ | ||
834 | /* Marvel-specific registers */ | ||
835 | PHY_MARV_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */ | ||
836 | PHY_MARV_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */ | ||
837 | PHY_MARV_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */ | ||
838 | PHY_MARV_PHY_CTRL = 0x10,/* 16 bit r/w PHY Specific Ctrl Reg */ | ||
839 | PHY_MARV_PHY_STAT = 0x11,/* 16 bit r/o PHY Specific Stat Reg */ | ||
840 | PHY_MARV_INT_MASK = 0x12,/* 16 bit r/w Interrupt Mask Reg */ | ||
841 | PHY_MARV_INT_STAT = 0x13,/* 16 bit r/o Interrupt Status Reg */ | ||
842 | PHY_MARV_EXT_CTRL = 0x14,/* 16 bit r/w Ext. PHY Specific Ctrl */ | ||
843 | PHY_MARV_RXE_CNT = 0x15,/* 16 bit r/w Receive Error Counter */ | ||
844 | PHY_MARV_EXT_ADR = 0x16,/* 16 bit r/w Ext. Ad. for Cable Diag. */ | ||
845 | PHY_MARV_PORT_IRQ = 0x17,/* 16 bit r/o Port 0 IRQ (88E1111 only) */ | ||
846 | PHY_MARV_LED_CTRL = 0x18,/* 16 bit r/w LED Control Reg */ | ||
847 | PHY_MARV_LED_OVER = 0x19,/* 16 bit r/w Manual LED Override Reg */ | ||
848 | PHY_MARV_EXT_CTRL_2 = 0x1a,/* 16 bit r/w Ext. PHY Specific Ctrl 2 */ | ||
849 | PHY_MARV_EXT_P_STAT = 0x1b,/* 16 bit r/w Ext. PHY Spec. Stat Reg */ | ||
850 | PHY_MARV_CABLE_DIAG = 0x1c,/* 16 bit r/o Cable Diagnostic Reg */ | ||
851 | PHY_MARV_PAGE_ADDR = 0x1d,/* 16 bit r/w Extended Page Address Reg */ | ||
852 | PHY_MARV_PAGE_DATA = 0x1e,/* 16 bit r/w Extended Page Data Reg */ | ||
853 | |||
854 | /* for 10/100 Fast Ethernet PHY (88E3082 only) */ | ||
855 | PHY_MARV_FE_LED_PAR = 0x16,/* 16 bit r/w LED Parallel Select Reg. */ | ||
856 | PHY_MARV_FE_LED_SER = 0x17,/* 16 bit r/w LED Stream Select S. LED */ | ||
857 | PHY_MARV_FE_VCT_TX = 0x1a,/* 16 bit r/w VCT Reg. for TXP/N Pins */ | ||
858 | PHY_MARV_FE_VCT_RX = 0x1b,/* 16 bit r/o VCT Reg. for RXP/N Pins */ | ||
859 | PHY_MARV_FE_SPEC_2 = 0x1c,/* 16 bit r/w Specific Control Reg. 2 */ | ||
860 | }; | ||
861 | |||
862 | enum { | ||
863 | PHY_CT_RESET = 1<<15, /* Bit 15: (sc) clear all PHY related regs */ | ||
864 | PHY_CT_LOOP = 1<<14, /* Bit 14: enable Loopback over PHY */ | ||
865 | PHY_CT_SPS_LSB = 1<<13, /* Bit 13: Speed select, lower bit */ | ||
866 | PHY_CT_ANE = 1<<12, /* Bit 12: Auto-Negotiation Enabled */ | ||
867 | PHY_CT_PDOWN = 1<<11, /* Bit 11: Power Down Mode */ | ||
868 | PHY_CT_ISOL = 1<<10, /* Bit 10: Isolate Mode */ | ||
869 | PHY_CT_RE_CFG = 1<<9, /* Bit 9: (sc) Restart Auto-Negotiation */ | ||
870 | PHY_CT_DUP_MD = 1<<8, /* Bit 8: Duplex Mode */ | ||
871 | PHY_CT_COL_TST = 1<<7, /* Bit 7: Collision Test enabled */ | ||
872 | PHY_CT_SPS_MSB = 1<<6, /* Bit 6: Speed select, upper bit */ | ||
873 | }; | ||
874 | |||
875 | enum { | ||
876 | PHY_CT_SP1000 = PHY_CT_SPS_MSB, /* enable speed of 1000 Mbps */ | ||
877 | PHY_CT_SP100 = PHY_CT_SPS_LSB, /* enable speed of 100 Mbps */ | ||
878 | PHY_CT_SP10 = 0, /* enable speed of 10 Mbps */ | ||
879 | }; | ||
880 | |||
881 | enum { | ||
882 | PHY_ST_EXT_ST = 1<<8, /* Bit 8: Extended Status Present */ | ||
883 | |||
884 | PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */ | ||
885 | PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */ | ||
886 | PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occured */ | ||
887 | PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */ | ||
888 | PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */ | ||
889 | PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */ | ||
890 | PHY_ST_EXT_REG = 1<<0, /* Bit 0: Extended Register available */ | ||
891 | }; | ||
892 | |||
893 | enum { | ||
894 | PHY_I1_OUI_MSK = 0x3f<<10, /* Bit 15..10: Organization Unique ID */ | ||
895 | PHY_I1_MOD_NUM = 0x3f<<4, /* Bit 9.. 4: Model Number */ | ||
896 | PHY_I1_REV_MSK = 0xf, /* Bit 3.. 0: Revision Number */ | ||
897 | }; | ||
898 | |||
899 | /* different Marvell PHY Ids */ | ||
900 | enum { | ||
901 | PHY_MARV_ID0_VAL= 0x0141, /* Marvell Unique Identifier */ | ||
902 | |||
903 | PHY_BCOM_ID1_A1 = 0x6041, | ||
904 | PHY_BCOM_ID1_B2 = 0x6043, | ||
905 | PHY_BCOM_ID1_C0 = 0x6044, | ||
906 | PHY_BCOM_ID1_C5 = 0x6047, | ||
907 | |||
908 | PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */ | ||
909 | PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */ | ||
910 | PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */ | ||
911 | PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */ | ||
912 | }; | ||
913 | |||
914 | /* Advertisement register bits */ | ||
915 | enum { | ||
916 | PHY_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */ | ||
917 | PHY_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */ | ||
918 | PHY_AN_RF = 1<<13, /* Bit 13: Remote Fault Bits */ | ||
919 | |||
920 | PHY_AN_PAUSE_ASYM = 1<<11,/* Bit 11: Try for asymmetric */ | ||
921 | PHY_AN_PAUSE_CAP = 1<<10, /* Bit 10: Try for pause */ | ||
922 | PHY_AN_100BASE4 = 1<<9, /* Bit 9: Try for 100mbps 4k packets */ | ||
923 | PHY_AN_100FULL = 1<<8, /* Bit 8: Try for 100mbps full-duplex */ | ||
924 | PHY_AN_100HALF = 1<<7, /* Bit 7: Try for 100mbps half-duplex */ | ||
925 | PHY_AN_10FULL = 1<<6, /* Bit 6: Try for 10mbps full-duplex */ | ||
926 | PHY_AN_10HALF = 1<<5, /* Bit 5: Try for 10mbps half-duplex */ | ||
927 | PHY_AN_CSMA = 1<<0, /* Bit 0: Only selector supported */ | ||
928 | PHY_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/ | ||
929 | PHY_AN_FULL = PHY_AN_100FULL | PHY_AN_10FULL | PHY_AN_CSMA, | ||
930 | PHY_AN_ALL = PHY_AN_10HALF | PHY_AN_10FULL | | ||
931 | PHY_AN_100HALF | PHY_AN_100FULL, | ||
932 | }; | ||
933 | |||
934 | /***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ | ||
935 | /***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ | ||
936 | enum { | ||
937 | PHY_B_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */ | ||
938 | PHY_B_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */ | ||
939 | PHY_B_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */ | ||
940 | PHY_B_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status */ | ||
941 | PHY_B_1000S_LP_FD = 1<<11, /* Bit 11: Link Partner can FD */ | ||
942 | PHY_B_1000S_LP_HD = 1<<10, /* Bit 10: Link Partner can HD */ | ||
943 | /* Bit 9..8: reserved */ | ||
944 | PHY_B_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */ | ||
945 | }; | ||
946 | |||
947 | /** Marvell-Specific */ | ||
948 | enum { | ||
949 | PHY_M_AN_NXT_PG = 1<<15, /* Request Next Page */ | ||
950 | PHY_M_AN_ACK = 1<<14, /* (ro) Acknowledge Received */ | ||
951 | PHY_M_AN_RF = 1<<13, /* Remote Fault */ | ||
952 | |||
953 | PHY_M_AN_ASP = 1<<11, /* Asymmetric Pause */ | ||
954 | PHY_M_AN_PC = 1<<10, /* MAC Pause implemented */ | ||
955 | PHY_M_AN_100_T4 = 1<<9, /* Not cap. 100Base-T4 (always 0) */ | ||
956 | PHY_M_AN_100_FD = 1<<8, /* Advertise 100Base-TX Full Duplex */ | ||
957 | PHY_M_AN_100_HD = 1<<7, /* Advertise 100Base-TX Half Duplex */ | ||
958 | PHY_M_AN_10_FD = 1<<6, /* Advertise 10Base-TX Full Duplex */ | ||
959 | PHY_M_AN_10_HD = 1<<5, /* Advertise 10Base-TX Half Duplex */ | ||
960 | PHY_M_AN_SEL_MSK =0x1f<<4, /* Bit 4.. 0: Selector Field Mask */ | ||
961 | }; | ||
962 | |||
963 | /* special defines for FIBER (88E1011S only) */ | ||
964 | enum { | ||
965 | PHY_M_AN_ASP_X = 1<<8, /* Asymmetric Pause */ | ||
966 | PHY_M_AN_PC_X = 1<<7, /* MAC Pause implemented */ | ||
967 | PHY_M_AN_1000X_AHD = 1<<6, /* Advertise 10000Base-X Half Duplex */ | ||
968 | PHY_M_AN_1000X_AFD = 1<<5, /* Advertise 10000Base-X Full Duplex */ | ||
969 | }; | ||
970 | |||
971 | /* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */ | ||
972 | enum { | ||
973 | PHY_M_P_NO_PAUSE_X = 0<<7,/* Bit 8.. 7: no Pause Mode */ | ||
974 | PHY_M_P_SYM_MD_X = 1<<7, /* Bit 8.. 7: symmetric Pause Mode */ | ||
975 | PHY_M_P_ASYM_MD_X = 2<<7,/* Bit 8.. 7: asymmetric Pause Mode */ | ||
976 | PHY_M_P_BOTH_MD_X = 3<<7,/* Bit 8.. 7: both Pause Mode */ | ||
977 | }; | ||
978 | |||
979 | /***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ | ||
980 | enum { | ||
981 | PHY_M_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */ | ||
982 | PHY_M_1000C_MSE = 1<<12, /* Manual Master/Slave Enable */ | ||
983 | PHY_M_1000C_MSC = 1<<11, /* M/S Configuration (1=Master) */ | ||
984 | PHY_M_1000C_MPD = 1<<10, /* Multi-Port Device */ | ||
985 | PHY_M_1000C_AFD = 1<<9, /* Advertise Full Duplex */ | ||
986 | PHY_M_1000C_AHD = 1<<8, /* Advertise Half Duplex */ | ||
987 | }; | ||
988 | |||
989 | /***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/ | ||
990 | enum { | ||
991 | PHY_M_PC_TX_FFD_MSK = 3<<14,/* Bit 15..14: Tx FIFO Depth Mask */ | ||
992 | PHY_M_PC_RX_FFD_MSK = 3<<12,/* Bit 13..12: Rx FIFO Depth Mask */ | ||
993 | PHY_M_PC_ASS_CRS_TX = 1<<11, /* Assert CRS on Transmit */ | ||
994 | PHY_M_PC_FL_GOOD = 1<<10, /* Force Link Good */ | ||
995 | PHY_M_PC_EN_DET_MSK = 3<<8,/* Bit 9.. 8: Energy Detect Mask */ | ||
996 | PHY_M_PC_ENA_EXT_D = 1<<7, /* Enable Ext. Distance (10BT) */ | ||
997 | PHY_M_PC_MDIX_MSK = 3<<5,/* Bit 6.. 5: MDI/MDIX Config. Mask */ | ||
998 | PHY_M_PC_DIS_125CLK = 1<<4, /* Disable 125 CLK */ | ||
999 | PHY_M_PC_MAC_POW_UP = 1<<3, /* MAC Power up */ | ||
1000 | PHY_M_PC_SQE_T_ENA = 1<<2, /* SQE Test Enabled */ | ||
1001 | PHY_M_PC_POL_R_DIS = 1<<1, /* Polarity Reversal Disabled */ | ||
1002 | PHY_M_PC_DIS_JABBER = 1<<0, /* Disable Jabber */ | ||
1003 | }; | ||
1004 | |||
1005 | enum { | ||
1006 | PHY_M_PC_EN_DET = 2<<8, /* Energy Detect (Mode 1) */ | ||
1007 | PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */ | ||
1008 | }; | ||
1009 | |||
1010 | #define PHY_M_PC_MDI_XMODE(x) (((x)<<5) & PHY_M_PC_MDIX_MSK) | ||
1011 | |||
1012 | enum { | ||
1013 | PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */ | ||
1014 | PHY_M_PC_MAN_MDIX = 1, /* 01 = Manual MDIX configuration */ | ||
1015 | PHY_M_PC_ENA_AUTO = 3, /* 11 = Enable Automatic Crossover */ | ||
1016 | }; | ||
1017 | |||
1018 | /* for 10/100 Fast Ethernet PHY (88E3082 only) */ | ||
1019 | enum { | ||
1020 | PHY_M_PC_ENA_DTE_DT = 1<<15, /* Enable Data Terminal Equ. (DTE) Detect */ | ||
1021 | PHY_M_PC_ENA_ENE_DT = 1<<14, /* Enable Energy Detect (sense & pulse) */ | ||
1022 | PHY_M_PC_DIS_NLP_CK = 1<<13, /* Disable Normal Link Puls (NLP) Check */ | ||
1023 | PHY_M_PC_ENA_LIP_NP = 1<<12, /* Enable Link Partner Next Page Reg. */ | ||
1024 | PHY_M_PC_DIS_NLP_GN = 1<<11, /* Disable Normal Link Puls Generation */ | ||
1025 | |||
1026 | PHY_M_PC_DIS_SCRAMB = 1<<9, /* Disable Scrambler */ | ||
1027 | PHY_M_PC_DIS_FEFI = 1<<8, /* Disable Far End Fault Indic. (FEFI) */ | ||
1028 | |||
1029 | PHY_M_PC_SH_TP_SEL = 1<<6, /* Shielded Twisted Pair Select */ | ||
1030 | PHY_M_PC_RX_FD_MSK = 3<<2,/* Bit 3.. 2: Rx FIFO Depth Mask */ | ||
1031 | }; | ||
1032 | |||
1033 | /***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/ | ||
1034 | enum { | ||
1035 | PHY_M_PS_SPEED_MSK = 3<<14, /* Bit 15..14: Speed Mask */ | ||
1036 | PHY_M_PS_SPEED_1000 = 1<<15, /* 10 = 1000 Mbps */ | ||
1037 | PHY_M_PS_SPEED_100 = 1<<14, /* 01 = 100 Mbps */ | ||
1038 | PHY_M_PS_SPEED_10 = 0, /* 00 = 10 Mbps */ | ||
1039 | PHY_M_PS_FULL_DUP = 1<<13, /* Full Duplex */ | ||
1040 | PHY_M_PS_PAGE_REC = 1<<12, /* Page Received */ | ||
1041 | PHY_M_PS_SPDUP_RES = 1<<11, /* Speed & Duplex Resolved */ | ||
1042 | PHY_M_PS_LINK_UP = 1<<10, /* Link Up */ | ||
1043 | PHY_M_PS_CABLE_MSK = 7<<7, /* Bit 9.. 7: Cable Length Mask */ | ||
1044 | PHY_M_PS_MDI_X_STAT = 1<<6, /* MDI Crossover Stat (1=MDIX) */ | ||
1045 | PHY_M_PS_DOWNS_STAT = 1<<5, /* Downshift Status (1=downsh.) */ | ||
1046 | PHY_M_PS_ENDET_STAT = 1<<4, /* Energy Detect Status (1=act) */ | ||
1047 | PHY_M_PS_TX_P_EN = 1<<3, /* Tx Pause Enabled */ | ||
1048 | PHY_M_PS_RX_P_EN = 1<<2, /* Rx Pause Enabled */ | ||
1049 | PHY_M_PS_POL_REV = 1<<1, /* Polarity Reversed */ | ||
1050 | PHY_M_PS_JABBER = 1<<0, /* Jabber */ | ||
1051 | }; | ||
1052 | |||
1053 | #define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN) | ||
1054 | |||
1055 | /* for 10/100 Fast Ethernet PHY (88E3082 only) */ | ||
1056 | enum { | ||
1057 | PHY_M_PS_DTE_DETECT = 1<<15, /* Data Terminal Equipment (DTE) Detected */ | ||
1058 | PHY_M_PS_RES_SPEED = 1<<14, /* Resolved Speed (1=100 Mbps, 0=10 Mbps */ | ||
1059 | }; | ||
1060 | |||
1061 | enum { | ||
1062 | PHY_M_IS_AN_ERROR = 1<<15, /* Auto-Negotiation Error */ | ||
1063 | PHY_M_IS_LSP_CHANGE = 1<<14, /* Link Speed Changed */ | ||
1064 | PHY_M_IS_DUP_CHANGE = 1<<13, /* Duplex Mode Changed */ | ||
1065 | PHY_M_IS_AN_PR = 1<<12, /* Page Received */ | ||
1066 | PHY_M_IS_AN_COMPL = 1<<11, /* Auto-Negotiation Completed */ | ||
1067 | PHY_M_IS_LST_CHANGE = 1<<10, /* Link Status Changed */ | ||
1068 | PHY_M_IS_SYMB_ERROR = 1<<9, /* Symbol Error */ | ||
1069 | PHY_M_IS_FALSE_CARR = 1<<8, /* False Carrier */ | ||
1070 | PHY_M_IS_FIFO_ERROR = 1<<7, /* FIFO Overflow/Underrun Error */ | ||
1071 | PHY_M_IS_MDI_CHANGE = 1<<6, /* MDI Crossover Changed */ | ||
1072 | PHY_M_IS_DOWNSH_DET = 1<<5, /* Downshift Detected */ | ||
1073 | PHY_M_IS_END_CHANGE = 1<<4, /* Energy Detect Changed */ | ||
1074 | |||
1075 | PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */ | ||
1076 | PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */ | ||
1077 | PHY_M_IS_JABBER = 1<<0, /* Jabber */ | ||
1078 | |||
1079 | PHY_M_DEF_MSK = PHY_M_IS_LSP_CHANGE | PHY_M_IS_LST_CHANGE | ||
1080 | | PHY_M_IS_FIFO_ERROR, | ||
1081 | PHY_M_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL, | ||
1082 | }; | ||
1083 | |||
1084 | |||
1085 | /***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ | ||
1086 | enum { | ||
1087 | PHY_M_EC_ENA_BC_EXT = 1<<15, /* Enable Block Carr. Ext. (88E1111 only) */ | ||
1088 | PHY_M_EC_ENA_LIN_LB = 1<<14, /* Enable Line Loopback (88E1111 only) */ | ||
1089 | |||
1090 | PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */ | ||
1091 | PHY_M_EC_M_DSC_MSK = 3<<10, /* Bit 11..10: Master Downshift Counter */ | ||
1092 | /* (88E1011 only) */ | ||
1093 | PHY_M_EC_S_DSC_MSK = 3<<8,/* Bit 9.. 8: Slave Downshift Counter */ | ||
1094 | /* (88E1011 only) */ | ||
1095 | PHY_M_EC_M_DSC_MSK2 = 7<<9,/* Bit 11.. 9: Master Downshift Counter */ | ||
1096 | /* (88E1111 only) */ | ||
1097 | PHY_M_EC_DOWN_S_ENA = 1<<8, /* Downshift Enable (88E1111 only) */ | ||
1098 | /* !!! Errata in spec. (1 = disable) */ | ||
1099 | PHY_M_EC_RX_TIM_CT = 1<<7, /* RGMII Rx Timing Control*/ | ||
1100 | PHY_M_EC_MAC_S_MSK = 7<<4,/* Bit 6.. 4: Def. MAC interface speed */ | ||
1101 | PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */ | ||
1102 | PHY_M_EC_DTE_D_ENA = 1<<2, /* DTE Detect Enable (88E1111 only) */ | ||
1103 | PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */ | ||
1104 | PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */}; | ||
1105 | |||
1106 | #define PHY_M_EC_M_DSC(x) ((x)<<10 & PHY_M_EC_M_DSC_MSK) | ||
1107 | /* 00=1x; 01=2x; 10=3x; 11=4x */ | ||
1108 | #define PHY_M_EC_S_DSC(x) ((x)<<8 & PHY_M_EC_S_DSC_MSK) | ||
1109 | /* 00=dis; 01=1x; 10=2x; 11=3x */ | ||
1110 | #define PHY_M_EC_DSC_2(x) ((x)<<9 & PHY_M_EC_M_DSC_MSK2) | ||
1111 | /* 000=1x; 001=2x; 010=3x; 011=4x */ | ||
1112 | #define PHY_M_EC_MAC_S(x) ((x)<<4 & PHY_M_EC_MAC_S_MSK) | ||
1113 | /* 01X=0; 110=2.5; 111=25 (MHz) */ | ||
1114 | |||
1115 | /* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */ | ||
1116 | enum { | ||
1117 | PHY_M_PC_DIS_LINK_Pa = 1<<15,/* Disable Link Pulses */ | ||
1118 | PHY_M_PC_DSC_MSK = 7<<12,/* Bit 14..12: Downshift Counter */ | ||
1119 | PHY_M_PC_DOWN_S_ENA = 1<<11,/* Downshift Enable */ | ||
1120 | }; | ||
1121 | /* !!! Errata in spec. (1 = disable) */ | ||
1122 | |||
1123 | #define PHY_M_PC_DSC(x) (((x)<<12) & PHY_M_PC_DSC_MSK) | ||
1124 | /* 100=5x; 101=6x; 110=7x; 111=8x */ | ||
1125 | enum { | ||
1126 | MAC_TX_CLK_0_MHZ = 2, | ||
1127 | MAC_TX_CLK_2_5_MHZ = 6, | ||
1128 | MAC_TX_CLK_25_MHZ = 7, | ||
1129 | }; | ||
1130 | |||
1131 | /***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/ | ||
1132 | enum { | ||
1133 | PHY_M_LEDC_DIS_LED = 1<<15, /* Disable LED */ | ||
1134 | PHY_M_LEDC_PULS_MSK = 7<<12,/* Bit 14..12: Pulse Stretch Mask */ | ||
1135 | PHY_M_LEDC_F_INT = 1<<11, /* Force Interrupt */ | ||
1136 | PHY_M_LEDC_BL_R_MSK = 7<<8,/* Bit 10.. 8: Blink Rate Mask */ | ||
1137 | PHY_M_LEDC_DP_C_LSB = 1<<7, /* Duplex Control (LSB, 88E1111 only) */ | ||
1138 | PHY_M_LEDC_TX_C_LSB = 1<<6, /* Tx Control (LSB, 88E1111 only) */ | ||
1139 | PHY_M_LEDC_LK_C_MSK = 7<<3,/* Bit 5.. 3: Link Control Mask */ | ||
1140 | /* (88E1111 only) */ | ||
1141 | }; | ||
1142 | |||
1143 | enum { | ||
1144 | PHY_M_LEDC_LINK_MSK = 3<<3,/* Bit 4.. 3: Link Control Mask */ | ||
1145 | /* (88E1011 only) */ | ||
1146 | PHY_M_LEDC_DP_CTRL = 1<<2, /* Duplex Control */ | ||
1147 | PHY_M_LEDC_DP_C_MSB = 1<<2, /* Duplex Control (MSB, 88E1111 only) */ | ||
1148 | PHY_M_LEDC_RX_CTRL = 1<<1, /* Rx Activity / Link */ | ||
1149 | PHY_M_LEDC_TX_CTRL = 1<<0, /* Tx Activity / Link */ | ||
1150 | PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */ | ||
1151 | }; | ||
1152 | |||
1153 | #define PHY_M_LED_PULS_DUR(x) (((x)<<12) & PHY_M_LEDC_PULS_MSK) | ||
1154 | |||
1155 | /***** PHY_MARV_PHY_STAT (page 3)16 bit r/w Polarity Control Reg. *****/ | ||
1156 | enum { | ||
1157 | PHY_M_POLC_LS1M_MSK = 0xf<<12, /* Bit 15..12: LOS,STAT1 Mix % Mask */ | ||
1158 | PHY_M_POLC_IS0M_MSK = 0xf<<8, /* Bit 11.. 8: INIT,STAT0 Mix % Mask */ | ||
1159 | PHY_M_POLC_LOS_MSK = 0x3<<6, /* Bit 7.. 6: LOS Pol. Ctrl. Mask */ | ||
1160 | PHY_M_POLC_INIT_MSK = 0x3<<4, /* Bit 5.. 4: INIT Pol. Ctrl. Mask */ | ||
1161 | PHY_M_POLC_STA1_MSK = 0x3<<2, /* Bit 3.. 2: STAT1 Pol. Ctrl. Mask */ | ||
1162 | PHY_M_POLC_STA0_MSK = 0x3, /* Bit 1.. 0: STAT0 Pol. Ctrl. Mask */ | ||
1163 | }; | ||
1164 | |||
1165 | #define PHY_M_POLC_LS1_P_MIX(x) (((x)<<12) & PHY_M_POLC_LS1M_MSK) | ||
1166 | #define PHY_M_POLC_IS0_P_MIX(x) (((x)<<8) & PHY_M_POLC_IS0M_MSK) | ||
1167 | #define PHY_M_POLC_LOS_CTRL(x) (((x)<<6) & PHY_M_POLC_LOS_MSK) | ||
1168 | #define PHY_M_POLC_INIT_CTRL(x) (((x)<<4) & PHY_M_POLC_INIT_MSK) | ||
1169 | #define PHY_M_POLC_STA1_CTRL(x) (((x)<<2) & PHY_M_POLC_STA1_MSK) | ||
1170 | #define PHY_M_POLC_STA0_CTRL(x) (((x)<<0) & PHY_M_POLC_STA0_MSK) | ||
1171 | |||
1172 | enum { | ||
1173 | PULS_NO_STR = 0,/* no pulse stretching */ | ||
1174 | PULS_21MS = 1,/* 21 ms to 42 ms */ | ||
1175 | PULS_42MS = 2,/* 42 ms to 84 ms */ | ||
1176 | PULS_84MS = 3,/* 84 ms to 170 ms */ | ||
1177 | PULS_170MS = 4,/* 170 ms to 340 ms */ | ||
1178 | PULS_340MS = 5,/* 340 ms to 670 ms */ | ||
1179 | PULS_670MS = 6,/* 670 ms to 1.3 s */ | ||
1180 | PULS_1300MS = 7,/* 1.3 s to 2.7 s */ | ||
1181 | }; | ||
1182 | |||
1183 | #define PHY_M_LED_BLINK_RT(x) (((x)<<8) & PHY_M_LEDC_BL_R_MSK) | ||
1184 | |||
1185 | enum { | ||
1186 | BLINK_42MS = 0,/* 42 ms */ | ||
1187 | BLINK_84MS = 1,/* 84 ms */ | ||
1188 | BLINK_170MS = 2,/* 170 ms */ | ||
1189 | BLINK_340MS = 3,/* 340 ms */ | ||
1190 | BLINK_670MS = 4,/* 670 ms */ | ||
1191 | }; | ||
1192 | |||
1193 | /***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ | ||
1194 | #define PHY_M_LED_MO_SGMII(x) ((x)<<14) /* Bit 15..14: SGMII AN Timer */ | ||
1195 | /* Bit 13..12: reserved */ | ||
1196 | #define PHY_M_LED_MO_DUP(x) ((x)<<10) /* Bit 11..10: Duplex */ | ||
1197 | #define PHY_M_LED_MO_10(x) ((x)<<8) /* Bit 9.. 8: Link 10 */ | ||
1198 | #define PHY_M_LED_MO_100(x) ((x)<<6) /* Bit 7.. 6: Link 100 */ | ||
1199 | #define PHY_M_LED_MO_1000(x) ((x)<<4) /* Bit 5.. 4: Link 1000 */ | ||
1200 | #define PHY_M_LED_MO_RX(x) ((x)<<2) /* Bit 3.. 2: Rx */ | ||
1201 | #define PHY_M_LED_MO_TX(x) ((x)<<0) /* Bit 1.. 0: Tx */ | ||
1202 | |||
1203 | enum { | ||
1204 | MO_LED_NORM = 0, | ||
1205 | MO_LED_BLINK = 1, | ||
1206 | MO_LED_OFF = 2, | ||
1207 | MO_LED_ON = 3, | ||
1208 | }; | ||
1209 | |||
1210 | /***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/ | ||
1211 | enum { | ||
1212 | PHY_M_EC2_FI_IMPED = 1<<6, /* Fiber Input Impedance */ | ||
1213 | PHY_M_EC2_FO_IMPED = 1<<5, /* Fiber Output Impedance */ | ||
1214 | PHY_M_EC2_FO_M_CLK = 1<<4, /* Fiber Mode Clock Enable */ | ||
1215 | PHY_M_EC2_FO_BOOST = 1<<3, /* Fiber Output Boost */ | ||
1216 | PHY_M_EC2_FO_AM_MSK = 7,/* Bit 2.. 0: Fiber Output Amplitude */ | ||
1217 | }; | ||
1218 | |||
1219 | /***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/ | ||
1220 | enum { | ||
1221 | PHY_M_FC_AUTO_SEL = 1<<15, /* Fiber/Copper Auto Sel. Dis. */ | ||
1222 | PHY_M_FC_AN_REG_ACC = 1<<14, /* Fiber/Copper AN Reg. Access */ | ||
1223 | PHY_M_FC_RESOLUTION = 1<<13, /* Fiber/Copper Resolution */ | ||
1224 | PHY_M_SER_IF_AN_BP = 1<<12, /* Ser. IF AN Bypass Enable */ | ||
1225 | PHY_M_SER_IF_BP_ST = 1<<11, /* Ser. IF AN Bypass Status */ | ||
1226 | PHY_M_IRQ_POLARITY = 1<<10, /* IRQ polarity */ | ||
1227 | PHY_M_DIS_AUT_MED = 1<<9, /* Disable Aut. Medium Reg. Selection */ | ||
1228 | /* (88E1111 only) */ | ||
1229 | |||
1230 | PHY_M_UNDOC1 = 1<<7, /* undocumented bit !! */ | ||
1231 | PHY_M_DTE_POW_STAT = 1<<4, /* DTE Power Status (88E1111 only) */ | ||
1232 | PHY_M_MODE_MASK = 0xf, /* Bit 3.. 0: copy of HWCFG MODE[3:0] */ | ||
1233 | }; | ||
1234 | |||
1235 | /* for 10/100 Fast Ethernet PHY (88E3082 only) */ | ||
1236 | /***** PHY_MARV_FE_LED_PAR 16 bit r/w LED Parallel Select Reg. *****/ | ||
1237 | /* Bit 15..12: reserved (used internally) */ | ||
1238 | enum { | ||
1239 | PHY_M_FELP_LED2_MSK = 0xf<<8, /* Bit 11.. 8: LED2 Mask (LINK) */ | ||
1240 | PHY_M_FELP_LED1_MSK = 0xf<<4, /* Bit 7.. 4: LED1 Mask (ACT) */ | ||
1241 | PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */ | ||
1242 | }; | ||
1243 | |||
1244 | #define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK) | ||
1245 | #define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK) | ||
1246 | #define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK) | ||
1247 | |||
1248 | enum { | ||
1249 | LED_PAR_CTRL_COLX = 0x00, | ||
1250 | LED_PAR_CTRL_ERROR = 0x01, | ||
1251 | LED_PAR_CTRL_DUPLEX = 0x02, | ||
1252 | LED_PAR_CTRL_DP_COL = 0x03, | ||
1253 | LED_PAR_CTRL_SPEED = 0x04, | ||
1254 | LED_PAR_CTRL_LINK = 0x05, | ||
1255 | LED_PAR_CTRL_TX = 0x06, | ||
1256 | LED_PAR_CTRL_RX = 0x07, | ||
1257 | LED_PAR_CTRL_ACT = 0x08, | ||
1258 | LED_PAR_CTRL_LNK_RX = 0x09, | ||
1259 | LED_PAR_CTRL_LNK_AC = 0x0a, | ||
1260 | LED_PAR_CTRL_ACT_BL = 0x0b, | ||
1261 | LED_PAR_CTRL_TX_BL = 0x0c, | ||
1262 | LED_PAR_CTRL_RX_BL = 0x0d, | ||
1263 | LED_PAR_CTRL_COL_BL = 0x0e, | ||
1264 | LED_PAR_CTRL_INACT = 0x0f | ||
1265 | }; | ||
1266 | |||
1267 | /*****,PHY_MARV_FE_SPEC_2 16 bit r/w Specific Control Reg. 2 *****/ | ||
1268 | enum { | ||
1269 | PHY_M_FESC_DIS_WAIT = 1<<2, /* Disable TDR Waiting Period */ | ||
1270 | PHY_M_FESC_ENA_MCLK = 1<<1, /* Enable MAC Rx Clock in sleep mode */ | ||
1271 | PHY_M_FESC_SEL_CL_A = 1<<0, /* Select Class A driver (100B-TX) */ | ||
1272 | }; | ||
1273 | |||
1274 | /* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */ | ||
1275 | /***** PHY_MARV_PHY_CTRL (page 2) 16 bit r/w MAC Specific Ctrl *****/ | ||
1276 | enum { | ||
1277 | PHY_M_MAC_MD_MSK = 7<<7, /* Bit 9.. 7: Mode Select Mask */ | ||
1278 | PHY_M_MAC_MD_AUTO = 3,/* Auto Copper/1000Base-X */ | ||
1279 | PHY_M_MAC_MD_COPPER = 5,/* Copper only */ | ||
1280 | PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */ | ||
1281 | }; | ||
1282 | #define PHY_M_MAC_MODE_SEL(x) (((x)<<7) & PHY_M_MAC_MD_MSK) | ||
1283 | |||
1284 | /***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/ | ||
1285 | enum { | ||
1286 | PHY_M_LEDC_LOS_MSK = 0xf<<12,/* Bit 15..12: LOS LED Ctrl. Mask */ | ||
1287 | PHY_M_LEDC_INIT_MSK = 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */ | ||
1288 | PHY_M_LEDC_STA1_MSK = 0xf<<4,/* Bit 7.. 4: STAT1 LED Ctrl. Mask */ | ||
1289 | PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */ | ||
1290 | }; | ||
1291 | |||
1292 | #define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK) | ||
1293 | #define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK) | ||
1294 | #define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK) | ||
1295 | #define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK) | ||
1296 | |||
1297 | /* GMAC registers */ | ||
1298 | /* Port Registers */ | ||
1299 | enum { | ||
1300 | GM_GP_STAT = 0x0000, /* 16 bit r/o General Purpose Status */ | ||
1301 | GM_GP_CTRL = 0x0004, /* 16 bit r/w General Purpose Control */ | ||
1302 | GM_TX_CTRL = 0x0008, /* 16 bit r/w Transmit Control Reg. */ | ||
1303 | GM_RX_CTRL = 0x000c, /* 16 bit r/w Receive Control Reg. */ | ||
1304 | GM_TX_FLOW_CTRL = 0x0010, /* 16 bit r/w Transmit Flow-Control */ | ||
1305 | GM_TX_PARAM = 0x0014, /* 16 bit r/w Transmit Parameter Reg. */ | ||
1306 | GM_SERIAL_MODE = 0x0018, /* 16 bit r/w Serial Mode Register */ | ||
1307 | /* Source Address Registers */ | ||
1308 | GM_SRC_ADDR_1L = 0x001c, /* 16 bit r/w Source Address 1 (low) */ | ||
1309 | GM_SRC_ADDR_1M = 0x0020, /* 16 bit r/w Source Address 1 (middle) */ | ||
1310 | GM_SRC_ADDR_1H = 0x0024, /* 16 bit r/w Source Address 1 (high) */ | ||
1311 | GM_SRC_ADDR_2L = 0x0028, /* 16 bit r/w Source Address 2 (low) */ | ||
1312 | GM_SRC_ADDR_2M = 0x002c, /* 16 bit r/w Source Address 2 (middle) */ | ||
1313 | GM_SRC_ADDR_2H = 0x0030, /* 16 bit r/w Source Address 2 (high) */ | ||
1314 | |||
1315 | /* Multicast Address Hash Registers */ | ||
1316 | GM_MC_ADDR_H1 = 0x0034, /* 16 bit r/w Multicast Address Hash 1 */ | ||
1317 | GM_MC_ADDR_H2 = 0x0038, /* 16 bit r/w Multicast Address Hash 2 */ | ||
1318 | GM_MC_ADDR_H3 = 0x003c, /* 16 bit r/w Multicast Address Hash 3 */ | ||
1319 | GM_MC_ADDR_H4 = 0x0040, /* 16 bit r/w Multicast Address Hash 4 */ | ||
1320 | |||
1321 | /* Interrupt Source Registers */ | ||
1322 | GM_TX_IRQ_SRC = 0x0044, /* 16 bit r/o Tx Overflow IRQ Source */ | ||
1323 | GM_RX_IRQ_SRC = 0x0048, /* 16 bit r/o Rx Overflow IRQ Source */ | ||
1324 | GM_TR_IRQ_SRC = 0x004c, /* 16 bit r/o Tx/Rx Over. IRQ Source */ | ||
1325 | |||
1326 | /* Interrupt Mask Registers */ | ||
1327 | GM_TX_IRQ_MSK = 0x0050, /* 16 bit r/w Tx Overflow IRQ Mask */ | ||
1328 | GM_RX_IRQ_MSK = 0x0054, /* 16 bit r/w Rx Overflow IRQ Mask */ | ||
1329 | GM_TR_IRQ_MSK = 0x0058, /* 16 bit r/w Tx/Rx Over. IRQ Mask */ | ||
1330 | |||
1331 | /* Serial Management Interface (SMI) Registers */ | ||
1332 | GM_SMI_CTRL = 0x0080, /* 16 bit r/w SMI Control Register */ | ||
1333 | GM_SMI_DATA = 0x0084, /* 16 bit r/w SMI Data Register */ | ||
1334 | GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */ | ||
1335 | }; | ||
1336 | |||
1337 | /* MIB Counters */ | ||
1338 | #define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */ | ||
1339 | #define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */ | ||
1340 | |||
1341 | /* | ||
1342 | * MIB Counters base address definitions (low word) - | ||
1343 | * use offset 4 for access to high word (32 bit r/o) | ||
1344 | */ | ||
1345 | enum { | ||
1346 | GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */ | ||
1347 | GM_RXF_BC_OK = GM_MIB_CNT_BASE + 8, /* Broadcast Frames Received OK */ | ||
1348 | GM_RXF_MPAUSE = GM_MIB_CNT_BASE + 16, /* Pause MAC Ctrl Frames Received */ | ||
1349 | GM_RXF_MC_OK = GM_MIB_CNT_BASE + 24, /* Multicast Frames Received OK */ | ||
1350 | GM_RXF_FCS_ERR = GM_MIB_CNT_BASE + 32, /* Rx Frame Check Seq. Error */ | ||
1351 | /* GM_MIB_CNT_BASE + 40: reserved */ | ||
1352 | GM_RXO_OK_LO = GM_MIB_CNT_BASE + 48, /* Octets Received OK Low */ | ||
1353 | GM_RXO_OK_HI = GM_MIB_CNT_BASE + 56, /* Octets Received OK High */ | ||
1354 | GM_RXO_ERR_LO = GM_MIB_CNT_BASE + 64, /* Octets Received Invalid Low */ | ||
1355 | GM_RXO_ERR_HI = GM_MIB_CNT_BASE + 72, /* Octets Received Invalid High */ | ||
1356 | GM_RXF_SHT = GM_MIB_CNT_BASE + 80, /* Frames <64 Byte Received OK */ | ||
1357 | GM_RXE_FRAG = GM_MIB_CNT_BASE + 88, /* Frames <64 Byte Received with FCS Err */ | ||
1358 | GM_RXF_64B = GM_MIB_CNT_BASE + 96, /* 64 Byte Rx Frame */ | ||
1359 | GM_RXF_127B = GM_MIB_CNT_BASE + 104, /* 65-127 Byte Rx Frame */ | ||
1360 | GM_RXF_255B = GM_MIB_CNT_BASE + 112, /* 128-255 Byte Rx Frame */ | ||
1361 | GM_RXF_511B = GM_MIB_CNT_BASE + 120, /* 256-511 Byte Rx Frame */ | ||
1362 | GM_RXF_1023B = GM_MIB_CNT_BASE + 128, /* 512-1023 Byte Rx Frame */ | ||
1363 | GM_RXF_1518B = GM_MIB_CNT_BASE + 136, /* 1024-1518 Byte Rx Frame */ | ||
1364 | GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144, /* 1519-MaxSize Byte Rx Frame */ | ||
1365 | GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152, /* Rx Frame too Long Error */ | ||
1366 | GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160, /* Rx Jabber Packet Frame */ | ||
1367 | /* GM_MIB_CNT_BASE + 168: reserved */ | ||
1368 | GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176, /* Rx FIFO overflow Event */ | ||
1369 | /* GM_MIB_CNT_BASE + 184: reserved */ | ||
1370 | GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192, /* Unicast Frames Xmitted OK */ | ||
1371 | GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200, /* Broadcast Frames Xmitted OK */ | ||
1372 | GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208, /* Pause MAC Ctrl Frames Xmitted */ | ||
1373 | GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216, /* Multicast Frames Xmitted OK */ | ||
1374 | GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224, /* Octets Transmitted OK Low */ | ||
1375 | GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232, /* Octets Transmitted OK High */ | ||
1376 | GM_TXF_64B = GM_MIB_CNT_BASE + 240, /* 64 Byte Tx Frame */ | ||
1377 | GM_TXF_127B = GM_MIB_CNT_BASE + 248, /* 65-127 Byte Tx Frame */ | ||
1378 | GM_TXF_255B = GM_MIB_CNT_BASE + 256, /* 128-255 Byte Tx Frame */ | ||
1379 | GM_TXF_511B = GM_MIB_CNT_BASE + 264, /* 256-511 Byte Tx Frame */ | ||
1380 | GM_TXF_1023B = GM_MIB_CNT_BASE + 272, /* 512-1023 Byte Tx Frame */ | ||
1381 | GM_TXF_1518B = GM_MIB_CNT_BASE + 280, /* 1024-1518 Byte Tx Frame */ | ||
1382 | GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288, /* 1519-MaxSize Byte Tx Frame */ | ||
1383 | |||
1384 | GM_TXF_COL = GM_MIB_CNT_BASE + 304, /* Tx Collision */ | ||
1385 | GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312, /* Tx Late Collision */ | ||
1386 | GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320, /* Tx aborted due to Exces. Col. */ | ||
1387 | GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328, /* Tx Multiple Collision */ | ||
1388 | GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336, /* Tx Single Collision */ | ||
1389 | GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344, /* Tx FIFO Underrun Event */ | ||
1390 | }; | ||
1391 | |||
1392 | /* GMAC Bit Definitions */ | ||
1393 | /* GM_GP_STAT 16 bit r/o General Purpose Status Register */ | ||
1394 | enum { | ||
1395 | GM_GPSR_SPEED = 1<<15, /* Bit 15: Port Speed (1 = 100 Mbps) */ | ||
1396 | GM_GPSR_DUPLEX = 1<<14, /* Bit 14: Duplex Mode (1 = Full) */ | ||
1397 | GM_GPSR_FC_TX_DIS = 1<<13, /* Bit 13: Tx Flow-Control Mode Disabled */ | ||
1398 | GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */ | ||
1399 | GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */ | ||
1400 | GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */ | ||
1401 | GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occured */ | ||
1402 | GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occured */ | ||
1403 | |||
1404 | GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */ | ||
1405 | GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ | ||
1406 | GM_GPSR_PART_MODE = 1<<3, /* Bit 3: Partition mode */ | ||
1407 | GM_GPSR_FC_RX_DIS = 1<<2, /* Bit 2: Rx Flow-Control Mode Disabled */ | ||
1408 | GM_GPSR_PROM_EN = 1<<1, /* Bit 1: Promiscuous Mode Enabled */ | ||
1409 | }; | ||
1410 | |||
1411 | /* GM_GP_CTRL 16 bit r/w General Purpose Control Register */ | ||
1412 | enum { | ||
1413 | GM_GPCR_PROM_ENA = 1<<14, /* Bit 14: Enable Promiscuous Mode */ | ||
1414 | GM_GPCR_FC_TX_DIS = 1<<13, /* Bit 13: Disable Tx Flow-Control Mode */ | ||
1415 | GM_GPCR_TX_ENA = 1<<12, /* Bit 12: Enable Transmit */ | ||
1416 | GM_GPCR_RX_ENA = 1<<11, /* Bit 11: Enable Receive */ | ||
1417 | GM_GPCR_BURST_ENA = 1<<10, /* Bit 10: Enable Burst Mode */ | ||
1418 | GM_GPCR_LOOP_ENA = 1<<9, /* Bit 9: Enable MAC Loopback Mode */ | ||
1419 | GM_GPCR_PART_ENA = 1<<8, /* Bit 8: Enable Partition Mode */ | ||
1420 | GM_GPCR_GIGS_ENA = 1<<7, /* Bit 7: Gigabit Speed (1000 Mbps) */ | ||
1421 | GM_GPCR_FL_PASS = 1<<6, /* Bit 6: Force Link Pass */ | ||
1422 | GM_GPCR_DUP_FULL = 1<<5, /* Bit 5: Full Duplex Mode */ | ||
1423 | GM_GPCR_FC_RX_DIS = 1<<4, /* Bit 4: Disable Rx Flow-Control Mode */ | ||
1424 | GM_GPCR_SPEED_100 = 1<<3, /* Bit 3: Port Speed 100 Mbps */ | ||
1425 | GM_GPCR_AU_DUP_DIS = 1<<2, /* Bit 2: Disable Auto-Update Duplex */ | ||
1426 | GM_GPCR_AU_FCT_DIS = 1<<1, /* Bit 1: Disable Auto-Update Flow-C. */ | ||
1427 | GM_GPCR_AU_SPD_DIS = 1<<0, /* Bit 0: Disable Auto-Update Speed */ | ||
1428 | }; | ||
1429 | |||
1430 | #define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100) | ||
1431 | #define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS) | ||
1432 | |||
1433 | /* GM_TX_CTRL 16 bit r/w Transmit Control Register */ | ||
1434 | enum { | ||
1435 | GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */ | ||
1436 | GM_TXCR_CRC_DIS = 1<<14, /* Bit 14: Disable insertion of CRC */ | ||
1437 | GM_TXCR_PAD_DIS = 1<<13, /* Bit 13: Disable padding of packets */ | ||
1438 | GM_TXCR_COL_THR_MSK = 1<<10, /* Bit 12..10: Collision Threshold */ | ||
1439 | }; | ||
1440 | |||
1441 | #define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK) | ||
1442 | #define TX_COL_DEF 0x04 | ||
1443 | |||
1444 | /* GM_RX_CTRL 16 bit r/w Receive Control Register */ | ||
1445 | enum { | ||
1446 | GM_RXCR_UCF_ENA = 1<<15, /* Bit 15: Enable Unicast filtering */ | ||
1447 | GM_RXCR_MCF_ENA = 1<<14, /* Bit 14: Enable Multicast filtering */ | ||
1448 | GM_RXCR_CRC_DIS = 1<<13, /* Bit 13: Remove 4-byte CRC */ | ||
1449 | GM_RXCR_PASS_FC = 1<<12, /* Bit 12: Pass FC packets to FIFO */ | ||
1450 | }; | ||
1451 | |||
1452 | /* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */ | ||
1453 | enum { | ||
1454 | GM_TXPA_JAMLEN_MSK = 0x03<<14, /* Bit 15..14: Jam Length */ | ||
1455 | GM_TXPA_JAMIPG_MSK = 0x1f<<9, /* Bit 13..9: Jam IPG */ | ||
1456 | GM_TXPA_JAMDAT_MSK = 0x1f<<4, /* Bit 8..4: IPG Jam to Data */ | ||
1457 | GM_TXPA_BO_LIM_MSK = 0x0f, /* Bit 3.. 0: Backoff Limit Mask */ | ||
1458 | |||
1459 | TX_JAM_LEN_DEF = 0x03, | ||
1460 | TX_JAM_IPG_DEF = 0x0b, | ||
1461 | TX_IPG_JAM_DEF = 0x1c, | ||
1462 | TX_BOF_LIM_DEF = 0x04, | ||
1463 | }; | ||
1464 | |||
1465 | #define TX_JAM_LEN_VAL(x) (((x)<<14) & GM_TXPA_JAMLEN_MSK) | ||
1466 | #define TX_JAM_IPG_VAL(x) (((x)<<9) & GM_TXPA_JAMIPG_MSK) | ||
1467 | #define TX_IPG_JAM_DATA(x) (((x)<<4) & GM_TXPA_JAMDAT_MSK) | ||
1468 | #define TX_BACK_OFF_LIM(x) ((x) & GM_TXPA_BO_LIM_MSK) | ||
1469 | |||
1470 | |||
1471 | /* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */ | ||
1472 | enum { | ||
1473 | GM_SMOD_DATABL_MSK = 0x1f<<11, /* Bit 15..11: Data Blinder (r/o) */ | ||
1474 | GM_SMOD_LIMIT_4 = 1<<10, /* Bit 10: 4 consecutive Tx trials */ | ||
1475 | GM_SMOD_VLAN_ENA = 1<<9, /* Bit 9: Enable VLAN (Max. Frame Len) */ | ||
1476 | GM_SMOD_JUMBO_ENA = 1<<8, /* Bit 8: Enable Jumbo (Max. Frame Len) */ | ||
1477 | GM_SMOD_IPG_MSK = 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */ | ||
1478 | }; | ||
1479 | |||
1480 | #define DATA_BLIND_VAL(x) (((x)<<11) & GM_SMOD_DATABL_MSK) | ||
1481 | #define DATA_BLIND_DEF 0x04 | ||
1482 | |||
1483 | #define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK) | ||
1484 | #define IPG_DATA_DEF 0x1e | ||
1485 | |||
1486 | /* GM_SMI_CTRL 16 bit r/w SMI Control Register */ | ||
1487 | enum { | ||
1488 | GM_SMI_CT_PHY_A_MSK = 0x1f<<11,/* Bit 15..11: PHY Device Address */ | ||
1489 | GM_SMI_CT_REG_A_MSK = 0x1f<<6,/* Bit 10.. 6: PHY Register Address */ | ||
1490 | GM_SMI_CT_OP_RD = 1<<5, /* Bit 5: OpCode Read (0=Write)*/ | ||
1491 | GM_SMI_CT_RD_VAL = 1<<4, /* Bit 4: Read Valid (Read completed) */ | ||
1492 | GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */ | ||
1493 | }; | ||
1494 | |||
1495 | #define GM_SMI_CT_PHY_AD(x) (((x)<<11) & GM_SMI_CT_PHY_A_MSK) | ||
1496 | #define GM_SMI_CT_REG_AD(x) (((x)<<6) & GM_SMI_CT_REG_A_MSK) | ||
1497 | |||
1498 | /* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ | ||
1499 | enum { | ||
1500 | GM_PAR_MIB_CLR = 1<<5, /* Bit 5: Set MIB Clear Counter Mode */ | ||
1501 | GM_PAR_MIB_TST = 1<<4, /* Bit 4: MIB Load Counter (Test Mode) */ | ||
1502 | }; | ||
1503 | |||
1504 | /* Receive Frame Status Encoding */ | ||
1505 | enum { | ||
1506 | GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */ | ||
1507 | GMR_FS_VLAN = 1<<13, /* VLAN Packet */ | ||
1508 | GMR_FS_JABBER = 1<<12, /* Jabber Packet */ | ||
1509 | GMR_FS_UN_SIZE = 1<<11, /* Undersize Packet */ | ||
1510 | GMR_FS_MC = 1<<10, /* Multicast Packet */ | ||
1511 | GMR_FS_BC = 1<<9, /* Broadcast Packet */ | ||
1512 | GMR_FS_RX_OK = 1<<8, /* Receive OK (Good Packet) */ | ||
1513 | GMR_FS_GOOD_FC = 1<<7, /* Good Flow-Control Packet */ | ||
1514 | GMR_FS_BAD_FC = 1<<6, /* Bad Flow-Control Packet */ | ||
1515 | GMR_FS_MII_ERR = 1<<5, /* MII Error */ | ||
1516 | GMR_FS_LONG_ERR = 1<<4, /* Too Long Packet */ | ||
1517 | GMR_FS_FRAGMENT = 1<<3, /* Fragment */ | ||
1518 | |||
1519 | GMR_FS_CRC_ERR = 1<<1, /* CRC Error */ | ||
1520 | GMR_FS_RX_FF_OV = 1<<0, /* Rx FIFO Overflow */ | ||
1521 | |||
1522 | GMR_FS_ANY_ERR = GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR | | ||
1523 | GMR_FS_FRAGMENT | GMR_FS_LONG_ERR | | ||
1524 | GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC | | ||
1525 | GMR_FS_UN_SIZE | GMR_FS_JABBER, | ||
1526 | }; | ||
1527 | |||
1528 | /* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */ | ||
1529 | enum { | ||
1530 | RX_TRUNC_ON = 1<<27, /* enable packet truncation */ | ||
1531 | RX_TRUNC_OFF = 1<<26, /* disable packet truncation */ | ||
1532 | RX_VLAN_STRIP_ON = 1<<25, /* enable VLAN stripping */ | ||
1533 | RX_VLAN_STRIP_OFF = 1<<24, /* disable VLAN stripping */ | ||
1534 | |||
1535 | GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */ | ||
1536 | GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */ | ||
1537 | GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */ | ||
1538 | |||
1539 | GMF_RP_TST_ON = 1<<10, /* Read Pointer Test On */ | ||
1540 | GMF_RP_TST_OFF = 1<<9, /* Read Pointer Test Off */ | ||
1541 | GMF_RP_STEP = 1<<8, /* Read Pointer Step/Increment */ | ||
1542 | GMF_RX_F_FL_ON = 1<<7, /* Rx FIFO Flush Mode On */ | ||
1543 | GMF_RX_F_FL_OFF = 1<<6, /* Rx FIFO Flush Mode Off */ | ||
1544 | GMF_CLI_RX_FO = 1<<5, /* Clear IRQ Rx FIFO Overrun */ | ||
1545 | GMF_CLI_RX_C = 1<<4, /* Clear IRQ Rx Frame Complete */ | ||
1546 | |||
1547 | GMF_OPER_ON = 1<<3, /* Operational Mode On */ | ||
1548 | GMF_OPER_OFF = 1<<2, /* Operational Mode Off */ | ||
1549 | GMF_RST_CLR = 1<<1, /* Clear GMAC FIFO Reset */ | ||
1550 | GMF_RST_SET = 1<<0, /* Set GMAC FIFO Reset */ | ||
1551 | |||
1552 | RX_GMF_FL_THR_DEF = 0xa, /* flush threshold (default) */ | ||
1553 | |||
1554 | GMF_RX_CTRL_DEF = GMF_OPER_ON | GMF_RX_F_FL_ON, | ||
1555 | }; | ||
1556 | |||
1557 | |||
1558 | /* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ | ||
1559 | enum { | ||
1560 | TX_VLAN_TAG_ON = 1<<25,/* enable VLAN tagging */ | ||
1561 | TX_VLAN_TAG_OFF = 1<<24,/* disable VLAN tagging */ | ||
1562 | |||
1563 | GMF_WSP_TST_ON = 1<<18,/* Write Shadow Pointer Test On */ | ||
1564 | GMF_WSP_TST_OFF = 1<<17,/* Write Shadow Pointer Test Off */ | ||
1565 | GMF_WSP_STEP = 1<<16,/* Write Shadow Pointer Step/Increment */ | ||
1566 | |||
1567 | GMF_CLI_TX_FU = 1<<6, /* Clear IRQ Tx FIFO Underrun */ | ||
1568 | GMF_CLI_TX_FC = 1<<5, /* Clear IRQ Tx Frame Complete */ | ||
1569 | GMF_CLI_TX_PE = 1<<4, /* Clear IRQ Tx Parity Error */ | ||
1570 | }; | ||
1571 | |||
1572 | /* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ | ||
1573 | enum { | ||
1574 | GMT_ST_START = 1<<2, /* Start Time Stamp Timer */ | ||
1575 | GMT_ST_STOP = 1<<1, /* Stop Time Stamp Timer */ | ||
1576 | GMT_ST_CLR_IRQ = 1<<0, /* Clear Time Stamp Timer IRQ */ | ||
1577 | }; | ||
1578 | |||
1579 | /* B28_Y2_ASF_STAT_CMD 32 bit ASF Status and Command Reg */ | ||
1580 | enum { | ||
1581 | Y2_ASF_OS_PRES = 1<<4, /* ASF operation system present */ | ||
1582 | Y2_ASF_RESET = 1<<3, /* ASF system in reset state */ | ||
1583 | Y2_ASF_RUNNING = 1<<2, /* ASF system operational */ | ||
1584 | Y2_ASF_CLR_HSTI = 1<<1, /* Clear ASF IRQ */ | ||
1585 | Y2_ASF_IRQ = 1<<0, /* Issue an IRQ to ASF system */ | ||
1586 | |||
1587 | Y2_ASF_UC_STATE = 3<<2, /* ASF uC State */ | ||
1588 | Y2_ASF_CLK_HALT = 0, /* ASF system clock stopped */ | ||
1589 | }; | ||
1590 | |||
1591 | /* B28_Y2_ASF_HOST_COM 32 bit ASF Host Communication Reg */ | ||
1592 | enum { | ||
1593 | Y2_ASF_CLR_ASFI = 1<<1, /* Clear host IRQ */ | ||
1594 | Y2_ASF_HOST_IRQ = 1<<0, /* Issue an IRQ to HOST system */ | ||
1595 | }; | ||
1596 | |||
1597 | /* STAT_CTRL 32 bit Status BMU control register (Yukon-2 only) */ | ||
1598 | enum { | ||
1599 | SC_STAT_CLR_IRQ = 1<<4, /* Status Burst IRQ clear */ | ||
1600 | SC_STAT_OP_ON = 1<<3, /* Operational Mode On */ | ||
1601 | SC_STAT_OP_OFF = 1<<2, /* Operational Mode Off */ | ||
1602 | SC_STAT_RST_CLR = 1<<1, /* Clear Status Unit Reset (Enable) */ | ||
1603 | SC_STAT_RST_SET = 1<<0, /* Set Status Unit Reset */ | ||
1604 | }; | ||
1605 | |||
1606 | /* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ | ||
1607 | enum { | ||
1608 | GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */ | ||
1609 | GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */ | ||
1610 | GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */ | ||
1611 | GMC_F_LOOPB_OFF = 1<<4, /* FIFO Loopback Off */ | ||
1612 | GMC_PAUSE_ON = 1<<3, /* Pause On */ | ||
1613 | GMC_PAUSE_OFF = 1<<2, /* Pause Off */ | ||
1614 | GMC_RST_CLR = 1<<1, /* Clear GMAC Reset */ | ||
1615 | GMC_RST_SET = 1<<0, /* Set GMAC Reset */ | ||
1616 | }; | ||
1617 | |||
1618 | /* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */ | ||
1619 | enum { | ||
1620 | GPC_SEL_BDT = 1<<28, /* Select Bi-Dir. Transfer for MDC/MDIO */ | ||
1621 | GPC_INT_POL_HI = 1<<27, /* IRQ Polarity is Active HIGH */ | ||
1622 | GPC_75_OHM = 1<<26, /* Use 75 Ohm Termination instead of 50 */ | ||
1623 | GPC_DIS_FC = 1<<25, /* Disable Automatic Fiber/Copper Detection */ | ||
1624 | GPC_DIS_SLEEP = 1<<24, /* Disable Energy Detect */ | ||
1625 | GPC_HWCFG_M_3 = 1<<23, /* HWCFG_MODE[3] */ | ||
1626 | GPC_HWCFG_M_2 = 1<<22, /* HWCFG_MODE[2] */ | ||
1627 | GPC_HWCFG_M_1 = 1<<21, /* HWCFG_MODE[1] */ | ||
1628 | GPC_HWCFG_M_0 = 1<<20, /* HWCFG_MODE[0] */ | ||
1629 | GPC_ANEG_0 = 1<<19, /* ANEG[0] */ | ||
1630 | GPC_ENA_XC = 1<<18, /* Enable MDI crossover */ | ||
1631 | GPC_DIS_125 = 1<<17, /* Disable 125 MHz clock */ | ||
1632 | GPC_ANEG_3 = 1<<16, /* ANEG[3] */ | ||
1633 | GPC_ANEG_2 = 1<<15, /* ANEG[2] */ | ||
1634 | GPC_ANEG_1 = 1<<14, /* ANEG[1] */ | ||
1635 | GPC_ENA_PAUSE = 1<<13, /* Enable Pause (SYM_OR_REM) */ | ||
1636 | GPC_PHYADDR_4 = 1<<12, /* Bit 4 of Phy Addr */ | ||
1637 | GPC_PHYADDR_3 = 1<<11, /* Bit 3 of Phy Addr */ | ||
1638 | GPC_PHYADDR_2 = 1<<10, /* Bit 2 of Phy Addr */ | ||
1639 | GPC_PHYADDR_1 = 1<<9, /* Bit 1 of Phy Addr */ | ||
1640 | GPC_PHYADDR_0 = 1<<8, /* Bit 0 of Phy Addr */ | ||
1641 | /* Bits 7..2: reserved */ | ||
1642 | GPC_RST_CLR = 1<<1, /* Clear GPHY Reset */ | ||
1643 | GPC_RST_SET = 1<<0, /* Set GPHY Reset */ | ||
1644 | }; | ||
1645 | |||
1646 | /* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */ | ||
1647 | /* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */ | ||
1648 | enum { | ||
1649 | GM_IS_TX_CO_OV = 1<<5, /* Transmit Counter Overflow IRQ */ | ||
1650 | GM_IS_RX_CO_OV = 1<<4, /* Receive Counter Overflow IRQ */ | ||
1651 | GM_IS_TX_FF_UR = 1<<3, /* Transmit FIFO Underrun */ | ||
1652 | GM_IS_TX_COMPL = 1<<2, /* Frame Transmission Complete */ | ||
1653 | GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */ | ||
1654 | GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */ | ||
1655 | |||
1656 | #define GMAC_DEF_MSK GM_IS_TX_FF_UR | ||
1657 | |||
1658 | /* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ | ||
1659 | /* Bits 15.. 2: reserved */ | ||
1660 | GMLC_RST_CLR = 1<<1, /* Clear GMAC Link Reset */ | ||
1661 | GMLC_RST_SET = 1<<0, /* Set GMAC Link Reset */ | ||
1662 | |||
1663 | |||
1664 | /* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ | ||
1665 | WOL_CTL_LINK_CHG_OCC = 1<<15, | ||
1666 | WOL_CTL_MAGIC_PKT_OCC = 1<<14, | ||
1667 | WOL_CTL_PATTERN_OCC = 1<<13, | ||
1668 | WOL_CTL_CLEAR_RESULT = 1<<12, | ||
1669 | WOL_CTL_ENA_PME_ON_LINK_CHG = 1<<11, | ||
1670 | WOL_CTL_DIS_PME_ON_LINK_CHG = 1<<10, | ||
1671 | WOL_CTL_ENA_PME_ON_MAGIC_PKT = 1<<9, | ||
1672 | WOL_CTL_DIS_PME_ON_MAGIC_PKT = 1<<8, | ||
1673 | WOL_CTL_ENA_PME_ON_PATTERN = 1<<7, | ||
1674 | WOL_CTL_DIS_PME_ON_PATTERN = 1<<6, | ||
1675 | WOL_CTL_ENA_LINK_CHG_UNIT = 1<<5, | ||
1676 | WOL_CTL_DIS_LINK_CHG_UNIT = 1<<4, | ||
1677 | WOL_CTL_ENA_MAGIC_PKT_UNIT = 1<<3, | ||
1678 | WOL_CTL_DIS_MAGIC_PKT_UNIT = 1<<2, | ||
1679 | WOL_CTL_ENA_PATTERN_UNIT = 1<<1, | ||
1680 | WOL_CTL_DIS_PATTERN_UNIT = 1<<0, | ||
1681 | }; | ||
1682 | |||
1683 | #define WOL_CTL_DEFAULT \ | ||
1684 | (WOL_CTL_DIS_PME_ON_LINK_CHG | \ | ||
1685 | WOL_CTL_DIS_PME_ON_PATTERN | \ | ||
1686 | WOL_CTL_DIS_PME_ON_MAGIC_PKT | \ | ||
1687 | WOL_CTL_DIS_LINK_CHG_UNIT | \ | ||
1688 | WOL_CTL_DIS_PATTERN_UNIT | \ | ||
1689 | WOL_CTL_DIS_MAGIC_PKT_UNIT) | ||
1690 | |||
1691 | /* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ | ||
1692 | #define WOL_CTL_PATT_ENA(x) (1 << (x)) | ||
1693 | |||
1694 | |||
1695 | /* Control flags */ | ||
1696 | enum { | ||
1697 | UDPTCP = 1<<0, | ||
1698 | CALSUM = 1<<1, | ||
1699 | WR_SUM = 1<<2, | ||
1700 | INIT_SUM= 1<<3, | ||
1701 | LOCK_SUM= 1<<4, | ||
1702 | INS_VLAN= 1<<5, | ||
1703 | FRC_STAT= 1<<6, | ||
1704 | EOP = 1<<7, | ||
1705 | }; | ||
1706 | |||
1707 | enum { | ||
1708 | HW_OWNER = 1<<7, | ||
1709 | OP_TCPWRITE = 0x11, | ||
1710 | OP_TCPSTART = 0x12, | ||
1711 | OP_TCPINIT = 0x14, | ||
1712 | OP_TCPLCK = 0x18, | ||
1713 | OP_TCPCHKSUM = OP_TCPSTART, | ||
1714 | OP_TCPIS = OP_TCPINIT | OP_TCPSTART, | ||
1715 | OP_TCPLW = OP_TCPLCK | OP_TCPWRITE, | ||
1716 | OP_TCPLSW = OP_TCPLCK | OP_TCPSTART | OP_TCPWRITE, | ||
1717 | OP_TCPLISW = OP_TCPLCK | OP_TCPINIT | OP_TCPSTART | OP_TCPWRITE, | ||
1718 | |||
1719 | OP_ADDR64 = 0x21, | ||
1720 | OP_VLAN = 0x22, | ||
1721 | OP_ADDR64VLAN = OP_ADDR64 | OP_VLAN, | ||
1722 | OP_LRGLEN = 0x24, | ||
1723 | OP_LRGLENVLAN = OP_LRGLEN | OP_VLAN, | ||
1724 | OP_BUFFER = 0x40, | ||
1725 | OP_PACKET = 0x41, | ||
1726 | OP_LARGESEND = 0x43, | ||
1727 | |||
1728 | /* YUKON-2 STATUS opcodes defines */ | ||
1729 | OP_RXSTAT = 0x60, | ||
1730 | OP_RXTIMESTAMP = 0x61, | ||
1731 | OP_RXVLAN = 0x62, | ||
1732 | OP_RXCHKS = 0x64, | ||
1733 | OP_RXCHKSVLAN = OP_RXCHKS | OP_RXVLAN, | ||
1734 | OP_RXTIMEVLAN = OP_RXTIMESTAMP | OP_RXVLAN, | ||
1735 | OP_RSS_HASH = 0x65, | ||
1736 | OP_TXINDEXLE = 0x68, | ||
1737 | }; | ||
1738 | |||
1739 | /* Yukon 2 hardware interface | ||
1740 | * Not tested on big endian | ||
1741 | */ | ||
1742 | struct sky2_tx_le { | ||
1743 | union { | ||
1744 | u32 addr; | ||
1745 | struct { | ||
1746 | u16 offset; | ||
1747 | u16 start; | ||
1748 | } csum __attribute((packed)); | ||
1749 | struct { | ||
1750 | u16 size; | ||
1751 | u16 rsvd; | ||
1752 | } tso __attribute((packed)); | ||
1753 | } tx; | ||
1754 | u16 length; /* also vlan tag or checksum start */ | ||
1755 | u8 ctrl; | ||
1756 | u8 opcode; | ||
1757 | } __attribute((packed)); | ||
1758 | |||
1759 | struct sky2_rx_le { | ||
1760 | u32 addr; | ||
1761 | u16 length; | ||
1762 | u8 ctrl; | ||
1763 | u8 opcode; | ||
1764 | } __attribute((packed));; | ||
1765 | |||
1766 | struct sky2_status_le { | ||
1767 | u32 status; /* also checksum */ | ||
1768 | u16 length; /* also vlan tag */ | ||
1769 | u8 link; | ||
1770 | u8 opcode; | ||
1771 | } __attribute((packed)); | ||
1772 | |||
1773 | struct ring_info { | ||
1774 | struct sk_buff *skb; | ||
1775 | dma_addr_t mapaddr; | ||
1776 | u16 maplen; | ||
1777 | u16 idx; | ||
1778 | }; | ||
1779 | |||
1780 | struct sky2_port { | ||
1781 | struct sky2_hw *hw; | ||
1782 | struct net_device *netdev; | ||
1783 | unsigned port; | ||
1784 | u32 msg_enable; | ||
1785 | |||
1786 | struct ring_info *tx_ring; | ||
1787 | struct sky2_tx_le *tx_le; | ||
1788 | spinlock_t tx_lock; | ||
1789 | u32 tx_addr64; | ||
1790 | u16 tx_cons; /* next le to check */ | ||
1791 | u16 tx_prod; /* next le to use */ | ||
1792 | u16 tx_pending; | ||
1793 | u16 tx_last_put; | ||
1794 | u16 tx_last_mss; | ||
1795 | |||
1796 | struct ring_info *rx_ring; | ||
1797 | struct sky2_rx_le *rx_le; | ||
1798 | u32 rx_addr64; | ||
1799 | u16 rx_next; /* next re to check */ | ||
1800 | u16 rx_put; /* next le index to use */ | ||
1801 | u16 rx_pending; | ||
1802 | u16 rx_last_put; | ||
1803 | #ifdef SKY2_VLAN_TAG_USED | ||
1804 | u16 rx_tag; | ||
1805 | struct vlan_group *vlgrp; | ||
1806 | #endif | ||
1807 | |||
1808 | dma_addr_t rx_le_map; | ||
1809 | dma_addr_t tx_le_map; | ||
1810 | u32 advertising; /* ADVERTISED_ bits */ | ||
1811 | u16 speed; /* SPEED_1000, SPEED_100, ... */ | ||
1812 | u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */ | ||
1813 | u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */ | ||
1814 | u8 rx_pause; | ||
1815 | u8 tx_pause; | ||
1816 | u8 rx_csum; | ||
1817 | u8 wol; | ||
1818 | |||
1819 | struct tasklet_struct phy_task; | ||
1820 | struct net_device_stats net_stats; | ||
1821 | }; | ||
1822 | |||
1823 | struct sky2_hw { | ||
1824 | void __iomem *regs; | ||
1825 | struct pci_dev *pdev; | ||
1826 | u32 intr_mask; | ||
1827 | struct net_device *dev[2]; | ||
1828 | |||
1829 | int pm_cap; | ||
1830 | u8 chip_id; | ||
1831 | u8 chip_rev; | ||
1832 | u8 copper; | ||
1833 | u8 ports; | ||
1834 | |||
1835 | struct sky2_status_le *st_le; | ||
1836 | u32 st_idx; | ||
1837 | dma_addr_t st_dma; | ||
1838 | |||
1839 | spinlock_t phy_lock; | ||
1840 | }; | ||
1841 | |||
1842 | /* Register accessor for memory mapped device */ | ||
1843 | static inline u32 sky2_read32(const struct sky2_hw *hw, unsigned reg) | ||
1844 | { | ||
1845 | return readl(hw->regs + reg); | ||
1846 | } | ||
1847 | |||
1848 | static inline u16 sky2_read16(const struct sky2_hw *hw, unsigned reg) | ||
1849 | { | ||
1850 | return readw(hw->regs + reg); | ||
1851 | } | ||
1852 | |||
1853 | static inline u8 sky2_read8(const struct sky2_hw *hw, unsigned reg) | ||
1854 | { | ||
1855 | return readb(hw->regs + reg); | ||
1856 | } | ||
1857 | |||
1858 | /* This should probably go away, bus based tweeks suck */ | ||
1859 | static inline int is_pciex(const struct sky2_hw *hw) | ||
1860 | { | ||
1861 | u32 status; | ||
1862 | pci_read_config_dword(hw->pdev, PCI_DEV_STATUS, &status); | ||
1863 | return (status & PCI_OS_PCI_X) == 0; | ||
1864 | } | ||
1865 | |||
1866 | static inline void sky2_write32(const struct sky2_hw *hw, unsigned reg, u32 val) | ||
1867 | { | ||
1868 | writel(val, hw->regs + reg); | ||
1869 | } | ||
1870 | |||
1871 | static inline void sky2_write16(const struct sky2_hw *hw, unsigned reg, u16 val) | ||
1872 | { | ||
1873 | writew(val, hw->regs + reg); | ||
1874 | } | ||
1875 | |||
1876 | static inline void sky2_write8(const struct sky2_hw *hw, unsigned reg, u8 val) | ||
1877 | { | ||
1878 | writeb(val, hw->regs + reg); | ||
1879 | } | ||
1880 | |||
1881 | /* Yukon PHY related registers */ | ||
1882 | #define SK_GMAC_REG(port,reg) \ | ||
1883 | (BASE_GMAC_1 + (port) * (BASE_GMAC_2-BASE_GMAC_1) + (reg)) | ||
1884 | #define GM_PHY_RETRIES 100 | ||
1885 | |||
1886 | static inline u16 gma_read16(const struct sky2_hw *hw, unsigned port, unsigned reg) | ||
1887 | { | ||
1888 | return sky2_read16(hw, SK_GMAC_REG(port,reg)); | ||
1889 | } | ||
1890 | |||
1891 | static inline u32 gma_read32(struct sky2_hw *hw, unsigned port, unsigned reg) | ||
1892 | { | ||
1893 | unsigned base = SK_GMAC_REG(port, reg); | ||
1894 | return (u32) sky2_read16(hw, base) | ||
1895 | | (u32) sky2_read16(hw, base+4) << 16; | ||
1896 | } | ||
1897 | |||
1898 | static inline void gma_write16(const struct sky2_hw *hw, unsigned port, int r, u16 v) | ||
1899 | { | ||
1900 | sky2_write16(hw, SK_GMAC_REG(port,r), v); | ||
1901 | } | ||
1902 | |||
1903 | static inline void gma_set_addr(struct sky2_hw *hw, unsigned port, unsigned reg, | ||
1904 | const u8 *addr) | ||
1905 | { | ||
1906 | gma_write16(hw, port, reg, (u16) addr[0] | ((u16) addr[1] << 8)); | ||
1907 | gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8)); | ||
1908 | gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8)); | ||
1909 | } | ||
1910 | #endif | ||
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index a10cd184d597..5c2824be4ee6 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h | |||
@@ -100,14 +100,14 @@ | |||
100 | #define SMC_IO_SHIFT 0 | 100 | #define SMC_IO_SHIFT 0 |
101 | #define SMC_NOWAIT 1 | 101 | #define SMC_NOWAIT 1 |
102 | 102 | ||
103 | #define SMC_inb(a, r) inb((a) + (r)) | 103 | #define SMC_inb(a, r) readb((a) + (r)) |
104 | #define SMC_insb(a, r, p, l) insb((a) + (r), p, (l)) | 104 | #define SMC_insb(a, r, p, l) readsb((a) + (r), p, (l)) |
105 | #define SMC_inw(a, r) inw((a) + (r)) | 105 | #define SMC_inw(a, r) readw((a) + (r)) |
106 | #define SMC_insw(a, r, p, l) insw((a) + (r), p, l) | 106 | #define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) |
107 | #define SMC_outb(v, a, r) outb(v, (a) + (r)) | 107 | #define SMC_outb(v, a, r) writeb(v, (a) + (r)) |
108 | #define SMC_outsb(a, r, p, l) outsb((a) + (r), p, (l)) | 108 | #define SMC_outsb(a, r, p, l) writesb((a) + (r), p, (l)) |
109 | #define SMC_outw(v, a, r) outw(v, (a) + (r)) | 109 | #define SMC_outw(v, a, r) writew(v, (a) + (r)) |
110 | #define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) | 110 | #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) |
111 | 111 | ||
112 | #define set_irq_type(irq, type) do {} while (0) | 112 | #define set_irq_type(irq, type) do {} while (0) |
113 | 113 | ||
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index de399563a9db..081717d01374 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c | |||
@@ -128,6 +128,8 @@ static struct pci_device_id gem_pci_tbl[] = { | |||
128 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | 128 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, |
129 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_SUNGEM, | 129 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_SUNGEM, |
130 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | 130 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, |
131 | { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_GMAC, | ||
132 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, | ||
131 | {0, } | 133 | {0, } |
132 | }; | 134 | }; |
133 | 135 | ||
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c index 7c2cf2e76300..032c0f81928e 100644 --- a/drivers/net/wan/sdladrv.c +++ b/drivers/net/wan/sdladrv.c | |||
@@ -1994,7 +1994,7 @@ static int detect_s514 (sdlahw_t* hw) | |||
1994 | modname, hw->irq); | 1994 | modname, hw->irq); |
1995 | 1995 | ||
1996 | /* map the physical PCI memory to virtual memory */ | 1996 | /* map the physical PCI memory to virtual memory */ |
1997 | (void *)hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr, | 1997 | hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr, |
1998 | (unsigned long)MAX_SIZEOF_S514_MEMORY); | 1998 | (unsigned long)MAX_SIZEOF_S514_MEMORY); |
1999 | /* map the physical control register memory to virtual memory */ | 1999 | /* map the physical control register memory to virtual memory */ |
2000 | hw->vector = (unsigned long)ioremap( | 2000 | hw->vector = (unsigned long)ioremap( |
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index b0d195d1721a..5e7c7e944c9d 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
@@ -1110,8 +1110,7 @@ static struct ipw_fw_error *ipw_alloc_error_log(struct ipw_priv *priv) | |||
1110 | error->elem_len = elem_len; | 1110 | error->elem_len = elem_len; |
1111 | error->log_len = log_len; | 1111 | error->log_len = log_len; |
1112 | error->elem = (struct ipw_error_elem *)error->payload; | 1112 | error->elem = (struct ipw_error_elem *)error->payload; |
1113 | error->log = (struct ipw_event *)(error->elem + | 1113 | error->log = (struct ipw_event *)(error->elem + elem_len); |
1114 | (sizeof(*error->elem) * elem_len)); | ||
1115 | 1114 | ||
1116 | ipw_capture_event_log(priv, log_len, error->log); | 1115 | ipw_capture_event_log(priv, log_len, error->log); |
1117 | 1116 | ||
@@ -8926,6 +8925,10 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, | |||
8926 | struct ipw_scan_request_ext scan; | 8925 | struct ipw_scan_request_ext scan; |
8927 | int err = 0, scan_type; | 8926 | int err = 0, scan_type; |
8928 | 8927 | ||
8928 | if (!(priv->status & STATUS_INIT) || | ||
8929 | (priv->status & STATUS_EXIT_PENDING)) | ||
8930 | return 0; | ||
8931 | |||
8929 | down(&priv->sem); | 8932 | down(&priv->sem); |
8930 | 8933 | ||
8931 | if (priv->status & STATUS_RF_KILL_MASK) { | 8934 | if (priv->status & STATUS_RF_KILL_MASK) { |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 4a3cecca012c..2387e75da0fe 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/interrupt.h> | ||
35 | |||
34 | #include "../pci.h" | 36 | #include "../pci.h" |
35 | #include "pciehp.h" | 37 | #include "pciehp.h" |
36 | 38 | ||
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index a7859a84d1ae..4b35097b3d9f 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c | |||
@@ -253,7 +253,7 @@ rpaphp_pci_config_slot(struct pci_bus *bus) | |||
253 | if (!dn || !dn->child) | 253 | if (!dn || !dn->child) |
254 | return NULL; | 254 | return NULL; |
255 | 255 | ||
256 | if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { | 256 | if (_machine == PLATFORM_PSERIES_LPAR) { |
257 | of_scan_bus(dn, bus); | 257 | of_scan_bus(dn, bus); |
258 | if (list_empty(&bus->devices)) { | 258 | if (list_empty(&bus->devices)) { |
259 | err("%s: No new device found\n", __FUNCTION__); | 259 | err("%s: No new device found\n", __FUNCTION__); |
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 40905a6c8094..9987a6fd65b8 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/interrupt.h> | ||
35 | |||
34 | #include "shpchp.h" | 36 | #include "shpchp.h" |
35 | 37 | ||
36 | #ifdef DEBUG | 38 | #ifdef DEBUG |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 234cdca6fe13..a30aa74304a2 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -513,6 +513,11 @@ static int socket_insert(struct pcmcia_socket *skt) | |||
513 | ret = socket_setup(skt, setup_delay); | 513 | ret = socket_setup(skt, setup_delay); |
514 | if (ret == CS_SUCCESS) { | 514 | if (ret == CS_SUCCESS) { |
515 | skt->state |= SOCKET_PRESENT; | 515 | skt->state |= SOCKET_PRESENT; |
516 | |||
517 | printk(KERN_NOTICE "pccard: %s card inserted into slot %d\n", | ||
518 | (skt->state & SOCKET_CARDBUS) ? "CardBus" : "PCMCIA", | ||
519 | skt->sock); | ||
520 | |||
516 | #ifdef CONFIG_CARDBUS | 521 | #ifdef CONFIG_CARDBUS |
517 | if (skt->state & SOCKET_CARDBUS) { | 522 | if (skt->state & SOCKET_CARDBUS) { |
518 | cb_alloc(skt); | 523 | cb_alloc(skt); |
@@ -598,6 +603,7 @@ static int socket_resume(struct pcmcia_socket *skt) | |||
598 | 603 | ||
599 | static void socket_remove(struct pcmcia_socket *skt) | 604 | static void socket_remove(struct pcmcia_socket *skt) |
600 | { | 605 | { |
606 | printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock); | ||
601 | socket_shutdown(skt); | 607 | socket_shutdown(skt); |
602 | cs_socket_put(skt); | 608 | cs_socket_put(skt); |
603 | } | 609 | } |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 39d096b52926..7f8219f3fd9e 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -544,6 +544,9 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
544 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); | 544 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); |
545 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 545 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
546 | 546 | ||
547 | printk(KERN_NOTICE "pcmcia: registering new device %s\n", | ||
548 | p_dev->devname); | ||
549 | |||
547 | pcmcia_device_query(p_dev); | 550 | pcmcia_device_query(p_dev); |
548 | 551 | ||
549 | if (device_register(&p_dev->dev)) { | 552 | if (device_register(&p_dev->dev)) { |
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 4ddd76239b34..4d56bc9926d6 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c | |||
@@ -1339,10 +1339,7 @@ static struct device_driver i82365_driver = { | |||
1339 | .resume = pcmcia_socket_dev_resume, | 1339 | .resume = pcmcia_socket_dev_resume, |
1340 | }; | 1340 | }; |
1341 | 1341 | ||
1342 | static struct platform_device i82365_device = { | 1342 | static struct platform_device *i82365_device; |
1343 | .name = "i82365", | ||
1344 | .id = 0, | ||
1345 | }; | ||
1346 | 1343 | ||
1347 | static int __init init_i82365(void) | 1344 | static int __init init_i82365(void) |
1348 | { | 1345 | { |
@@ -1352,7 +1349,14 @@ static int __init init_i82365(void) | |||
1352 | if (ret) | 1349 | if (ret) |
1353 | return ret; | 1350 | return ret; |
1354 | 1351 | ||
1355 | ret = platform_device_register(&i82365_device); | 1352 | i82365_device = platform_device_alloc("i82365", 0); |
1353 | if (i82365_device) { | ||
1354 | ret = platform_device_add(i82365_device); | ||
1355 | if (ret) | ||
1356 | platform_device_put(i82365_device); | ||
1357 | } else | ||
1358 | ret = -ENOMEM; | ||
1359 | |||
1356 | if (ret) { | 1360 | if (ret) { |
1357 | driver_unregister(&i82365_driver); | 1361 | driver_unregister(&i82365_driver); |
1358 | return ret; | 1362 | return ret; |
@@ -1365,7 +1369,7 @@ static int __init init_i82365(void) | |||
1365 | 1369 | ||
1366 | if (sockets == 0) { | 1370 | if (sockets == 0) { |
1367 | printk("not found.\n"); | 1371 | printk("not found.\n"); |
1368 | platform_device_unregister(&i82365_device); | 1372 | platform_device_unregister(i82365_device); |
1369 | release_region(i365_base, 2); | 1373 | release_region(i365_base, 2); |
1370 | driver_unregister(&i82365_driver); | 1374 | driver_unregister(&i82365_driver); |
1371 | return -ENODEV; | 1375 | return -ENODEV; |
@@ -1377,7 +1381,7 @@ static int __init init_i82365(void) | |||
1377 | 1381 | ||
1378 | /* register sockets with the pcmcia core */ | 1382 | /* register sockets with the pcmcia core */ |
1379 | for (i = 0; i < sockets; i++) { | 1383 | for (i = 0; i < sockets; i++) { |
1380 | socket[i].socket.dev.dev = &i82365_device.dev; | 1384 | socket[i].socket.dev.dev = &i82365_device->dev; |
1381 | socket[i].socket.ops = &pcic_operations; | 1385 | socket[i].socket.ops = &pcic_operations; |
1382 | socket[i].socket.resource_ops = &pccard_nonstatic_ops; | 1386 | socket[i].socket.resource_ops = &pccard_nonstatic_ops; |
1383 | socket[i].socket.owner = THIS_MODULE; | 1387 | socket[i].socket.owner = THIS_MODULE; |
@@ -1415,7 +1419,7 @@ static void __exit exit_i82365(void) | |||
1415 | if (socket[i].flags & IS_REGISTERED) | 1419 | if (socket[i].flags & IS_REGISTERED) |
1416 | pcmcia_unregister_socket(&socket[i].socket); | 1420 | pcmcia_unregister_socket(&socket[i].socket); |
1417 | } | 1421 | } |
1418 | platform_device_unregister(&i82365_device); | 1422 | platform_device_unregister(i82365_device); |
1419 | if (poll_interval != 0) | 1423 | if (poll_interval != 0) |
1420 | del_timer_sync(&poll_timer); | 1424 | del_timer_sync(&poll_timer); |
1421 | if (grab_irq != 0) | 1425 | if (grab_irq != 0) |
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index f5b7d360fc10..1026f2bc3185 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c | |||
@@ -1179,12 +1179,12 @@ raw3270_create_attributes(struct raw3270 *rp) | |||
1179 | //FIXME: check return code | 1179 | //FIXME: check return code |
1180 | sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group); | 1180 | sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group); |
1181 | rp->clttydev = | 1181 | rp->clttydev = |
1182 | class_device_create(class3270, | 1182 | class_device_create(class3270, NULL, |
1183 | MKDEV(IBM_TTY3270_MAJOR, rp->minor), | 1183 | MKDEV(IBM_TTY3270_MAJOR, rp->minor), |
1184 | &rp->cdev->dev, "tty%s", | 1184 | &rp->cdev->dev, "tty%s", |
1185 | rp->cdev->dev.bus_id); | 1185 | rp->cdev->dev.bus_id); |
1186 | rp->cltubdev = | 1186 | rp->cltubdev = |
1187 | class_device_create(class3270, | 1187 | class_device_create(class3270, NULL, |
1188 | MKDEV(IBM_FS3270_MAJOR, rp->minor), | 1188 | MKDEV(IBM_FS3270_MAJOR, rp->minor), |
1189 | &rp->cdev->dev, "tub%s", | 1189 | &rp->cdev->dev, "tub%s", |
1190 | rp->cdev->dev.bus_id); | 1190 | rp->cdev->dev.bus_id); |
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c index 5774bdd0e26f..9b988baf0b51 100644 --- a/drivers/sbus/char/rtc.c +++ b/drivers/sbus/char/rtc.c | |||
@@ -210,27 +210,6 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
210 | } | 210 | } |
211 | } | 211 | } |
212 | 212 | ||
213 | static long rtc_compat_ioctl(struct file *file, unsigned int cmd, | ||
214 | unsigned long arg) | ||
215 | { | ||
216 | int rval = -ENOIOCTLCMD; | ||
217 | |||
218 | switch (cmd) { | ||
219 | /* | ||
220 | * These two are specific to this driver, the generic rtc ioctls | ||
221 | * are hanlded elsewhere. | ||
222 | */ | ||
223 | case RTCGET: | ||
224 | case RTCSET: | ||
225 | lock_kernel(); | ||
226 | rval = rtc_ioctl(file->f_dentry->d_inode, file, cmd, arg); | ||
227 | unlock_kernel(); | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | return rval; | ||
232 | } | ||
233 | |||
234 | static int rtc_open(struct inode *inode, struct file *file) | 213 | static int rtc_open(struct inode *inode, struct file *file) |
235 | { | 214 | { |
236 | int ret; | 215 | int ret; |
@@ -258,7 +237,6 @@ static struct file_operations rtc_fops = { | |||
258 | .owner = THIS_MODULE, | 237 | .owner = THIS_MODULE, |
259 | .llseek = no_llseek, | 238 | .llseek = no_llseek, |
260 | .ioctl = rtc_ioctl, | 239 | .ioctl = rtc_ioctl, |
261 | .compat_ioctl = rtc_compat_ioctl, | ||
262 | .open = rtc_open, | 240 | .open = rtc_open, |
263 | .release = rtc_release, | 241 | .release = rtc_release, |
264 | }; | 242 | }; |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 84c42c44e04d..20dd85a77813 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -497,7 +497,7 @@ config SCSI_ATA_PIIX | |||
497 | If unsure, say N. | 497 | If unsure, say N. |
498 | 498 | ||
499 | config SCSI_SATA_MV | 499 | config SCSI_SATA_MV |
500 | tristate "Marvell SATA support" | 500 | tristate "Marvell SATA support (HIGHLY EXPERIMENTAL)" |
501 | depends on SCSI_SATA && PCI && EXPERIMENTAL | 501 | depends on SCSI_SATA && PCI && EXPERIMENTAL |
502 | help | 502 | help |
503 | This option enables support for the Marvell Serial ATA family. | 503 | This option enables support for the Marvell Serial ATA family. |
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 57ef7ae387d9..83467a05dc8e 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c | |||
@@ -48,7 +48,7 @@ | |||
48 | #include <asm/io.h> | 48 | #include <asm/io.h> |
49 | 49 | ||
50 | #define DRV_NAME "ahci" | 50 | #define DRV_NAME "ahci" |
51 | #define DRV_VERSION "1.01" | 51 | #define DRV_VERSION "1.2" |
52 | 52 | ||
53 | 53 | ||
54 | enum { | 54 | enum { |
@@ -134,6 +134,7 @@ enum { | |||
134 | PORT_IRQ_D2H_REG_FIS, | 134 | PORT_IRQ_D2H_REG_FIS, |
135 | 135 | ||
136 | /* PORT_CMD bits */ | 136 | /* PORT_CMD bits */ |
137 | PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ | ||
137 | PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ | 138 | PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ |
138 | PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ | 139 | PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ |
139 | PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */ | 140 | PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */ |
@@ -441,7 +442,7 @@ static void ahci_phy_reset(struct ata_port *ap) | |||
441 | void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; | 442 | void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; |
442 | struct ata_taskfile tf; | 443 | struct ata_taskfile tf; |
443 | struct ata_device *dev = &ap->device[0]; | 444 | struct ata_device *dev = &ap->device[0]; |
444 | u32 tmp; | 445 | u32 new_tmp, tmp; |
445 | 446 | ||
446 | __sata_phy_reset(ap); | 447 | __sata_phy_reset(ap); |
447 | 448 | ||
@@ -455,8 +456,21 @@ static void ahci_phy_reset(struct ata_port *ap) | |||
455 | tf.nsect = (tmp) & 0xff; | 456 | tf.nsect = (tmp) & 0xff; |
456 | 457 | ||
457 | dev->class = ata_dev_classify(&tf); | 458 | dev->class = ata_dev_classify(&tf); |
458 | if (!ata_dev_present(dev)) | 459 | if (!ata_dev_present(dev)) { |
459 | ata_port_disable(ap); | 460 | ata_port_disable(ap); |
461 | return; | ||
462 | } | ||
463 | |||
464 | /* Make sure port's ATAPI bit is set appropriately */ | ||
465 | new_tmp = tmp = readl(port_mmio + PORT_CMD); | ||
466 | if (dev->class == ATA_DEV_ATAPI) | ||
467 | new_tmp |= PORT_CMD_ATAPI; | ||
468 | else | ||
469 | new_tmp &= ~PORT_CMD_ATAPI; | ||
470 | if (new_tmp != tmp) { | ||
471 | writel(new_tmp, port_mmio + PORT_CMD); | ||
472 | readl(port_mmio + PORT_CMD); /* flush */ | ||
473 | } | ||
460 | } | 474 | } |
461 | 475 | ||
462 | static u8 ahci_check_status(struct ata_port *ap) | 476 | static u8 ahci_check_status(struct ata_port *ap) |
@@ -474,11 +488,12 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf) | |||
474 | ata_tf_from_fis(d2h_fis, tf); | 488 | ata_tf_from_fis(d2h_fis, tf); |
475 | } | 489 | } |
476 | 490 | ||
477 | static void ahci_fill_sg(struct ata_queued_cmd *qc) | 491 | static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc) |
478 | { | 492 | { |
479 | struct ahci_port_priv *pp = qc->ap->private_data; | 493 | struct ahci_port_priv *pp = qc->ap->private_data; |
480 | struct scatterlist *sg; | 494 | struct scatterlist *sg; |
481 | struct ahci_sg *ahci_sg; | 495 | struct ahci_sg *ahci_sg; |
496 | unsigned int n_sg = 0; | ||
482 | 497 | ||
483 | VPRINTK("ENTER\n"); | 498 | VPRINTK("ENTER\n"); |
484 | 499 | ||
@@ -493,8 +508,12 @@ static void ahci_fill_sg(struct ata_queued_cmd *qc) | |||
493 | ahci_sg->addr = cpu_to_le32(addr & 0xffffffff); | 508 | ahci_sg->addr = cpu_to_le32(addr & 0xffffffff); |
494 | ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); | 509 | ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); |
495 | ahci_sg->flags_size = cpu_to_le32(sg_len - 1); | 510 | ahci_sg->flags_size = cpu_to_le32(sg_len - 1); |
511 | |||
496 | ahci_sg++; | 512 | ahci_sg++; |
513 | n_sg++; | ||
497 | } | 514 | } |
515 | |||
516 | return n_sg; | ||
498 | } | 517 | } |
499 | 518 | ||
500 | static void ahci_qc_prep(struct ata_queued_cmd *qc) | 519 | static void ahci_qc_prep(struct ata_queued_cmd *qc) |
@@ -503,13 +522,14 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) | |||
503 | struct ahci_port_priv *pp = ap->private_data; | 522 | struct ahci_port_priv *pp = ap->private_data; |
504 | u32 opts; | 523 | u32 opts; |
505 | const u32 cmd_fis_len = 5; /* five dwords */ | 524 | const u32 cmd_fis_len = 5; /* five dwords */ |
525 | unsigned int n_elem; | ||
506 | 526 | ||
507 | /* | 527 | /* |
508 | * Fill in command slot information (currently only one slot, | 528 | * Fill in command slot information (currently only one slot, |
509 | * slot 0, is currently since we don't do queueing) | 529 | * slot 0, is currently since we don't do queueing) |
510 | */ | 530 | */ |
511 | 531 | ||
512 | opts = (qc->n_elem << 16) | cmd_fis_len; | 532 | opts = cmd_fis_len; |
513 | if (qc->tf.flags & ATA_TFLAG_WRITE) | 533 | if (qc->tf.flags & ATA_TFLAG_WRITE) |
514 | opts |= AHCI_CMD_WRITE; | 534 | opts |= AHCI_CMD_WRITE; |
515 | if (is_atapi_taskfile(&qc->tf)) | 535 | if (is_atapi_taskfile(&qc->tf)) |
@@ -533,16 +553,31 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) | |||
533 | if (!(qc->flags & ATA_QCFLAG_DMAMAP)) | 553 | if (!(qc->flags & ATA_QCFLAG_DMAMAP)) |
534 | return; | 554 | return; |
535 | 555 | ||
536 | ahci_fill_sg(qc); | 556 | n_elem = ahci_fill_sg(qc); |
557 | |||
558 | pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16); | ||
537 | } | 559 | } |
538 | 560 | ||
539 | static void ahci_intr_error(struct ata_port *ap, u32 irq_stat) | 561 | static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) |
540 | { | 562 | { |
541 | void __iomem *mmio = ap->host_set->mmio_base; | 563 | void __iomem *mmio = ap->host_set->mmio_base; |
542 | void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); | 564 | void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); |
543 | u32 tmp; | 565 | u32 tmp; |
544 | int work; | 566 | int work; |
545 | 567 | ||
568 | if ((ap->device[0].class != ATA_DEV_ATAPI) || | ||
569 | ((irq_stat & PORT_IRQ_TF_ERR) == 0)) | ||
570 | printk(KERN_WARNING "ata%u: port reset, " | ||
571 | "p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n", | ||
572 | ap->id, | ||
573 | irq_stat, | ||
574 | readl(mmio + HOST_IRQ_STAT), | ||
575 | readl(port_mmio + PORT_IRQ_STAT), | ||
576 | readl(port_mmio + PORT_CMD), | ||
577 | readl(port_mmio + PORT_TFDATA), | ||
578 | readl(port_mmio + PORT_SCR_STAT), | ||
579 | readl(port_mmio + PORT_SCR_ERR)); | ||
580 | |||
546 | /* stop DMA */ | 581 | /* stop DMA */ |
547 | tmp = readl(port_mmio + PORT_CMD); | 582 | tmp = readl(port_mmio + PORT_CMD); |
548 | tmp &= ~PORT_CMD_START; | 583 | tmp &= ~PORT_CMD_START; |
@@ -580,8 +615,6 @@ static void ahci_intr_error(struct ata_port *ap, u32 irq_stat) | |||
580 | tmp |= PORT_CMD_START; | 615 | tmp |= PORT_CMD_START; |
581 | writel(tmp, port_mmio + PORT_CMD); | 616 | writel(tmp, port_mmio + PORT_CMD); |
582 | readl(port_mmio + PORT_CMD); /* flush */ | 617 | readl(port_mmio + PORT_CMD); /* flush */ |
583 | |||
584 | printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->id); | ||
585 | } | 618 | } |
586 | 619 | ||
587 | static void ahci_eng_timeout(struct ata_port *ap) | 620 | static void ahci_eng_timeout(struct ata_port *ap) |
@@ -592,17 +625,17 @@ static void ahci_eng_timeout(struct ata_port *ap) | |||
592 | struct ata_queued_cmd *qc; | 625 | struct ata_queued_cmd *qc; |
593 | unsigned long flags; | 626 | unsigned long flags; |
594 | 627 | ||
595 | DPRINTK("ENTER\n"); | 628 | printk(KERN_WARNING "ata%u: handling error/timeout\n", ap->id); |
596 | 629 | ||
597 | spin_lock_irqsave(&host_set->lock, flags); | 630 | spin_lock_irqsave(&host_set->lock, flags); |
598 | 631 | ||
599 | ahci_intr_error(ap, readl(port_mmio + PORT_IRQ_STAT)); | ||
600 | |||
601 | qc = ata_qc_from_tag(ap, ap->active_tag); | 632 | qc = ata_qc_from_tag(ap, ap->active_tag); |
602 | if (!qc) { | 633 | if (!qc) { |
603 | printk(KERN_ERR "ata%u: BUG: timeout without command\n", | 634 | printk(KERN_ERR "ata%u: BUG: timeout without command\n", |
604 | ap->id); | 635 | ap->id); |
605 | } else { | 636 | } else { |
637 | ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT)); | ||
638 | |||
606 | /* hack alert! We cannot use the supplied completion | 639 | /* hack alert! We cannot use the supplied completion |
607 | * function from inside the ->eh_strategy_handler() thread. | 640 | * function from inside the ->eh_strategy_handler() thread. |
608 | * libata is the only user of ->eh_strategy_handler() in | 641 | * libata is the only user of ->eh_strategy_handler() in |
@@ -637,9 +670,19 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) | |||
637 | } | 670 | } |
638 | 671 | ||
639 | if (status & PORT_IRQ_FATAL) { | 672 | if (status & PORT_IRQ_FATAL) { |
640 | ahci_intr_error(ap, status); | 673 | unsigned int err_mask; |
674 | if (status & PORT_IRQ_TF_ERR) | ||
675 | err_mask = AC_ERR_DEV; | ||
676 | else if (status & PORT_IRQ_IF_ERR) | ||
677 | err_mask = AC_ERR_ATA_BUS; | ||
678 | else | ||
679 | err_mask = AC_ERR_HOST_BUS; | ||
680 | |||
681 | /* command processing has stopped due to error; restart */ | ||
682 | ahci_restart_port(ap, status); | ||
683 | |||
641 | if (qc) | 684 | if (qc) |
642 | ata_qc_complete(qc, AC_ERR_OTHER); | 685 | ata_qc_complete(qc, err_mask); |
643 | } | 686 | } |
644 | 687 | ||
645 | return 1; | 688 | return 1; |
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 855428ff37e9..333d69dd84ef 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c | |||
@@ -50,7 +50,7 @@ | |||
50 | #include <linux/libata.h> | 50 | #include <linux/libata.h> |
51 | 51 | ||
52 | #define DRV_NAME "ata_piix" | 52 | #define DRV_NAME "ata_piix" |
53 | #define DRV_VERSION "1.04" | 53 | #define DRV_VERSION "1.05" |
54 | 54 | ||
55 | enum { | 55 | enum { |
56 | PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ | 56 | PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ |
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index e51d9a8a2796..665ae79e1fd6 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -532,8 +532,7 @@ void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp) | |||
532 | * @fis: Buffer from which data will be input | 532 | * @fis: Buffer from which data will be input |
533 | * @tf: Taskfile to output | 533 | * @tf: Taskfile to output |
534 | * | 534 | * |
535 | * Converts a standard ATA taskfile to a Serial ATA | 535 | * Converts a serial ATA FIS structure to a standard ATA taskfile. |
536 | * FIS structure (Register - Host to Device). | ||
537 | * | 536 | * |
538 | * LOCKING: | 537 | * LOCKING: |
539 | * Inherited from caller. | 538 | * Inherited from caller. |
@@ -1047,6 +1046,30 @@ static unsigned int ata_pio_modes(const struct ata_device *adev) | |||
1047 | return modes; | 1046 | return modes; |
1048 | } | 1047 | } |
1049 | 1048 | ||
1049 | static int ata_qc_wait_err(struct ata_queued_cmd *qc, | ||
1050 | struct completion *wait) | ||
1051 | { | ||
1052 | int rc = 0; | ||
1053 | |||
1054 | if (wait_for_completion_timeout(wait, 30 * HZ) < 1) { | ||
1055 | /* timeout handling */ | ||
1056 | unsigned int err_mask = ac_err_mask(ata_chk_status(qc->ap)); | ||
1057 | |||
1058 | if (!err_mask) { | ||
1059 | printk(KERN_WARNING "ata%u: slow completion (cmd %x)\n", | ||
1060 | qc->ap->id, qc->tf.command); | ||
1061 | } else { | ||
1062 | printk(KERN_WARNING "ata%u: qc timeout (cmd %x)\n", | ||
1063 | qc->ap->id, qc->tf.command); | ||
1064 | rc = -EIO; | ||
1065 | } | ||
1066 | |||
1067 | ata_qc_complete(qc, err_mask); | ||
1068 | } | ||
1069 | |||
1070 | return rc; | ||
1071 | } | ||
1072 | |||
1050 | /** | 1073 | /** |
1051 | * ata_dev_identify - obtain IDENTIFY x DEVICE page | 1074 | * ata_dev_identify - obtain IDENTIFY x DEVICE page |
1052 | * @ap: port on which device we wish to probe resides | 1075 | * @ap: port on which device we wish to probe resides |
@@ -1126,7 +1149,7 @@ retry: | |||
1126 | if (rc) | 1149 | if (rc) |
1127 | goto err_out; | 1150 | goto err_out; |
1128 | else | 1151 | else |
1129 | wait_for_completion(&wait); | 1152 | ata_qc_wait_err(qc, &wait); |
1130 | 1153 | ||
1131 | spin_lock_irqsave(&ap->host_set->lock, flags); | 1154 | spin_lock_irqsave(&ap->host_set->lock, flags); |
1132 | ap->ops->tf_read(ap, &qc->tf); | 1155 | ap->ops->tf_read(ap, &qc->tf); |
@@ -1264,7 +1287,7 @@ retry: | |||
1264 | } | 1287 | } |
1265 | 1288 | ||
1266 | /* ATAPI-specific feature tests */ | 1289 | /* ATAPI-specific feature tests */ |
1267 | else { | 1290 | else if (dev->class == ATA_DEV_ATAPI) { |
1268 | if (ata_id_is_ata(dev->id)) /* sanity check */ | 1291 | if (ata_id_is_ata(dev->id)) /* sanity check */ |
1269 | goto err_out_nosup; | 1292 | goto err_out_nosup; |
1270 | 1293 | ||
@@ -1571,11 +1594,13 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, | |||
1571 | 1594 | ||
1572 | /* | 1595 | /* |
1573 | * Find the mode. | 1596 | * Find the mode. |
1574 | */ | 1597 | */ |
1575 | 1598 | ||
1576 | if (!(s = ata_timing_find_mode(speed))) | 1599 | if (!(s = ata_timing_find_mode(speed))) |
1577 | return -EINVAL; | 1600 | return -EINVAL; |
1578 | 1601 | ||
1602 | memcpy(t, s, sizeof(*s)); | ||
1603 | |||
1579 | /* | 1604 | /* |
1580 | * If the drive is an EIDE drive, it can tell us it needs extended | 1605 | * If the drive is an EIDE drive, it can tell us it needs extended |
1581 | * PIO/MW_DMA cycle timing. | 1606 | * PIO/MW_DMA cycle timing. |
@@ -1596,7 +1621,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, | |||
1596 | * Convert the timing to bus clock counts. | 1621 | * Convert the timing to bus clock counts. |
1597 | */ | 1622 | */ |
1598 | 1623 | ||
1599 | ata_timing_quantize(s, t, T, UT); | 1624 | ata_timing_quantize(t, t, T, UT); |
1600 | 1625 | ||
1601 | /* | 1626 | /* |
1602 | * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T | 1627 | * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T |
@@ -2268,7 +2293,7 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev) | |||
2268 | if (rc) | 2293 | if (rc) |
2269 | ata_port_disable(ap); | 2294 | ata_port_disable(ap); |
2270 | else | 2295 | else |
2271 | wait_for_completion(&wait); | 2296 | ata_qc_wait_err(qc, &wait); |
2272 | 2297 | ||
2273 | DPRINTK("EXIT\n"); | 2298 | DPRINTK("EXIT\n"); |
2274 | } | 2299 | } |
@@ -2316,7 +2341,7 @@ static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev) | |||
2316 | if (rc) | 2341 | if (rc) |
2317 | goto err_out; | 2342 | goto err_out; |
2318 | 2343 | ||
2319 | wait_for_completion(&wait); | 2344 | ata_qc_wait_err(qc, &wait); |
2320 | 2345 | ||
2321 | swap_buf_le16(dev->id, ATA_ID_WORDS); | 2346 | swap_buf_le16(dev->id, ATA_ID_WORDS); |
2322 | 2347 | ||
@@ -2372,7 +2397,7 @@ static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev) | |||
2372 | if (rc) | 2397 | if (rc) |
2373 | ata_port_disable(ap); | 2398 | ata_port_disable(ap); |
2374 | else | 2399 | else |
2375 | wait_for_completion(&wait); | 2400 | ata_qc_wait_err(qc, &wait); |
2376 | 2401 | ||
2377 | DPRINTK("EXIT\n"); | 2402 | DPRINTK("EXIT\n"); |
2378 | } | 2403 | } |
@@ -2400,7 +2425,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) | |||
2400 | if (qc->flags & ATA_QCFLAG_SINGLE) | 2425 | if (qc->flags & ATA_QCFLAG_SINGLE) |
2401 | assert(qc->n_elem == 1); | 2426 | assert(qc->n_elem == 1); |
2402 | 2427 | ||
2403 | DPRINTK("unmapping %u sg elements\n", qc->n_elem); | 2428 | VPRINTK("unmapping %u sg elements\n", qc->n_elem); |
2404 | 2429 | ||
2405 | /* if we padded the buffer out to 32-bit bound, and data | 2430 | /* if we padded the buffer out to 32-bit bound, and data |
2406 | * xfer direction is from-device, we must copy from the | 2431 | * xfer direction is from-device, we must copy from the |
@@ -2410,7 +2435,8 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) | |||
2410 | pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); | 2435 | pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); |
2411 | 2436 | ||
2412 | if (qc->flags & ATA_QCFLAG_SG) { | 2437 | if (qc->flags & ATA_QCFLAG_SG) { |
2413 | dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir); | 2438 | if (qc->n_elem) |
2439 | dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir); | ||
2414 | /* restore last sg */ | 2440 | /* restore last sg */ |
2415 | sg[qc->orig_n_elem - 1].length += qc->pad_len; | 2441 | sg[qc->orig_n_elem - 1].length += qc->pad_len; |
2416 | if (pad_buf) { | 2442 | if (pad_buf) { |
@@ -2420,8 +2446,10 @@ static void ata_sg_clean(struct ata_queued_cmd *qc) | |||
2420 | kunmap_atomic(psg->page, KM_IRQ0); | 2446 | kunmap_atomic(psg->page, KM_IRQ0); |
2421 | } | 2447 | } |
2422 | } else { | 2448 | } else { |
2423 | dma_unmap_single(ap->host_set->dev, sg_dma_address(&sg[0]), | 2449 | if (sg_dma_len(&sg[0]) > 0) |
2424 | sg_dma_len(&sg[0]), dir); | 2450 | dma_unmap_single(ap->host_set->dev, |
2451 | sg_dma_address(&sg[0]), sg_dma_len(&sg[0]), | ||
2452 | dir); | ||
2425 | /* restore sg */ | 2453 | /* restore sg */ |
2426 | sg->length += qc->pad_len; | 2454 | sg->length += qc->pad_len; |
2427 | if (pad_buf) | 2455 | if (pad_buf) |
@@ -2620,6 +2648,11 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) | |||
2620 | sg->length, qc->pad_len); | 2648 | sg->length, qc->pad_len); |
2621 | } | 2649 | } |
2622 | 2650 | ||
2651 | if (!sg->length) { | ||
2652 | sg_dma_address(sg) = 0; | ||
2653 | goto skip_map; | ||
2654 | } | ||
2655 | |||
2623 | dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt, | 2656 | dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt, |
2624 | sg->length, dir); | 2657 | sg->length, dir); |
2625 | if (dma_mapping_error(dma_address)) { | 2658 | if (dma_mapping_error(dma_address)) { |
@@ -2629,6 +2662,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc) | |||
2629 | } | 2662 | } |
2630 | 2663 | ||
2631 | sg_dma_address(sg) = dma_address; | 2664 | sg_dma_address(sg) = dma_address; |
2665 | skip_map: | ||
2632 | sg_dma_len(sg) = sg->length; | 2666 | sg_dma_len(sg) = sg->length; |
2633 | 2667 | ||
2634 | DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg), | 2668 | DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg), |
@@ -2656,7 +2690,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) | |||
2656 | struct ata_port *ap = qc->ap; | 2690 | struct ata_port *ap = qc->ap; |
2657 | struct scatterlist *sg = qc->__sg; | 2691 | struct scatterlist *sg = qc->__sg; |
2658 | struct scatterlist *lsg = &sg[qc->n_elem - 1]; | 2692 | struct scatterlist *lsg = &sg[qc->n_elem - 1]; |
2659 | int n_elem, dir; | 2693 | int n_elem, pre_n_elem, dir, trim_sg = 0; |
2660 | 2694 | ||
2661 | VPRINTK("ENTER, ata%u\n", ap->id); | 2695 | VPRINTK("ENTER, ata%u\n", ap->id); |
2662 | assert(qc->flags & ATA_QCFLAG_SG); | 2696 | assert(qc->flags & ATA_QCFLAG_SG); |
@@ -2690,13 +2724,24 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) | |||
2690 | sg_dma_len(psg) = ATA_DMA_PAD_SZ; | 2724 | sg_dma_len(psg) = ATA_DMA_PAD_SZ; |
2691 | /* trim last sg */ | 2725 | /* trim last sg */ |
2692 | lsg->length -= qc->pad_len; | 2726 | lsg->length -= qc->pad_len; |
2727 | if (lsg->length == 0) | ||
2728 | trim_sg = 1; | ||
2693 | 2729 | ||
2694 | DPRINTK("padding done, sg[%d].length=%u pad_len=%u\n", | 2730 | DPRINTK("padding done, sg[%d].length=%u pad_len=%u\n", |
2695 | qc->n_elem - 1, lsg->length, qc->pad_len); | 2731 | qc->n_elem - 1, lsg->length, qc->pad_len); |
2696 | } | 2732 | } |
2697 | 2733 | ||
2734 | pre_n_elem = qc->n_elem; | ||
2735 | if (trim_sg && pre_n_elem) | ||
2736 | pre_n_elem--; | ||
2737 | |||
2738 | if (!pre_n_elem) { | ||
2739 | n_elem = 0; | ||
2740 | goto skip_map; | ||
2741 | } | ||
2742 | |||
2698 | dir = qc->dma_dir; | 2743 | dir = qc->dma_dir; |
2699 | n_elem = dma_map_sg(ap->host_set->dev, sg, qc->n_elem, dir); | 2744 | n_elem = dma_map_sg(ap->host_set->dev, sg, pre_n_elem, dir); |
2700 | if (n_elem < 1) { | 2745 | if (n_elem < 1) { |
2701 | /* restore last sg */ | 2746 | /* restore last sg */ |
2702 | lsg->length += qc->pad_len; | 2747 | lsg->length += qc->pad_len; |
@@ -2705,6 +2750,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) | |||
2705 | 2750 | ||
2706 | DPRINTK("%d sg elements mapped\n", n_elem); | 2751 | DPRINTK("%d sg elements mapped\n", n_elem); |
2707 | 2752 | ||
2753 | skip_map: | ||
2708 | qc->n_elem = n_elem; | 2754 | qc->n_elem = n_elem; |
2709 | 2755 | ||
2710 | return 0; | 2756 | return 0; |
@@ -3264,32 +3310,11 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) | |||
3264 | { | 3310 | { |
3265 | struct ata_port *ap = qc->ap; | 3311 | struct ata_port *ap = qc->ap; |
3266 | struct ata_host_set *host_set = ap->host_set; | 3312 | struct ata_host_set *host_set = ap->host_set; |
3267 | struct ata_device *dev = qc->dev; | ||
3268 | u8 host_stat = 0, drv_stat; | 3313 | u8 host_stat = 0, drv_stat; |
3269 | unsigned long flags; | 3314 | unsigned long flags; |
3270 | 3315 | ||
3271 | DPRINTK("ENTER\n"); | 3316 | DPRINTK("ENTER\n"); |
3272 | 3317 | ||
3273 | /* FIXME: doesn't this conflict with timeout handling? */ | ||
3274 | if (qc->dev->class == ATA_DEV_ATAPI && qc->scsicmd) { | ||
3275 | struct scsi_cmnd *cmd = qc->scsicmd; | ||
3276 | |||
3277 | if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) { | ||
3278 | |||
3279 | /* finish completing original command */ | ||
3280 | spin_lock_irqsave(&host_set->lock, flags); | ||
3281 | __ata_qc_complete(qc); | ||
3282 | spin_unlock_irqrestore(&host_set->lock, flags); | ||
3283 | |||
3284 | atapi_request_sense(ap, dev, cmd); | ||
3285 | |||
3286 | cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16); | ||
3287 | scsi_finish_command(cmd); | ||
3288 | |||
3289 | goto out; | ||
3290 | } | ||
3291 | } | ||
3292 | |||
3293 | spin_lock_irqsave(&host_set->lock, flags); | 3318 | spin_lock_irqsave(&host_set->lock, flags); |
3294 | 3319 | ||
3295 | /* hack alert! We cannot use the supplied completion | 3320 | /* hack alert! We cannot use the supplied completion |
@@ -3328,7 +3353,6 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) | |||
3328 | 3353 | ||
3329 | spin_unlock_irqrestore(&host_set->lock, flags); | 3354 | spin_unlock_irqrestore(&host_set->lock, flags); |
3330 | 3355 | ||
3331 | out: | ||
3332 | DPRINTK("EXIT\n"); | 3356 | DPRINTK("EXIT\n"); |
3333 | } | 3357 | } |
3334 | 3358 | ||
@@ -3412,16 +3436,11 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, | |||
3412 | 3436 | ||
3413 | qc = ata_qc_new(ap); | 3437 | qc = ata_qc_new(ap); |
3414 | if (qc) { | 3438 | if (qc) { |
3415 | qc->__sg = NULL; | ||
3416 | qc->flags = 0; | ||
3417 | qc->scsicmd = NULL; | 3439 | qc->scsicmd = NULL; |
3418 | qc->ap = ap; | 3440 | qc->ap = ap; |
3419 | qc->dev = dev; | 3441 | qc->dev = dev; |
3420 | qc->cursect = qc->cursg = qc->cursg_ofs = 0; | ||
3421 | qc->nsect = 0; | ||
3422 | qc->nbytes = qc->curbytes = 0; | ||
3423 | 3442 | ||
3424 | ata_tf_init(ap, &qc->tf, dev->devno); | 3443 | ata_qc_reinit(qc); |
3425 | } | 3444 | } |
3426 | 3445 | ||
3427 | return qc; | 3446 | return qc; |
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 261be24e1df3..3b4ca55a3332 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -1955,22 +1955,44 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 | |||
1955 | done(cmd); | 1955 | done(cmd); |
1956 | } | 1956 | } |
1957 | 1957 | ||
1958 | void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, | 1958 | static int atapi_sense_complete(struct ata_queued_cmd *qc,unsigned int err_mask) |
1959 | struct scsi_cmnd *cmd) | ||
1960 | { | 1959 | { |
1961 | DECLARE_COMPLETION(wait); | 1960 | if (err_mask && ((err_mask & AC_ERR_DEV) == 0)) |
1962 | struct ata_queued_cmd *qc; | 1961 | /* FIXME: not quite right; we don't want the |
1963 | unsigned long flags; | 1962 | * translation of taskfile registers into |
1964 | int rc; | 1963 | * a sense descriptors, since that's only |
1964 | * correct for ATA, not ATAPI | ||
1965 | */ | ||
1966 | ata_gen_ata_desc_sense(qc); | ||
1965 | 1967 | ||
1966 | DPRINTK("ATAPI request sense\n"); | 1968 | qc->scsidone(qc->scsicmd); |
1969 | return 0; | ||
1970 | } | ||
1967 | 1971 | ||
1968 | qc = ata_qc_new_init(ap, dev); | 1972 | /* is it pointless to prefer PIO for "safety reasons"? */ |
1969 | BUG_ON(qc == NULL); | 1973 | static inline int ata_pio_use_silly(struct ata_port *ap) |
1974 | { | ||
1975 | return (ap->flags & ATA_FLAG_PIO_DMA); | ||
1976 | } | ||
1977 | |||
1978 | static void atapi_request_sense(struct ata_queued_cmd *qc) | ||
1979 | { | ||
1980 | struct ata_port *ap = qc->ap; | ||
1981 | struct scsi_cmnd *cmd = qc->scsicmd; | ||
1982 | |||
1983 | DPRINTK("ATAPI request sense\n"); | ||
1970 | 1984 | ||
1971 | /* FIXME: is this needed? */ | 1985 | /* FIXME: is this needed? */ |
1972 | memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); | 1986 | memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); |
1973 | 1987 | ||
1988 | ap->ops->tf_read(ap, &qc->tf); | ||
1989 | |||
1990 | /* fill these in, for the case where they are -not- overwritten */ | ||
1991 | cmd->sense_buffer[0] = 0x70; | ||
1992 | cmd->sense_buffer[2] = qc->tf.feature >> 4; | ||
1993 | |||
1994 | ata_qc_reinit(qc); | ||
1995 | |||
1974 | ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer)); | 1996 | ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer)); |
1975 | qc->dma_dir = DMA_FROM_DEVICE; | 1997 | qc->dma_dir = DMA_FROM_DEVICE; |
1976 | 1998 | ||
@@ -1981,22 +2003,20 @@ void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, | |||
1981 | qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; | 2003 | qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; |
1982 | qc->tf.command = ATA_CMD_PACKET; | 2004 | qc->tf.command = ATA_CMD_PACKET; |
1983 | 2005 | ||
1984 | qc->tf.protocol = ATA_PROT_ATAPI; | 2006 | if (ata_pio_use_silly(ap)) { |
1985 | qc->tf.lbam = (8 * 1024) & 0xff; | 2007 | qc->tf.protocol = ATA_PROT_ATAPI_DMA; |
1986 | qc->tf.lbah = (8 * 1024) >> 8; | 2008 | qc->tf.feature |= ATAPI_PKT_DMA; |
2009 | } else { | ||
2010 | qc->tf.protocol = ATA_PROT_ATAPI; | ||
2011 | qc->tf.lbam = (8 * 1024) & 0xff; | ||
2012 | qc->tf.lbah = (8 * 1024) >> 8; | ||
2013 | } | ||
1987 | qc->nbytes = SCSI_SENSE_BUFFERSIZE; | 2014 | qc->nbytes = SCSI_SENSE_BUFFERSIZE; |
1988 | 2015 | ||
1989 | qc->waiting = &wait; | 2016 | qc->complete_fn = atapi_sense_complete; |
1990 | qc->complete_fn = ata_qc_complete_noop; | ||
1991 | |||
1992 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
1993 | rc = ata_qc_issue(qc); | ||
1994 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
1995 | 2017 | ||
1996 | if (rc) | 2018 | if (ata_qc_issue(qc)) |
1997 | ata_port_disable(ap); | 2019 | ata_qc_complete(qc, AC_ERR_OTHER); |
1998 | else | ||
1999 | wait_for_completion(&wait); | ||
2000 | 2020 | ||
2001 | DPRINTK("EXIT\n"); | 2021 | DPRINTK("EXIT\n"); |
2002 | } | 2022 | } |
@@ -2008,19 +2028,8 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask) | |||
2008 | VPRINTK("ENTER, err_mask 0x%X\n", err_mask); | 2028 | VPRINTK("ENTER, err_mask 0x%X\n", err_mask); |
2009 | 2029 | ||
2010 | if (unlikely(err_mask & AC_ERR_DEV)) { | 2030 | if (unlikely(err_mask & AC_ERR_DEV)) { |
2011 | DPRINTK("request check condition\n"); | ||
2012 | |||
2013 | /* FIXME: command completion with check condition | ||
2014 | * but no sense causes the error handler to run, | ||
2015 | * which then issues REQUEST SENSE, fills in the sense | ||
2016 | * buffer, and completes the command (for the second | ||
2017 | * time). We need to issue REQUEST SENSE some other | ||
2018 | * way, to avoid completing the command twice. | ||
2019 | */ | ||
2020 | cmd->result = SAM_STAT_CHECK_CONDITION; | 2031 | cmd->result = SAM_STAT_CHECK_CONDITION; |
2021 | 2032 | atapi_request_sense(qc); | |
2022 | qc->scsidone(cmd); | ||
2023 | |||
2024 | return 1; | 2033 | return 1; |
2025 | } | 2034 | } |
2026 | 2035 | ||
@@ -2276,6 +2285,12 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) | |||
2276 | tf->device = scsicmd[8]; | 2285 | tf->device = scsicmd[8]; |
2277 | tf->command = scsicmd[9]; | 2286 | tf->command = scsicmd[9]; |
2278 | } | 2287 | } |
2288 | /* | ||
2289 | * If slave is possible, enforce correct master/slave bit | ||
2290 | */ | ||
2291 | if (qc->ap->flags & ATA_FLAG_SLAVE_POSS) | ||
2292 | tf->device = qc->dev->devno ? | ||
2293 | tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1; | ||
2279 | 2294 | ||
2280 | /* | 2295 | /* |
2281 | * Filter SET_FEATURES - XFER MODE command -- otherwise, | 2296 | * Filter SET_FEATURES - XFER MODE command -- otherwise, |
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index fad051ca4672..8ebaa694d18e 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h | |||
@@ -29,7 +29,7 @@ | |||
29 | #define __LIBATA_H__ | 29 | #define __LIBATA_H__ |
30 | 30 | ||
31 | #define DRV_NAME "libata" | 31 | #define DRV_NAME "libata" |
32 | #define DRV_VERSION "1.12" /* must be exactly four chars */ | 32 | #define DRV_VERSION "1.20" /* must be exactly four chars */ |
33 | 33 | ||
34 | struct ata_scsi_args { | 34 | struct ata_scsi_args { |
35 | u16 *id; | 35 | u16 *id; |
@@ -54,8 +54,6 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); | |||
54 | 54 | ||
55 | 55 | ||
56 | /* libata-scsi.c */ | 56 | /* libata-scsi.c */ |
57 | extern void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, | ||
58 | struct scsi_cmnd *cmd); | ||
59 | extern void ata_scsi_scan_host(struct ata_port *ap); | 57 | extern void ata_scsi_scan_host(struct ata_port *ap); |
60 | extern int ata_scsi_error(struct Scsi_Host *host); | 58 | extern int ata_scsi_error(struct Scsi_Host *host); |
61 | extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, | 59 | extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, |
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 257c128f4aaa..ac184e60797e 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * sata_mv.c - Marvell SATA support | 2 | * sata_mv.c - Marvell SATA support |
3 | * | 3 | * |
4 | * Copyright 2005: EMC Corporation, all rights reserved. | 4 | * Copyright 2005: EMC Corporation, all rights reserved. |
5 | * | 5 | * |
6 | * Please ALWAYS copy linux-ide@vger.kernel.org on emails. | 6 | * Please ALWAYS copy linux-ide@vger.kernel.org on emails. |
7 | * | 7 | * |
@@ -50,6 +50,9 @@ enum { | |||
50 | MV_PCI_REG_BASE = 0, | 50 | MV_PCI_REG_BASE = 0, |
51 | MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */ | 51 | MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */ |
52 | MV_SATAHC0_REG_BASE = 0x20000, | 52 | MV_SATAHC0_REG_BASE = 0x20000, |
53 | MV_FLASH_CTL = 0x1046c, | ||
54 | MV_GPIO_PORT_CTL = 0x104f0, | ||
55 | MV_RESET_CFG = 0x180d8, | ||
53 | 56 | ||
54 | MV_PCI_REG_SZ = MV_MAJOR_REG_AREA_SZ, | 57 | MV_PCI_REG_SZ = MV_MAJOR_REG_AREA_SZ, |
55 | MV_SATAHC_REG_SZ = MV_MAJOR_REG_AREA_SZ, | 58 | MV_SATAHC_REG_SZ = MV_MAJOR_REG_AREA_SZ, |
@@ -72,11 +75,6 @@ enum { | |||
72 | MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT), | 75 | MV_SG_TBL_SZ = (16 * MV_MAX_SG_CT), |
73 | MV_PORT_PRIV_DMA_SZ = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ), | 76 | MV_PORT_PRIV_DMA_SZ = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ), |
74 | 77 | ||
75 | /* Our DMA boundary is determined by an ePRD being unable to handle | ||
76 | * anything larger than 64KB | ||
77 | */ | ||
78 | MV_DMA_BOUNDARY = 0xffffU, | ||
79 | |||
80 | MV_PORTS_PER_HC = 4, | 78 | MV_PORTS_PER_HC = 4, |
81 | /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */ | 79 | /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */ |
82 | MV_PORT_HC_SHIFT = 2, | 80 | MV_PORT_HC_SHIFT = 2, |
@@ -86,16 +84,9 @@ enum { | |||
86 | /* Host Flags */ | 84 | /* Host Flags */ |
87 | MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */ | 85 | MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */ |
88 | MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ | 86 | MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ |
89 | MV_FLAG_GLBL_SFT_RST = (1 << 28), /* Global Soft Reset support */ | ||
90 | MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 87 | MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
91 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO), | 88 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO), |
92 | MV_6XXX_FLAGS = (MV_FLAG_IRQ_COALESCE | | 89 | MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE, |
93 | MV_FLAG_GLBL_SFT_RST), | ||
94 | |||
95 | chip_504x = 0, | ||
96 | chip_508x = 1, | ||
97 | chip_604x = 2, | ||
98 | chip_608x = 3, | ||
99 | 90 | ||
100 | CRQB_FLAG_READ = (1 << 0), | 91 | CRQB_FLAG_READ = (1 << 0), |
101 | CRQB_TAG_SHIFT = 1, | 92 | CRQB_TAG_SHIFT = 1, |
@@ -116,8 +107,19 @@ enum { | |||
116 | PCI_MASTER_EMPTY = (1 << 3), | 107 | PCI_MASTER_EMPTY = (1 << 3), |
117 | GLOB_SFT_RST = (1 << 4), | 108 | GLOB_SFT_RST = (1 << 4), |
118 | 109 | ||
119 | PCI_IRQ_CAUSE_OFS = 0x1d58, | 110 | MV_PCI_MODE = 0xd00, |
120 | PCI_IRQ_MASK_OFS = 0x1d5c, | 111 | MV_PCI_EXP_ROM_BAR_CTL = 0xd2c, |
112 | MV_PCI_DISC_TIMER = 0xd04, | ||
113 | MV_PCI_MSI_TRIGGER = 0xc38, | ||
114 | MV_PCI_SERR_MASK = 0xc28, | ||
115 | MV_PCI_XBAR_TMOUT = 0x1d04, | ||
116 | MV_PCI_ERR_LOW_ADDRESS = 0x1d40, | ||
117 | MV_PCI_ERR_HIGH_ADDRESS = 0x1d44, | ||
118 | MV_PCI_ERR_ATTRIBUTE = 0x1d48, | ||
119 | MV_PCI_ERR_COMMAND = 0x1d50, | ||
120 | |||
121 | PCI_IRQ_CAUSE_OFS = 0x1d58, | ||
122 | PCI_IRQ_MASK_OFS = 0x1d5c, | ||
121 | PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */ | 123 | PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */ |
122 | 124 | ||
123 | HC_MAIN_IRQ_CAUSE_OFS = 0x1d60, | 125 | HC_MAIN_IRQ_CAUSE_OFS = 0x1d60, |
@@ -134,7 +136,7 @@ enum { | |||
134 | SELF_INT = (1 << 23), | 136 | SELF_INT = (1 << 23), |
135 | TWSI_INT = (1 << 24), | 137 | TWSI_INT = (1 << 24), |
136 | HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */ | 138 | HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */ |
137 | HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE | | 139 | HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE | |
138 | PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT | | 140 | PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT | |
139 | HC_MAIN_RSVD), | 141 | HC_MAIN_RSVD), |
140 | 142 | ||
@@ -153,6 +155,15 @@ enum { | |||
153 | /* SATA registers */ | 155 | /* SATA registers */ |
154 | SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */ | 156 | SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */ |
155 | SATA_ACTIVE_OFS = 0x350, | 157 | SATA_ACTIVE_OFS = 0x350, |
158 | PHY_MODE3 = 0x310, | ||
159 | PHY_MODE4 = 0x314, | ||
160 | PHY_MODE2 = 0x330, | ||
161 | MV5_PHY_MODE = 0x74, | ||
162 | MV5_LT_MODE = 0x30, | ||
163 | MV5_PHY_CTL = 0x0C, | ||
164 | SATA_INTERFACE_CTL = 0x050, | ||
165 | |||
166 | MV_M2_PREAMP_MASK = 0x7e0, | ||
156 | 167 | ||
157 | /* Port registers */ | 168 | /* Port registers */ |
158 | EDMA_CFG_OFS = 0, | 169 | EDMA_CFG_OFS = 0, |
@@ -182,17 +193,16 @@ enum { | |||
182 | EDMA_ERR_LNK_CTRL_TX = (0x1f << 21), | 193 | EDMA_ERR_LNK_CTRL_TX = (0x1f << 21), |
183 | EDMA_ERR_LNK_DATA_TX = (0x1f << 26), | 194 | EDMA_ERR_LNK_DATA_TX = (0x1f << 26), |
184 | EDMA_ERR_TRANS_PROTO = (1 << 31), | 195 | EDMA_ERR_TRANS_PROTO = (1 << 31), |
185 | EDMA_ERR_FATAL = (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR | | 196 | EDMA_ERR_FATAL = (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR | |
186 | EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR | | 197 | EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR | |
187 | EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR | | 198 | EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR | |
188 | EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 | | 199 | EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 | |
189 | EDMA_ERR_LNK_DATA_RX | | 200 | EDMA_ERR_LNK_DATA_RX | |
190 | EDMA_ERR_LNK_DATA_TX | | 201 | EDMA_ERR_LNK_DATA_TX | |
191 | EDMA_ERR_TRANS_PROTO), | 202 | EDMA_ERR_TRANS_PROTO), |
192 | 203 | ||
193 | EDMA_REQ_Q_BASE_HI_OFS = 0x10, | 204 | EDMA_REQ_Q_BASE_HI_OFS = 0x10, |
194 | EDMA_REQ_Q_IN_PTR_OFS = 0x14, /* also contains BASE_LO */ | 205 | EDMA_REQ_Q_IN_PTR_OFS = 0x14, /* also contains BASE_LO */ |
195 | EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U, | ||
196 | 206 | ||
197 | EDMA_REQ_Q_OUT_PTR_OFS = 0x18, | 207 | EDMA_REQ_Q_OUT_PTR_OFS = 0x18, |
198 | EDMA_REQ_Q_PTR_SHIFT = 5, | 208 | EDMA_REQ_Q_PTR_SHIFT = 5, |
@@ -200,7 +210,6 @@ enum { | |||
200 | EDMA_RSP_Q_BASE_HI_OFS = 0x1c, | 210 | EDMA_RSP_Q_BASE_HI_OFS = 0x1c, |
201 | EDMA_RSP_Q_IN_PTR_OFS = 0x20, | 211 | EDMA_RSP_Q_IN_PTR_OFS = 0x20, |
202 | EDMA_RSP_Q_OUT_PTR_OFS = 0x24, /* also contains BASE_LO */ | 212 | EDMA_RSP_Q_OUT_PTR_OFS = 0x24, /* also contains BASE_LO */ |
203 | EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U, | ||
204 | EDMA_RSP_Q_PTR_SHIFT = 3, | 213 | EDMA_RSP_Q_PTR_SHIFT = 3, |
205 | 214 | ||
206 | EDMA_CMD_OFS = 0x28, | 215 | EDMA_CMD_OFS = 0x28, |
@@ -208,14 +217,44 @@ enum { | |||
208 | EDMA_DS = (1 << 1), | 217 | EDMA_DS = (1 << 1), |
209 | ATA_RST = (1 << 2), | 218 | ATA_RST = (1 << 2), |
210 | 219 | ||
220 | EDMA_IORDY_TMOUT = 0x34, | ||
221 | EDMA_ARB_CFG = 0x38, | ||
222 | |||
211 | /* Host private flags (hp_flags) */ | 223 | /* Host private flags (hp_flags) */ |
212 | MV_HP_FLAG_MSI = (1 << 0), | 224 | MV_HP_FLAG_MSI = (1 << 0), |
225 | MV_HP_ERRATA_50XXB0 = (1 << 1), | ||
226 | MV_HP_ERRATA_50XXB2 = (1 << 2), | ||
227 | MV_HP_ERRATA_60X1B2 = (1 << 3), | ||
228 | MV_HP_ERRATA_60X1C0 = (1 << 4), | ||
229 | MV_HP_50XX = (1 << 5), | ||
213 | 230 | ||
214 | /* Port private flags (pp_flags) */ | 231 | /* Port private flags (pp_flags) */ |
215 | MV_PP_FLAG_EDMA_EN = (1 << 0), | 232 | MV_PP_FLAG_EDMA_EN = (1 << 0), |
216 | MV_PP_FLAG_EDMA_DS_ACT = (1 << 1), | 233 | MV_PP_FLAG_EDMA_DS_ACT = (1 << 1), |
217 | }; | 234 | }; |
218 | 235 | ||
236 | #define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX) | ||
237 | #define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0) | ||
238 | |||
239 | enum { | ||
240 | /* Our DMA boundary is determined by an ePRD being unable to handle | ||
241 | * anything larger than 64KB | ||
242 | */ | ||
243 | MV_DMA_BOUNDARY = 0xffffU, | ||
244 | |||
245 | EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U, | ||
246 | |||
247 | EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U, | ||
248 | }; | ||
249 | |||
250 | enum chip_type { | ||
251 | chip_504x, | ||
252 | chip_508x, | ||
253 | chip_5080, | ||
254 | chip_604x, | ||
255 | chip_608x, | ||
256 | }; | ||
257 | |||
219 | /* Command ReQuest Block: 32B */ | 258 | /* Command ReQuest Block: 32B */ |
220 | struct mv_crqb { | 259 | struct mv_crqb { |
221 | u32 sg_addr; | 260 | u32 sg_addr; |
@@ -252,14 +291,37 @@ struct mv_port_priv { | |||
252 | u32 pp_flags; | 291 | u32 pp_flags; |
253 | }; | 292 | }; |
254 | 293 | ||
294 | struct mv_port_signal { | ||
295 | u32 amps; | ||
296 | u32 pre; | ||
297 | }; | ||
298 | |||
299 | struct mv_host_priv; | ||
300 | struct mv_hw_ops { | ||
301 | void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
302 | unsigned int port); | ||
303 | void (*enable_leds)(struct mv_host_priv *hpriv, void __iomem *mmio); | ||
304 | void (*read_preamp)(struct mv_host_priv *hpriv, int idx, | ||
305 | void __iomem *mmio); | ||
306 | int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
307 | unsigned int n_hc); | ||
308 | void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio); | ||
309 | void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio); | ||
310 | }; | ||
311 | |||
255 | struct mv_host_priv { | 312 | struct mv_host_priv { |
256 | u32 hp_flags; | 313 | u32 hp_flags; |
314 | struct mv_port_signal signal[8]; | ||
315 | const struct mv_hw_ops *ops; | ||
257 | }; | 316 | }; |
258 | 317 | ||
259 | static void mv_irq_clear(struct ata_port *ap); | 318 | static void mv_irq_clear(struct ata_port *ap); |
260 | static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in); | 319 | static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in); |
261 | static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); | 320 | static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); |
321 | static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in); | ||
322 | static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); | ||
262 | static void mv_phy_reset(struct ata_port *ap); | 323 | static void mv_phy_reset(struct ata_port *ap); |
324 | static void __mv_phy_reset(struct ata_port *ap, int can_sleep); | ||
263 | static void mv_host_stop(struct ata_host_set *host_set); | 325 | static void mv_host_stop(struct ata_host_set *host_set); |
264 | static int mv_port_start(struct ata_port *ap); | 326 | static int mv_port_start(struct ata_port *ap); |
265 | static void mv_port_stop(struct ata_port *ap); | 327 | static void mv_port_stop(struct ata_port *ap); |
@@ -270,6 +332,29 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, | |||
270 | static void mv_eng_timeout(struct ata_port *ap); | 332 | static void mv_eng_timeout(struct ata_port *ap); |
271 | static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); | 333 | static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); |
272 | 334 | ||
335 | static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
336 | unsigned int port); | ||
337 | static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); | ||
338 | static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, | ||
339 | void __iomem *mmio); | ||
340 | static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
341 | unsigned int n_hc); | ||
342 | static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); | ||
343 | static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio); | ||
344 | |||
345 | static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
346 | unsigned int port); | ||
347 | static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); | ||
348 | static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, | ||
349 | void __iomem *mmio); | ||
350 | static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
351 | unsigned int n_hc); | ||
352 | static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); | ||
353 | static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio); | ||
354 | static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
355 | unsigned int port_no); | ||
356 | static void mv_stop_and_reset(struct ata_port *ap); | ||
357 | |||
273 | static struct scsi_host_template mv_sht = { | 358 | static struct scsi_host_template mv_sht = { |
274 | .module = THIS_MODULE, | 359 | .module = THIS_MODULE, |
275 | .name = DRV_NAME, | 360 | .name = DRV_NAME, |
@@ -278,7 +363,7 @@ static struct scsi_host_template mv_sht = { | |||
278 | .eh_strategy_handler = ata_scsi_error, | 363 | .eh_strategy_handler = ata_scsi_error, |
279 | .can_queue = MV_USE_Q_DEPTH, | 364 | .can_queue = MV_USE_Q_DEPTH, |
280 | .this_id = ATA_SHT_THIS_ID, | 365 | .this_id = ATA_SHT_THIS_ID, |
281 | .sg_tablesize = MV_MAX_SG_CT, | 366 | .sg_tablesize = MV_MAX_SG_CT / 2, |
282 | .max_sectors = ATA_MAX_SECTORS, | 367 | .max_sectors = ATA_MAX_SECTORS, |
283 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, | 368 | .cmd_per_lun = ATA_SHT_CMD_PER_LUN, |
284 | .emulated = ATA_SHT_EMULATED, | 369 | .emulated = ATA_SHT_EMULATED, |
@@ -290,7 +375,34 @@ static struct scsi_host_template mv_sht = { | |||
290 | .ordered_flush = 1, | 375 | .ordered_flush = 1, |
291 | }; | 376 | }; |
292 | 377 | ||
293 | static const struct ata_port_operations mv_ops = { | 378 | static const struct ata_port_operations mv5_ops = { |
379 | .port_disable = ata_port_disable, | ||
380 | |||
381 | .tf_load = ata_tf_load, | ||
382 | .tf_read = ata_tf_read, | ||
383 | .check_status = ata_check_status, | ||
384 | .exec_command = ata_exec_command, | ||
385 | .dev_select = ata_std_dev_select, | ||
386 | |||
387 | .phy_reset = mv_phy_reset, | ||
388 | |||
389 | .qc_prep = mv_qc_prep, | ||
390 | .qc_issue = mv_qc_issue, | ||
391 | |||
392 | .eng_timeout = mv_eng_timeout, | ||
393 | |||
394 | .irq_handler = mv_interrupt, | ||
395 | .irq_clear = mv_irq_clear, | ||
396 | |||
397 | .scr_read = mv5_scr_read, | ||
398 | .scr_write = mv5_scr_write, | ||
399 | |||
400 | .port_start = mv_port_start, | ||
401 | .port_stop = mv_port_stop, | ||
402 | .host_stop = mv_host_stop, | ||
403 | }; | ||
404 | |||
405 | static const struct ata_port_operations mv6_ops = { | ||
294 | .port_disable = ata_port_disable, | 406 | .port_disable = ata_port_disable, |
295 | 407 | ||
296 | .tf_load = ata_tf_load, | 408 | .tf_load = ata_tf_load, |
@@ -322,37 +434,44 @@ static struct ata_port_info mv_port_info[] = { | |||
322 | .sht = &mv_sht, | 434 | .sht = &mv_sht, |
323 | .host_flags = MV_COMMON_FLAGS, | 435 | .host_flags = MV_COMMON_FLAGS, |
324 | .pio_mask = 0x1f, /* pio0-4 */ | 436 | .pio_mask = 0x1f, /* pio0-4 */ |
325 | .udma_mask = 0, /* 0x7f (udma0-6 disabled for now) */ | 437 | .udma_mask = 0x7f, /* udma0-6 */ |
326 | .port_ops = &mv_ops, | 438 | .port_ops = &mv5_ops, |
327 | }, | 439 | }, |
328 | { /* chip_508x */ | 440 | { /* chip_508x */ |
329 | .sht = &mv_sht, | 441 | .sht = &mv_sht, |
330 | .host_flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC), | 442 | .host_flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC), |
331 | .pio_mask = 0x1f, /* pio0-4 */ | 443 | .pio_mask = 0x1f, /* pio0-4 */ |
332 | .udma_mask = 0, /* 0x7f (udma0-6 disabled for now) */ | 444 | .udma_mask = 0x7f, /* udma0-6 */ |
333 | .port_ops = &mv_ops, | 445 | .port_ops = &mv5_ops, |
446 | }, | ||
447 | { /* chip_5080 */ | ||
448 | .sht = &mv_sht, | ||
449 | .host_flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC), | ||
450 | .pio_mask = 0x1f, /* pio0-4 */ | ||
451 | .udma_mask = 0x7f, /* udma0-6 */ | ||
452 | .port_ops = &mv5_ops, | ||
334 | }, | 453 | }, |
335 | { /* chip_604x */ | 454 | { /* chip_604x */ |
336 | .sht = &mv_sht, | 455 | .sht = &mv_sht, |
337 | .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), | 456 | .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), |
338 | .pio_mask = 0x1f, /* pio0-4 */ | 457 | .pio_mask = 0x1f, /* pio0-4 */ |
339 | .udma_mask = 0x7f, /* udma0-6 */ | 458 | .udma_mask = 0x7f, /* udma0-6 */ |
340 | .port_ops = &mv_ops, | 459 | .port_ops = &mv6_ops, |
341 | }, | 460 | }, |
342 | { /* chip_608x */ | 461 | { /* chip_608x */ |
343 | .sht = &mv_sht, | 462 | .sht = &mv_sht, |
344 | .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS | | 463 | .host_flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS | |
345 | MV_FLAG_DUAL_HC), | 464 | MV_FLAG_DUAL_HC), |
346 | .pio_mask = 0x1f, /* pio0-4 */ | 465 | .pio_mask = 0x1f, /* pio0-4 */ |
347 | .udma_mask = 0x7f, /* udma0-6 */ | 466 | .udma_mask = 0x7f, /* udma0-6 */ |
348 | .port_ops = &mv_ops, | 467 | .port_ops = &mv6_ops, |
349 | }, | 468 | }, |
350 | }; | 469 | }; |
351 | 470 | ||
352 | static const struct pci_device_id mv_pci_tbl[] = { | 471 | static const struct pci_device_id mv_pci_tbl[] = { |
353 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x}, | 472 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x}, |
354 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x}, | 473 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x}, |
355 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_508x}, | 474 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_5080}, |
356 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5081), 0, 0, chip_508x}, | 475 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5081), 0, 0, chip_508x}, |
357 | 476 | ||
358 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x}, | 477 | {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x}, |
@@ -371,6 +490,24 @@ static struct pci_driver mv_pci_driver = { | |||
371 | .remove = ata_pci_remove_one, | 490 | .remove = ata_pci_remove_one, |
372 | }; | 491 | }; |
373 | 492 | ||
493 | static const struct mv_hw_ops mv5xxx_ops = { | ||
494 | .phy_errata = mv5_phy_errata, | ||
495 | .enable_leds = mv5_enable_leds, | ||
496 | .read_preamp = mv5_read_preamp, | ||
497 | .reset_hc = mv5_reset_hc, | ||
498 | .reset_flash = mv5_reset_flash, | ||
499 | .reset_bus = mv5_reset_bus, | ||
500 | }; | ||
501 | |||
502 | static const struct mv_hw_ops mv6xxx_ops = { | ||
503 | .phy_errata = mv6_phy_errata, | ||
504 | .enable_leds = mv6_enable_leds, | ||
505 | .read_preamp = mv6_read_preamp, | ||
506 | .reset_hc = mv6_reset_hc, | ||
507 | .reset_flash = mv6_reset_flash, | ||
508 | .reset_bus = mv_reset_pci_bus, | ||
509 | }; | ||
510 | |||
374 | /* | 511 | /* |
375 | * Functions | 512 | * Functions |
376 | */ | 513 | */ |
@@ -386,11 +523,27 @@ static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc) | |||
386 | return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ)); | 523 | return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ)); |
387 | } | 524 | } |
388 | 525 | ||
526 | static inline unsigned int mv_hc_from_port(unsigned int port) | ||
527 | { | ||
528 | return port >> MV_PORT_HC_SHIFT; | ||
529 | } | ||
530 | |||
531 | static inline unsigned int mv_hardport_from_port(unsigned int port) | ||
532 | { | ||
533 | return port & MV_PORT_MASK; | ||
534 | } | ||
535 | |||
536 | static inline void __iomem *mv_hc_base_from_port(void __iomem *base, | ||
537 | unsigned int port) | ||
538 | { | ||
539 | return mv_hc_base(base, mv_hc_from_port(port)); | ||
540 | } | ||
541 | |||
389 | static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port) | 542 | static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port) |
390 | { | 543 | { |
391 | return (mv_hc_base(base, port >> MV_PORT_HC_SHIFT) + | 544 | return mv_hc_base_from_port(base, port) + |
392 | MV_SATAHC_ARBTR_REG_SZ + | 545 | MV_SATAHC_ARBTR_REG_SZ + |
393 | ((port & MV_PORT_MASK) * MV_PORT_REG_SZ)); | 546 | (mv_hardport_from_port(port) * MV_PORT_REG_SZ); |
394 | } | 547 | } |
395 | 548 | ||
396 | static inline void __iomem *mv_ap_base(struct ata_port *ap) | 549 | static inline void __iomem *mv_ap_base(struct ata_port *ap) |
@@ -398,9 +551,9 @@ static inline void __iomem *mv_ap_base(struct ata_port *ap) | |||
398 | return mv_port_base(ap->host_set->mmio_base, ap->port_no); | 551 | return mv_port_base(ap->host_set->mmio_base, ap->port_no); |
399 | } | 552 | } |
400 | 553 | ||
401 | static inline int mv_get_hc_count(unsigned long hp_flags) | 554 | static inline int mv_get_hc_count(unsigned long host_flags) |
402 | { | 555 | { |
403 | return ((hp_flags & MV_FLAG_DUAL_HC) ? 2 : 1); | 556 | return ((host_flags & MV_FLAG_DUAL_HC) ? 2 : 1); |
404 | } | 557 | } |
405 | 558 | ||
406 | static void mv_irq_clear(struct ata_port *ap) | 559 | static void mv_irq_clear(struct ata_port *ap) |
@@ -452,7 +605,7 @@ static void mv_stop_dma(struct ata_port *ap) | |||
452 | } else { | 605 | } else { |
453 | assert(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS))); | 606 | assert(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS))); |
454 | } | 607 | } |
455 | 608 | ||
456 | /* now properly wait for the eDMA to stop */ | 609 | /* now properly wait for the eDMA to stop */ |
457 | for (i = 1000; i > 0; i--) { | 610 | for (i = 1000; i > 0; i--) { |
458 | reg = readl(port_mmio + EDMA_CMD_OFS); | 611 | reg = readl(port_mmio + EDMA_CMD_OFS); |
@@ -503,7 +656,7 @@ static void mv_dump_all_regs(void __iomem *mmio_base, int port, | |||
503 | struct pci_dev *pdev) | 656 | struct pci_dev *pdev) |
504 | { | 657 | { |
505 | #ifdef ATA_DEBUG | 658 | #ifdef ATA_DEBUG |
506 | void __iomem *hc_base = mv_hc_base(mmio_base, | 659 | void __iomem *hc_base = mv_hc_base(mmio_base, |
507 | port >> MV_PORT_HC_SHIFT); | 660 | port >> MV_PORT_HC_SHIFT); |
508 | void __iomem *port_base; | 661 | void __iomem *port_base; |
509 | int start_port, num_ports, p, start_hc, num_hcs, hc; | 662 | int start_port, num_ports, p, start_hc, num_hcs, hc; |
@@ -517,7 +670,7 @@ static void mv_dump_all_regs(void __iomem *mmio_base, int port, | |||
517 | start_port = port; | 670 | start_port = port; |
518 | num_ports = num_hcs = 1; | 671 | num_ports = num_hcs = 1; |
519 | } | 672 | } |
520 | DPRINTK("All registers for port(s) %u-%u:\n", start_port, | 673 | DPRINTK("All registers for port(s) %u-%u:\n", start_port, |
521 | num_ports > 1 ? num_ports - 1 : start_port); | 674 | num_ports > 1 ? num_ports - 1 : start_port); |
522 | 675 | ||
523 | if (NULL != pdev) { | 676 | if (NULL != pdev) { |
@@ -585,70 +738,6 @@ static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) | |||
585 | } | 738 | } |
586 | 739 | ||
587 | /** | 740 | /** |
588 | * mv_global_soft_reset - Perform the 6xxx global soft reset | ||
589 | * @mmio_base: base address of the HBA | ||
590 | * | ||
591 | * This routine only applies to 6xxx parts. | ||
592 | * | ||
593 | * LOCKING: | ||
594 | * Inherited from caller. | ||
595 | */ | ||
596 | static int mv_global_soft_reset(void __iomem *mmio_base) | ||
597 | { | ||
598 | void __iomem *reg = mmio_base + PCI_MAIN_CMD_STS_OFS; | ||
599 | int i, rc = 0; | ||
600 | u32 t; | ||
601 | |||
602 | /* Following procedure defined in PCI "main command and status | ||
603 | * register" table. | ||
604 | */ | ||
605 | t = readl(reg); | ||
606 | writel(t | STOP_PCI_MASTER, reg); | ||
607 | |||
608 | for (i = 0; i < 1000; i++) { | ||
609 | udelay(1); | ||
610 | t = readl(reg); | ||
611 | if (PCI_MASTER_EMPTY & t) { | ||
612 | break; | ||
613 | } | ||
614 | } | ||
615 | if (!(PCI_MASTER_EMPTY & t)) { | ||
616 | printk(KERN_ERR DRV_NAME ": PCI master won't flush\n"); | ||
617 | rc = 1; | ||
618 | goto done; | ||
619 | } | ||
620 | |||
621 | /* set reset */ | ||
622 | i = 5; | ||
623 | do { | ||
624 | writel(t | GLOB_SFT_RST, reg); | ||
625 | t = readl(reg); | ||
626 | udelay(1); | ||
627 | } while (!(GLOB_SFT_RST & t) && (i-- > 0)); | ||
628 | |||
629 | if (!(GLOB_SFT_RST & t)) { | ||
630 | printk(KERN_ERR DRV_NAME ": can't set global reset\n"); | ||
631 | rc = 1; | ||
632 | goto done; | ||
633 | } | ||
634 | |||
635 | /* clear reset and *reenable the PCI master* (not mentioned in spec) */ | ||
636 | i = 5; | ||
637 | do { | ||
638 | writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg); | ||
639 | t = readl(reg); | ||
640 | udelay(1); | ||
641 | } while ((GLOB_SFT_RST & t) && (i-- > 0)); | ||
642 | |||
643 | if (GLOB_SFT_RST & t) { | ||
644 | printk(KERN_ERR DRV_NAME ": can't clear global reset\n"); | ||
645 | rc = 1; | ||
646 | } | ||
647 | done: | ||
648 | return rc; | ||
649 | } | ||
650 | |||
651 | /** | ||
652 | * mv_host_stop - Host specific cleanup/stop routine. | 741 | * mv_host_stop - Host specific cleanup/stop routine. |
653 | * @host_set: host data structure | 742 | * @host_set: host data structure |
654 | * | 743 | * |
@@ -701,7 +790,7 @@ static int mv_port_start(struct ata_port *ap) | |||
701 | goto err_out; | 790 | goto err_out; |
702 | memset(pp, 0, sizeof(*pp)); | 791 | memset(pp, 0, sizeof(*pp)); |
703 | 792 | ||
704 | mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, | 793 | mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, |
705 | GFP_KERNEL); | 794 | GFP_KERNEL); |
706 | if (!mem) | 795 | if (!mem) |
707 | goto err_out_pp; | 796 | goto err_out_pp; |
@@ -711,7 +800,7 @@ static int mv_port_start(struct ata_port *ap) | |||
711 | if (rc) | 800 | if (rc) |
712 | goto err_out_priv; | 801 | goto err_out_priv; |
713 | 802 | ||
714 | /* First item in chunk of DMA memory: | 803 | /* First item in chunk of DMA memory: |
715 | * 32-slot command request table (CRQB), 32 bytes each in size | 804 | * 32-slot command request table (CRQB), 32 bytes each in size |
716 | */ | 805 | */ |
717 | pp->crqb = mem; | 806 | pp->crqb = mem; |
@@ -719,7 +808,7 @@ static int mv_port_start(struct ata_port *ap) | |||
719 | mem += MV_CRQB_Q_SZ; | 808 | mem += MV_CRQB_Q_SZ; |
720 | mem_dma += MV_CRQB_Q_SZ; | 809 | mem_dma += MV_CRQB_Q_SZ; |
721 | 810 | ||
722 | /* Second item: | 811 | /* Second item: |
723 | * 32-slot command response table (CRPB), 8 bytes each in size | 812 | * 32-slot command response table (CRPB), 8 bytes each in size |
724 | */ | 813 | */ |
725 | pp->crpb = mem; | 814 | pp->crpb = mem; |
@@ -733,18 +822,18 @@ static int mv_port_start(struct ata_port *ap) | |||
733 | pp->sg_tbl = mem; | 822 | pp->sg_tbl = mem; |
734 | pp->sg_tbl_dma = mem_dma; | 823 | pp->sg_tbl_dma = mem_dma; |
735 | 824 | ||
736 | writelfl(EDMA_CFG_Q_DEPTH | EDMA_CFG_RD_BRST_EXT | | 825 | writelfl(EDMA_CFG_Q_DEPTH | EDMA_CFG_RD_BRST_EXT | |
737 | EDMA_CFG_WR_BUFF_LEN, port_mmio + EDMA_CFG_OFS); | 826 | EDMA_CFG_WR_BUFF_LEN, port_mmio + EDMA_CFG_OFS); |
738 | 827 | ||
739 | writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS); | 828 | writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS); |
740 | writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK, | 829 | writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK, |
741 | port_mmio + EDMA_REQ_Q_IN_PTR_OFS); | 830 | port_mmio + EDMA_REQ_Q_IN_PTR_OFS); |
742 | 831 | ||
743 | writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); | 832 | writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS); |
744 | writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); | 833 | writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS); |
745 | 834 | ||
746 | writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS); | 835 | writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS); |
747 | writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, | 836 | writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, |
748 | port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); | 837 | port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); |
749 | 838 | ||
750 | pp->req_producer = pp->rsp_consumer = 0; | 839 | pp->req_producer = pp->rsp_consumer = 0; |
@@ -805,20 +894,30 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) | |||
805 | struct scatterlist *sg; | 894 | struct scatterlist *sg; |
806 | 895 | ||
807 | ata_for_each_sg(sg, qc) { | 896 | ata_for_each_sg(sg, qc) { |
808 | u32 sg_len; | ||
809 | dma_addr_t addr; | 897 | dma_addr_t addr; |
898 | u32 sg_len, len, offset; | ||
810 | 899 | ||
811 | addr = sg_dma_address(sg); | 900 | addr = sg_dma_address(sg); |
812 | sg_len = sg_dma_len(sg); | 901 | sg_len = sg_dma_len(sg); |
813 | 902 | ||
814 | pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); | 903 | while (sg_len) { |
815 | pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); | 904 | offset = addr & MV_DMA_BOUNDARY; |
816 | assert(0 == (sg_len & ~MV_DMA_BOUNDARY)); | 905 | len = sg_len; |
817 | pp->sg_tbl[i].flags_size = cpu_to_le32(sg_len); | 906 | if ((offset + sg_len) > 0x10000) |
818 | if (ata_sg_is_last(sg, qc)) | 907 | len = 0x10000 - offset; |
819 | pp->sg_tbl[i].flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); | 908 | |
909 | pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); | ||
910 | pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); | ||
911 | pp->sg_tbl[i].flags_size = cpu_to_le32(len); | ||
912 | |||
913 | sg_len -= len; | ||
914 | addr += len; | ||
915 | |||
916 | if (!sg_len && ata_sg_is_last(sg, qc)) | ||
917 | pp->sg_tbl[i].flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); | ||
820 | 918 | ||
821 | i++; | 919 | i++; |
920 | } | ||
822 | } | 921 | } |
823 | } | 922 | } |
824 | 923 | ||
@@ -859,7 +958,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) | |||
859 | } | 958 | } |
860 | 959 | ||
861 | /* the req producer index should be the same as we remember it */ | 960 | /* the req producer index should be the same as we remember it */ |
862 | assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> | 961 | assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> |
863 | EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == | 962 | EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == |
864 | pp->req_producer); | 963 | pp->req_producer); |
865 | 964 | ||
@@ -871,9 +970,9 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) | |||
871 | assert(MV_MAX_Q_DEPTH > qc->tag); | 970 | assert(MV_MAX_Q_DEPTH > qc->tag); |
872 | flags |= qc->tag << CRQB_TAG_SHIFT; | 971 | flags |= qc->tag << CRQB_TAG_SHIFT; |
873 | 972 | ||
874 | pp->crqb[pp->req_producer].sg_addr = | 973 | pp->crqb[pp->req_producer].sg_addr = |
875 | cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); | 974 | cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); |
876 | pp->crqb[pp->req_producer].sg_addr_hi = | 975 | pp->crqb[pp->req_producer].sg_addr_hi = |
877 | cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); | 976 | cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); |
878 | pp->crqb[pp->req_producer].ctrl_flags = cpu_to_le16(flags); | 977 | pp->crqb[pp->req_producer].ctrl_flags = cpu_to_le16(flags); |
879 | 978 | ||
@@ -896,7 +995,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) | |||
896 | #ifdef LIBATA_NCQ /* FIXME: remove this line when NCQ added */ | 995 | #ifdef LIBATA_NCQ /* FIXME: remove this line when NCQ added */ |
897 | case ATA_CMD_FPDMA_READ: | 996 | case ATA_CMD_FPDMA_READ: |
898 | case ATA_CMD_FPDMA_WRITE: | 997 | case ATA_CMD_FPDMA_WRITE: |
899 | mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0); | 998 | mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0); |
900 | mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0); | 999 | mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0); |
901 | break; | 1000 | break; |
902 | #endif /* FIXME: remove this line when NCQ added */ | 1001 | #endif /* FIXME: remove this line when NCQ added */ |
@@ -962,7 +1061,7 @@ static int mv_qc_issue(struct ata_queued_cmd *qc) | |||
962 | pp->req_producer); | 1061 | pp->req_producer); |
963 | /* until we do queuing, the queue should be empty at this point */ | 1062 | /* until we do queuing, the queue should be empty at this point */ |
964 | assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == | 1063 | assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == |
965 | ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >> | 1064 | ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >> |
966 | EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); | 1065 | EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); |
967 | 1066 | ||
968 | mv_inc_q_index(&pp->req_producer); /* now incr producer index */ | 1067 | mv_inc_q_index(&pp->req_producer); /* now incr producer index */ |
@@ -999,15 +1098,15 @@ static u8 mv_get_crpb_status(struct ata_port *ap) | |||
999 | out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); | 1098 | out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); |
1000 | 1099 | ||
1001 | /* the response consumer index should be the same as we remember it */ | 1100 | /* the response consumer index should be the same as we remember it */ |
1002 | assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == | 1101 | assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == |
1003 | pp->rsp_consumer); | 1102 | pp->rsp_consumer); |
1004 | 1103 | ||
1005 | /* increment our consumer index... */ | 1104 | /* increment our consumer index... */ |
1006 | pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer); | 1105 | pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer); |
1007 | 1106 | ||
1008 | /* and, until we do NCQ, there should only be 1 CRPB waiting */ | 1107 | /* and, until we do NCQ, there should only be 1 CRPB waiting */ |
1009 | assert(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >> | 1108 | assert(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >> |
1010 | EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == | 1109 | EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == |
1011 | pp->rsp_consumer); | 1110 | pp->rsp_consumer); |
1012 | 1111 | ||
1013 | /* write out our inc'd consumer index so EDMA knows we're caught up */ | 1112 | /* write out our inc'd consumer index so EDMA knows we're caught up */ |
@@ -1055,7 +1154,7 @@ static void mv_err_intr(struct ata_port *ap) | |||
1055 | 1154 | ||
1056 | /* check for fatal here and recover if needed */ | 1155 | /* check for fatal here and recover if needed */ |
1057 | if (EDMA_ERR_FATAL & edma_err_cause) { | 1156 | if (EDMA_ERR_FATAL & edma_err_cause) { |
1058 | mv_phy_reset(ap); | 1157 | mv_stop_and_reset(ap); |
1059 | } | 1158 | } |
1060 | } | 1159 | } |
1061 | 1160 | ||
@@ -1120,6 +1219,10 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, | |||
1120 | handled++; | 1219 | handled++; |
1121 | } | 1220 | } |
1122 | 1221 | ||
1222 | if (ap && | ||
1223 | (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) | ||
1224 | continue; | ||
1225 | |||
1123 | err_mask = ac_err_mask(ata_status); | 1226 | err_mask = ac_err_mask(ata_status); |
1124 | 1227 | ||
1125 | shift = port << 1; /* (port * 2) */ | 1228 | shift = port << 1; /* (port * 2) */ |
@@ -1131,14 +1234,15 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, | |||
1131 | err_mask |= AC_ERR_OTHER; | 1234 | err_mask |= AC_ERR_OTHER; |
1132 | handled++; | 1235 | handled++; |
1133 | } | 1236 | } |
1134 | 1237 | ||
1135 | if (handled && ap) { | 1238 | if (handled && ap) { |
1136 | qc = ata_qc_from_tag(ap, ap->active_tag); | 1239 | qc = ata_qc_from_tag(ap, ap->active_tag); |
1137 | if (NULL != qc) { | 1240 | if (NULL != qc) { |
1138 | VPRINTK("port %u IRQ found for qc, " | 1241 | VPRINTK("port %u IRQ found for qc, " |
1139 | "ata_status 0x%x\n", port,ata_status); | 1242 | "ata_status 0x%x\n", port,ata_status); |
1140 | /* mark qc status appropriately */ | 1243 | /* mark qc status appropriately */ |
1141 | ata_qc_complete(qc, err_mask); | 1244 | if (!(qc->tf.ctl & ATA_NIEN)) |
1245 | ata_qc_complete(qc, err_mask); | ||
1142 | } | 1246 | } |
1143 | } | 1247 | } |
1144 | } | 1248 | } |
@@ -1146,7 +1250,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, | |||
1146 | } | 1250 | } |
1147 | 1251 | ||
1148 | /** | 1252 | /** |
1149 | * mv_interrupt - | 1253 | * mv_interrupt - |
1150 | * @irq: unused | 1254 | * @irq: unused |
1151 | * @dev_instance: private data; in this case the host structure | 1255 | * @dev_instance: private data; in this case the host structure |
1152 | * @regs: unused | 1256 | * @regs: unused |
@@ -1156,7 +1260,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, | |||
1156 | * routine to handle. Also check for PCI errors which are only | 1260 | * routine to handle. Also check for PCI errors which are only |
1157 | * reported here. | 1261 | * reported here. |
1158 | * | 1262 | * |
1159 | * LOCKING: | 1263 | * LOCKING: |
1160 | * This routine holds the host_set lock while processing pending | 1264 | * This routine holds the host_set lock while processing pending |
1161 | * interrupts. | 1265 | * interrupts. |
1162 | */ | 1266 | */ |
@@ -1202,8 +1306,422 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, | |||
1202 | return IRQ_RETVAL(handled); | 1306 | return IRQ_RETVAL(handled); |
1203 | } | 1307 | } |
1204 | 1308 | ||
1309 | static void __iomem *mv5_phy_base(void __iomem *mmio, unsigned int port) | ||
1310 | { | ||
1311 | void __iomem *hc_mmio = mv_hc_base_from_port(mmio, port); | ||
1312 | unsigned long ofs = (mv_hardport_from_port(port) + 1) * 0x100UL; | ||
1313 | |||
1314 | return hc_mmio + ofs; | ||
1315 | } | ||
1316 | |||
1317 | static unsigned int mv5_scr_offset(unsigned int sc_reg_in) | ||
1318 | { | ||
1319 | unsigned int ofs; | ||
1320 | |||
1321 | switch (sc_reg_in) { | ||
1322 | case SCR_STATUS: | ||
1323 | case SCR_ERROR: | ||
1324 | case SCR_CONTROL: | ||
1325 | ofs = sc_reg_in * sizeof(u32); | ||
1326 | break; | ||
1327 | default: | ||
1328 | ofs = 0xffffffffU; | ||
1329 | break; | ||
1330 | } | ||
1331 | return ofs; | ||
1332 | } | ||
1333 | |||
1334 | static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in) | ||
1335 | { | ||
1336 | void __iomem *mmio = mv5_phy_base(ap->host_set->mmio_base, ap->port_no); | ||
1337 | unsigned int ofs = mv5_scr_offset(sc_reg_in); | ||
1338 | |||
1339 | if (ofs != 0xffffffffU) | ||
1340 | return readl(mmio + ofs); | ||
1341 | else | ||
1342 | return (u32) ofs; | ||
1343 | } | ||
1344 | |||
1345 | static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) | ||
1346 | { | ||
1347 | void __iomem *mmio = mv5_phy_base(ap->host_set->mmio_base, ap->port_no); | ||
1348 | unsigned int ofs = mv5_scr_offset(sc_reg_in); | ||
1349 | |||
1350 | if (ofs != 0xffffffffU) | ||
1351 | writelfl(val, mmio + ofs); | ||
1352 | } | ||
1353 | |||
1354 | static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio) | ||
1355 | { | ||
1356 | u8 rev_id; | ||
1357 | int early_5080; | ||
1358 | |||
1359 | pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); | ||
1360 | |||
1361 | early_5080 = (pdev->device == 0x5080) && (rev_id == 0); | ||
1362 | |||
1363 | if (!early_5080) { | ||
1364 | u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); | ||
1365 | tmp |= (1 << 0); | ||
1366 | writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); | ||
1367 | } | ||
1368 | |||
1369 | mv_reset_pci_bus(pdev, mmio); | ||
1370 | } | ||
1371 | |||
1372 | static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) | ||
1373 | { | ||
1374 | writel(0x0fcfffff, mmio + MV_FLASH_CTL); | ||
1375 | } | ||
1376 | |||
1377 | static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, | ||
1378 | void __iomem *mmio) | ||
1379 | { | ||
1380 | void __iomem *phy_mmio = mv5_phy_base(mmio, idx); | ||
1381 | u32 tmp; | ||
1382 | |||
1383 | tmp = readl(phy_mmio + MV5_PHY_MODE); | ||
1384 | |||
1385 | hpriv->signal[idx].pre = tmp & 0x1800; /* bits 12:11 */ | ||
1386 | hpriv->signal[idx].amps = tmp & 0xe0; /* bits 7:5 */ | ||
1387 | } | ||
1388 | |||
1389 | static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) | ||
1390 | { | ||
1391 | u32 tmp; | ||
1392 | |||
1393 | writel(0, mmio + MV_GPIO_PORT_CTL); | ||
1394 | |||
1395 | /* FIXME: handle MV_HP_ERRATA_50XXB2 errata */ | ||
1396 | |||
1397 | tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); | ||
1398 | tmp |= ~(1 << 0); | ||
1399 | writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); | ||
1400 | } | ||
1401 | |||
1402 | static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
1403 | unsigned int port) | ||
1404 | { | ||
1405 | void __iomem *phy_mmio = mv5_phy_base(mmio, port); | ||
1406 | const u32 mask = (1<<12) | (1<<11) | (1<<7) | (1<<6) | (1<<5); | ||
1407 | u32 tmp; | ||
1408 | int fix_apm_sq = (hpriv->hp_flags & MV_HP_ERRATA_50XXB0); | ||
1409 | |||
1410 | if (fix_apm_sq) { | ||
1411 | tmp = readl(phy_mmio + MV5_LT_MODE); | ||
1412 | tmp |= (1 << 19); | ||
1413 | writel(tmp, phy_mmio + MV5_LT_MODE); | ||
1414 | |||
1415 | tmp = readl(phy_mmio + MV5_PHY_CTL); | ||
1416 | tmp &= ~0x3; | ||
1417 | tmp |= 0x1; | ||
1418 | writel(tmp, phy_mmio + MV5_PHY_CTL); | ||
1419 | } | ||
1420 | |||
1421 | tmp = readl(phy_mmio + MV5_PHY_MODE); | ||
1422 | tmp &= ~mask; | ||
1423 | tmp |= hpriv->signal[port].pre; | ||
1424 | tmp |= hpriv->signal[port].amps; | ||
1425 | writel(tmp, phy_mmio + MV5_PHY_MODE); | ||
1426 | } | ||
1427 | |||
1428 | |||
1429 | #undef ZERO | ||
1430 | #define ZERO(reg) writel(0, port_mmio + (reg)) | ||
1431 | static void mv5_reset_hc_port(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
1432 | unsigned int port) | ||
1433 | { | ||
1434 | void __iomem *port_mmio = mv_port_base(mmio, port); | ||
1435 | |||
1436 | writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); | ||
1437 | |||
1438 | mv_channel_reset(hpriv, mmio, port); | ||
1439 | |||
1440 | ZERO(0x028); /* command */ | ||
1441 | writel(0x11f, port_mmio + EDMA_CFG_OFS); | ||
1442 | ZERO(0x004); /* timer */ | ||
1443 | ZERO(0x008); /* irq err cause */ | ||
1444 | ZERO(0x00c); /* irq err mask */ | ||
1445 | ZERO(0x010); /* rq bah */ | ||
1446 | ZERO(0x014); /* rq inp */ | ||
1447 | ZERO(0x018); /* rq outp */ | ||
1448 | ZERO(0x01c); /* respq bah */ | ||
1449 | ZERO(0x024); /* respq outp */ | ||
1450 | ZERO(0x020); /* respq inp */ | ||
1451 | ZERO(0x02c); /* test control */ | ||
1452 | writel(0xbc, port_mmio + EDMA_IORDY_TMOUT); | ||
1453 | } | ||
1454 | #undef ZERO | ||
1455 | |||
1456 | #define ZERO(reg) writel(0, hc_mmio + (reg)) | ||
1457 | static void mv5_reset_one_hc(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
1458 | unsigned int hc) | ||
1459 | { | ||
1460 | void __iomem *hc_mmio = mv_hc_base(mmio, hc); | ||
1461 | u32 tmp; | ||
1462 | |||
1463 | ZERO(0x00c); | ||
1464 | ZERO(0x010); | ||
1465 | ZERO(0x014); | ||
1466 | ZERO(0x018); | ||
1467 | |||
1468 | tmp = readl(hc_mmio + 0x20); | ||
1469 | tmp &= 0x1c1c1c1c; | ||
1470 | tmp |= 0x03030303; | ||
1471 | writel(tmp, hc_mmio + 0x20); | ||
1472 | } | ||
1473 | #undef ZERO | ||
1474 | |||
1475 | static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
1476 | unsigned int n_hc) | ||
1477 | { | ||
1478 | unsigned int hc, port; | ||
1479 | |||
1480 | for (hc = 0; hc < n_hc; hc++) { | ||
1481 | for (port = 0; port < MV_PORTS_PER_HC; port++) | ||
1482 | mv5_reset_hc_port(hpriv, mmio, | ||
1483 | (hc * MV_PORTS_PER_HC) + port); | ||
1484 | |||
1485 | mv5_reset_one_hc(hpriv, mmio, hc); | ||
1486 | } | ||
1487 | |||
1488 | return 0; | ||
1489 | } | ||
1490 | |||
1491 | #undef ZERO | ||
1492 | #define ZERO(reg) writel(0, mmio + (reg)) | ||
1493 | static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio) | ||
1494 | { | ||
1495 | u32 tmp; | ||
1496 | |||
1497 | tmp = readl(mmio + MV_PCI_MODE); | ||
1498 | tmp &= 0xff00ffff; | ||
1499 | writel(tmp, mmio + MV_PCI_MODE); | ||
1500 | |||
1501 | ZERO(MV_PCI_DISC_TIMER); | ||
1502 | ZERO(MV_PCI_MSI_TRIGGER); | ||
1503 | writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT); | ||
1504 | ZERO(HC_MAIN_IRQ_MASK_OFS); | ||
1505 | ZERO(MV_PCI_SERR_MASK); | ||
1506 | ZERO(PCI_IRQ_CAUSE_OFS); | ||
1507 | ZERO(PCI_IRQ_MASK_OFS); | ||
1508 | ZERO(MV_PCI_ERR_LOW_ADDRESS); | ||
1509 | ZERO(MV_PCI_ERR_HIGH_ADDRESS); | ||
1510 | ZERO(MV_PCI_ERR_ATTRIBUTE); | ||
1511 | ZERO(MV_PCI_ERR_COMMAND); | ||
1512 | } | ||
1513 | #undef ZERO | ||
1514 | |||
1515 | static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) | ||
1516 | { | ||
1517 | u32 tmp; | ||
1518 | |||
1519 | mv5_reset_flash(hpriv, mmio); | ||
1520 | |||
1521 | tmp = readl(mmio + MV_GPIO_PORT_CTL); | ||
1522 | tmp &= 0x3; | ||
1523 | tmp |= (1 << 5) | (1 << 6); | ||
1524 | writel(tmp, mmio + MV_GPIO_PORT_CTL); | ||
1525 | } | ||
1526 | |||
1527 | /** | ||
1528 | * mv6_reset_hc - Perform the 6xxx global soft reset | ||
1529 | * @mmio: base address of the HBA | ||
1530 | * | ||
1531 | * This routine only applies to 6xxx parts. | ||
1532 | * | ||
1533 | * LOCKING: | ||
1534 | * Inherited from caller. | ||
1535 | */ | ||
1536 | static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
1537 | unsigned int n_hc) | ||
1538 | { | ||
1539 | void __iomem *reg = mmio + PCI_MAIN_CMD_STS_OFS; | ||
1540 | int i, rc = 0; | ||
1541 | u32 t; | ||
1542 | |||
1543 | /* Following procedure defined in PCI "main command and status | ||
1544 | * register" table. | ||
1545 | */ | ||
1546 | t = readl(reg); | ||
1547 | writel(t | STOP_PCI_MASTER, reg); | ||
1548 | |||
1549 | for (i = 0; i < 1000; i++) { | ||
1550 | udelay(1); | ||
1551 | t = readl(reg); | ||
1552 | if (PCI_MASTER_EMPTY & t) { | ||
1553 | break; | ||
1554 | } | ||
1555 | } | ||
1556 | if (!(PCI_MASTER_EMPTY & t)) { | ||
1557 | printk(KERN_ERR DRV_NAME ": PCI master won't flush\n"); | ||
1558 | rc = 1; | ||
1559 | goto done; | ||
1560 | } | ||
1561 | |||
1562 | /* set reset */ | ||
1563 | i = 5; | ||
1564 | do { | ||
1565 | writel(t | GLOB_SFT_RST, reg); | ||
1566 | t = readl(reg); | ||
1567 | udelay(1); | ||
1568 | } while (!(GLOB_SFT_RST & t) && (i-- > 0)); | ||
1569 | |||
1570 | if (!(GLOB_SFT_RST & t)) { | ||
1571 | printk(KERN_ERR DRV_NAME ": can't set global reset\n"); | ||
1572 | rc = 1; | ||
1573 | goto done; | ||
1574 | } | ||
1575 | |||
1576 | /* clear reset and *reenable the PCI master* (not mentioned in spec) */ | ||
1577 | i = 5; | ||
1578 | do { | ||
1579 | writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg); | ||
1580 | t = readl(reg); | ||
1581 | udelay(1); | ||
1582 | } while ((GLOB_SFT_RST & t) && (i-- > 0)); | ||
1583 | |||
1584 | if (GLOB_SFT_RST & t) { | ||
1585 | printk(KERN_ERR DRV_NAME ": can't clear global reset\n"); | ||
1586 | rc = 1; | ||
1587 | } | ||
1588 | done: | ||
1589 | return rc; | ||
1590 | } | ||
1591 | |||
1592 | static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, | ||
1593 | void __iomem *mmio) | ||
1594 | { | ||
1595 | void __iomem *port_mmio; | ||
1596 | u32 tmp; | ||
1597 | |||
1598 | tmp = readl(mmio + MV_RESET_CFG); | ||
1599 | if ((tmp & (1 << 0)) == 0) { | ||
1600 | hpriv->signal[idx].amps = 0x7 << 8; | ||
1601 | hpriv->signal[idx].pre = 0x1 << 5; | ||
1602 | return; | ||
1603 | } | ||
1604 | |||
1605 | port_mmio = mv_port_base(mmio, idx); | ||
1606 | tmp = readl(port_mmio + PHY_MODE2); | ||
1607 | |||
1608 | hpriv->signal[idx].amps = tmp & 0x700; /* bits 10:8 */ | ||
1609 | hpriv->signal[idx].pre = tmp & 0xe0; /* bits 7:5 */ | ||
1610 | } | ||
1611 | |||
1612 | static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) | ||
1613 | { | ||
1614 | writel(0x00000060, mmio + MV_GPIO_PORT_CTL); | ||
1615 | } | ||
1616 | |||
1617 | static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
1618 | unsigned int port) | ||
1619 | { | ||
1620 | void __iomem *port_mmio = mv_port_base(mmio, port); | ||
1621 | |||
1622 | u32 hp_flags = hpriv->hp_flags; | ||
1623 | int fix_phy_mode2 = | ||
1624 | hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); | ||
1625 | int fix_phy_mode4 = | ||
1626 | hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0); | ||
1627 | u32 m2, tmp; | ||
1628 | |||
1629 | if (fix_phy_mode2) { | ||
1630 | m2 = readl(port_mmio + PHY_MODE2); | ||
1631 | m2 &= ~(1 << 16); | ||
1632 | m2 |= (1 << 31); | ||
1633 | writel(m2, port_mmio + PHY_MODE2); | ||
1634 | |||
1635 | udelay(200); | ||
1636 | |||
1637 | m2 = readl(port_mmio + PHY_MODE2); | ||
1638 | m2 &= ~((1 << 16) | (1 << 31)); | ||
1639 | writel(m2, port_mmio + PHY_MODE2); | ||
1640 | |||
1641 | udelay(200); | ||
1642 | } | ||
1643 | |||
1644 | /* who knows what this magic does */ | ||
1645 | tmp = readl(port_mmio + PHY_MODE3); | ||
1646 | tmp &= ~0x7F800000; | ||
1647 | tmp |= 0x2A800000; | ||
1648 | writel(tmp, port_mmio + PHY_MODE3); | ||
1649 | |||
1650 | if (fix_phy_mode4) { | ||
1651 | u32 m4; | ||
1652 | |||
1653 | m4 = readl(port_mmio + PHY_MODE4); | ||
1654 | |||
1655 | if (hp_flags & MV_HP_ERRATA_60X1B2) | ||
1656 | tmp = readl(port_mmio + 0x310); | ||
1657 | |||
1658 | m4 = (m4 & ~(1 << 1)) | (1 << 0); | ||
1659 | |||
1660 | writel(m4, port_mmio + PHY_MODE4); | ||
1661 | |||
1662 | if (hp_flags & MV_HP_ERRATA_60X1B2) | ||
1663 | writel(tmp, port_mmio + 0x310); | ||
1664 | } | ||
1665 | |||
1666 | /* Revert values of pre-emphasis and signal amps to the saved ones */ | ||
1667 | m2 = readl(port_mmio + PHY_MODE2); | ||
1668 | |||
1669 | m2 &= ~MV_M2_PREAMP_MASK; | ||
1670 | m2 |= hpriv->signal[port].amps; | ||
1671 | m2 |= hpriv->signal[port].pre; | ||
1672 | m2 &= ~(1 << 16); | ||
1673 | |||
1674 | writel(m2, port_mmio + PHY_MODE2); | ||
1675 | } | ||
1676 | |||
1677 | static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, | ||
1678 | unsigned int port_no) | ||
1679 | { | ||
1680 | void __iomem *port_mmio = mv_port_base(mmio, port_no); | ||
1681 | |||
1682 | writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS); | ||
1683 | |||
1684 | if (IS_60XX(hpriv)) { | ||
1685 | u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); | ||
1686 | ifctl |= (1 << 12) | (1 << 7); | ||
1687 | writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); | ||
1688 | } | ||
1689 | |||
1690 | udelay(25); /* allow reset propagation */ | ||
1691 | |||
1692 | /* Spec never mentions clearing the bit. Marvell's driver does | ||
1693 | * clear the bit, however. | ||
1694 | */ | ||
1695 | writelfl(0, port_mmio + EDMA_CMD_OFS); | ||
1696 | |||
1697 | hpriv->ops->phy_errata(hpriv, mmio, port_no); | ||
1698 | |||
1699 | if (IS_50XX(hpriv)) | ||
1700 | mdelay(1); | ||
1701 | } | ||
1702 | |||
1703 | static void mv_stop_and_reset(struct ata_port *ap) | ||
1704 | { | ||
1705 | struct mv_host_priv *hpriv = ap->host_set->private_data; | ||
1706 | void __iomem *mmio = ap->host_set->mmio_base; | ||
1707 | |||
1708 | mv_stop_dma(ap); | ||
1709 | |||
1710 | mv_channel_reset(hpriv, mmio, ap->port_no); | ||
1711 | |||
1712 | __mv_phy_reset(ap, 0); | ||
1713 | } | ||
1714 | |||
1715 | static inline void __msleep(unsigned int msec, int can_sleep) | ||
1716 | { | ||
1717 | if (can_sleep) | ||
1718 | msleep(msec); | ||
1719 | else | ||
1720 | mdelay(msec); | ||
1721 | } | ||
1722 | |||
1205 | /** | 1723 | /** |
1206 | * mv_phy_reset - Perform eDMA reset followed by COMRESET | 1724 | * __mv_phy_reset - Perform eDMA reset followed by COMRESET |
1207 | * @ap: ATA channel to manipulate | 1725 | * @ap: ATA channel to manipulate |
1208 | * | 1726 | * |
1209 | * Part of this is taken from __sata_phy_reset and modified to | 1727 | * Part of this is taken from __sata_phy_reset and modified to |
@@ -1213,41 +1731,47 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, | |||
1213 | * Inherited from caller. This is coded to safe to call at | 1731 | * Inherited from caller. This is coded to safe to call at |
1214 | * interrupt level, i.e. it does not sleep. | 1732 | * interrupt level, i.e. it does not sleep. |
1215 | */ | 1733 | */ |
1216 | static void mv_phy_reset(struct ata_port *ap) | 1734 | static void __mv_phy_reset(struct ata_port *ap, int can_sleep) |
1217 | { | 1735 | { |
1736 | struct mv_port_priv *pp = ap->private_data; | ||
1737 | struct mv_host_priv *hpriv = ap->host_set->private_data; | ||
1218 | void __iomem *port_mmio = mv_ap_base(ap); | 1738 | void __iomem *port_mmio = mv_ap_base(ap); |
1219 | struct ata_taskfile tf; | 1739 | struct ata_taskfile tf; |
1220 | struct ata_device *dev = &ap->device[0]; | 1740 | struct ata_device *dev = &ap->device[0]; |
1221 | unsigned long timeout; | 1741 | unsigned long timeout; |
1742 | int retry = 5; | ||
1743 | u32 sstatus; | ||
1222 | 1744 | ||
1223 | VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio); | 1745 | VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio); |
1224 | 1746 | ||
1225 | mv_stop_dma(ap); | 1747 | DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x " |
1226 | |||
1227 | writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS); | ||
1228 | udelay(25); /* allow reset propagation */ | ||
1229 | |||
1230 | /* Spec never mentions clearing the bit. Marvell's driver does | ||
1231 | * clear the bit, however. | ||
1232 | */ | ||
1233 | writelfl(0, port_mmio + EDMA_CMD_OFS); | ||
1234 | |||
1235 | VPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x " | ||
1236 | "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), | 1748 | "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), |
1237 | mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); | 1749 | mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); |
1238 | 1750 | ||
1239 | /* proceed to init communications via the scr_control reg */ | 1751 | /* Issue COMRESET via SControl */ |
1752 | comreset_retry: | ||
1240 | scr_write_flush(ap, SCR_CONTROL, 0x301); | 1753 | scr_write_flush(ap, SCR_CONTROL, 0x301); |
1241 | mdelay(1); | 1754 | __msleep(1, can_sleep); |
1755 | |||
1242 | scr_write_flush(ap, SCR_CONTROL, 0x300); | 1756 | scr_write_flush(ap, SCR_CONTROL, 0x300); |
1243 | timeout = jiffies + (HZ * 1); | 1757 | __msleep(20, can_sleep); |
1758 | |||
1759 | timeout = jiffies + msecs_to_jiffies(200); | ||
1244 | do { | 1760 | do { |
1245 | mdelay(10); | 1761 | sstatus = scr_read(ap, SCR_STATUS) & 0x3; |
1246 | if ((scr_read(ap, SCR_STATUS) & 0xf) != 1) | 1762 | if ((sstatus == 3) || (sstatus == 0)) |
1247 | break; | 1763 | break; |
1764 | |||
1765 | __msleep(1, can_sleep); | ||
1248 | } while (time_before(jiffies, timeout)); | 1766 | } while (time_before(jiffies, timeout)); |
1249 | 1767 | ||
1250 | VPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x " | 1768 | /* work around errata */ |
1769 | if (IS_60XX(hpriv) && | ||
1770 | (sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) && | ||
1771 | (retry-- > 0)) | ||
1772 | goto comreset_retry; | ||
1773 | |||
1774 | DPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x " | ||
1251 | "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), | 1775 | "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), |
1252 | mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); | 1776 | mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); |
1253 | 1777 | ||
@@ -1261,6 +1785,21 @@ static void mv_phy_reset(struct ata_port *ap) | |||
1261 | } | 1785 | } |
1262 | ap->cbl = ATA_CBL_SATA; | 1786 | ap->cbl = ATA_CBL_SATA; |
1263 | 1787 | ||
1788 | /* even after SStatus reflects that device is ready, | ||
1789 | * it seems to take a while for link to be fully | ||
1790 | * established (and thus Status no longer 0x80/0x7F), | ||
1791 | * so we poll a bit for that, here. | ||
1792 | */ | ||
1793 | retry = 20; | ||
1794 | while (1) { | ||
1795 | u8 drv_stat = ata_check_status(ap); | ||
1796 | if ((drv_stat != 0x80) && (drv_stat != 0x7f)) | ||
1797 | break; | ||
1798 | __msleep(500, can_sleep); | ||
1799 | if (retry-- <= 0) | ||
1800 | break; | ||
1801 | } | ||
1802 | |||
1264 | tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr); | 1803 | tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr); |
1265 | tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr); | 1804 | tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr); |
1266 | tf.lbal = readb((void __iomem *) ap->ioaddr.lbal_addr); | 1805 | tf.lbal = readb((void __iomem *) ap->ioaddr.lbal_addr); |
@@ -1271,9 +1810,19 @@ static void mv_phy_reset(struct ata_port *ap) | |||
1271 | VPRINTK("Port disabled post-sig: No device present.\n"); | 1810 | VPRINTK("Port disabled post-sig: No device present.\n"); |
1272 | ata_port_disable(ap); | 1811 | ata_port_disable(ap); |
1273 | } | 1812 | } |
1813 | |||
1814 | writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); | ||
1815 | |||
1816 | pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; | ||
1817 | |||
1274 | VPRINTK("EXIT\n"); | 1818 | VPRINTK("EXIT\n"); |
1275 | } | 1819 | } |
1276 | 1820 | ||
1821 | static void mv_phy_reset(struct ata_port *ap) | ||
1822 | { | ||
1823 | __mv_phy_reset(ap, 1); | ||
1824 | } | ||
1825 | |||
1277 | /** | 1826 | /** |
1278 | * mv_eng_timeout - Routine called by libata when SCSI times out I/O | 1827 | * mv_eng_timeout - Routine called by libata when SCSI times out I/O |
1279 | * @ap: ATA channel to manipulate | 1828 | * @ap: ATA channel to manipulate |
@@ -1291,16 +1840,16 @@ static void mv_eng_timeout(struct ata_port *ap) | |||
1291 | 1840 | ||
1292 | printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id); | 1841 | printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id); |
1293 | DPRINTK("All regs @ start of eng_timeout\n"); | 1842 | DPRINTK("All regs @ start of eng_timeout\n"); |
1294 | mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no, | 1843 | mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no, |
1295 | to_pci_dev(ap->host_set->dev)); | 1844 | to_pci_dev(ap->host_set->dev)); |
1296 | 1845 | ||
1297 | qc = ata_qc_from_tag(ap, ap->active_tag); | 1846 | qc = ata_qc_from_tag(ap, ap->active_tag); |
1298 | printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n", | 1847 | printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n", |
1299 | ap->host_set->mmio_base, ap, qc, qc->scsicmd, | 1848 | ap->host_set->mmio_base, ap, qc, qc->scsicmd, |
1300 | &qc->scsicmd->cmnd); | 1849 | &qc->scsicmd->cmnd); |
1301 | 1850 | ||
1302 | mv_err_intr(ap); | 1851 | mv_err_intr(ap); |
1303 | mv_phy_reset(ap); | 1852 | mv_stop_and_reset(ap); |
1304 | 1853 | ||
1305 | if (!qc) { | 1854 | if (!qc) { |
1306 | printk(KERN_ERR "ata%u: BUG: timeout without command\n", | 1855 | printk(KERN_ERR "ata%u: BUG: timeout without command\n", |
@@ -1336,17 +1885,17 @@ static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio) | |||
1336 | unsigned long shd_base = (unsigned long) port_mmio + SHD_BLK_OFS; | 1885 | unsigned long shd_base = (unsigned long) port_mmio + SHD_BLK_OFS; |
1337 | unsigned serr_ofs; | 1886 | unsigned serr_ofs; |
1338 | 1887 | ||
1339 | /* PIO related setup | 1888 | /* PIO related setup |
1340 | */ | 1889 | */ |
1341 | port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA); | 1890 | port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA); |
1342 | port->error_addr = | 1891 | port->error_addr = |
1343 | port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR); | 1892 | port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR); |
1344 | port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT); | 1893 | port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT); |
1345 | port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL); | 1894 | port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL); |
1346 | port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM); | 1895 | port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM); |
1347 | port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH); | 1896 | port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH); |
1348 | port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE); | 1897 | port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE); |
1349 | port->status_addr = | 1898 | port->status_addr = |
1350 | port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS); | 1899 | port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS); |
1351 | /* special case: control/altstatus doesn't have ATA_REG_ address */ | 1900 | /* special case: control/altstatus doesn't have ATA_REG_ address */ |
1352 | port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS; | 1901 | port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS; |
@@ -1362,14 +1911,92 @@ static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio) | |||
1362 | /* unmask all EDMA error interrupts */ | 1911 | /* unmask all EDMA error interrupts */ |
1363 | writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS); | 1912 | writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS); |
1364 | 1913 | ||
1365 | VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n", | 1914 | VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n", |
1366 | readl(port_mmio + EDMA_CFG_OFS), | 1915 | readl(port_mmio + EDMA_CFG_OFS), |
1367 | readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS), | 1916 | readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS), |
1368 | readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS)); | 1917 | readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS)); |
1369 | } | 1918 | } |
1370 | 1919 | ||
1920 | static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv, | ||
1921 | unsigned int board_idx) | ||
1922 | { | ||
1923 | u8 rev_id; | ||
1924 | u32 hp_flags = hpriv->hp_flags; | ||
1925 | |||
1926 | pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); | ||
1927 | |||
1928 | switch(board_idx) { | ||
1929 | case chip_5080: | ||
1930 | hpriv->ops = &mv5xxx_ops; | ||
1931 | hp_flags |= MV_HP_50XX; | ||
1932 | |||
1933 | switch (rev_id) { | ||
1934 | case 0x1: | ||
1935 | hp_flags |= MV_HP_ERRATA_50XXB0; | ||
1936 | break; | ||
1937 | case 0x3: | ||
1938 | hp_flags |= MV_HP_ERRATA_50XXB2; | ||
1939 | break; | ||
1940 | default: | ||
1941 | dev_printk(KERN_WARNING, &pdev->dev, | ||
1942 | "Applying 50XXB2 workarounds to unknown rev\n"); | ||
1943 | hp_flags |= MV_HP_ERRATA_50XXB2; | ||
1944 | break; | ||
1945 | } | ||
1946 | break; | ||
1947 | |||
1948 | case chip_504x: | ||
1949 | case chip_508x: | ||
1950 | hpriv->ops = &mv5xxx_ops; | ||
1951 | hp_flags |= MV_HP_50XX; | ||
1952 | |||
1953 | switch (rev_id) { | ||
1954 | case 0x0: | ||
1955 | hp_flags |= MV_HP_ERRATA_50XXB0; | ||
1956 | break; | ||
1957 | case 0x3: | ||
1958 | hp_flags |= MV_HP_ERRATA_50XXB2; | ||
1959 | break; | ||
1960 | default: | ||
1961 | dev_printk(KERN_WARNING, &pdev->dev, | ||
1962 | "Applying B2 workarounds to unknown rev\n"); | ||
1963 | hp_flags |= MV_HP_ERRATA_50XXB2; | ||
1964 | break; | ||
1965 | } | ||
1966 | break; | ||
1967 | |||
1968 | case chip_604x: | ||
1969 | case chip_608x: | ||
1970 | hpriv->ops = &mv6xxx_ops; | ||
1971 | |||
1972 | switch (rev_id) { | ||
1973 | case 0x7: | ||
1974 | hp_flags |= MV_HP_ERRATA_60X1B2; | ||
1975 | break; | ||
1976 | case 0x9: | ||
1977 | hp_flags |= MV_HP_ERRATA_60X1C0; | ||
1978 | break; | ||
1979 | default: | ||
1980 | dev_printk(KERN_WARNING, &pdev->dev, | ||
1981 | "Applying B2 workarounds to unknown rev\n"); | ||
1982 | hp_flags |= MV_HP_ERRATA_60X1B2; | ||
1983 | break; | ||
1984 | } | ||
1985 | break; | ||
1986 | |||
1987 | default: | ||
1988 | printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx); | ||
1989 | return 1; | ||
1990 | } | ||
1991 | |||
1992 | hpriv->hp_flags = hp_flags; | ||
1993 | |||
1994 | return 0; | ||
1995 | } | ||
1996 | |||
1371 | /** | 1997 | /** |
1372 | * mv_host_init - Perform some early initialization of the host. | 1998 | * mv_init_host - Perform some early initialization of the host. |
1999 | * @pdev: host PCI device | ||
1373 | * @probe_ent: early data struct representing the host | 2000 | * @probe_ent: early data struct representing the host |
1374 | * | 2001 | * |
1375 | * If possible, do an early global reset of the host. Then do | 2002 | * If possible, do an early global reset of the host. Then do |
@@ -1378,23 +2005,48 @@ static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio) | |||
1378 | * LOCKING: | 2005 | * LOCKING: |
1379 | * Inherited from caller. | 2006 | * Inherited from caller. |
1380 | */ | 2007 | */ |
1381 | static int mv_host_init(struct ata_probe_ent *probe_ent) | 2008 | static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent, |
2009 | unsigned int board_idx) | ||
1382 | { | 2010 | { |
1383 | int rc = 0, n_hc, port, hc; | 2011 | int rc = 0, n_hc, port, hc; |
1384 | void __iomem *mmio = probe_ent->mmio_base; | 2012 | void __iomem *mmio = probe_ent->mmio_base; |
1385 | void __iomem *port_mmio; | 2013 | struct mv_host_priv *hpriv = probe_ent->private_data; |
1386 | 2014 | ||
1387 | if ((MV_FLAG_GLBL_SFT_RST & probe_ent->host_flags) && | 2015 | /* global interrupt mask */ |
1388 | mv_global_soft_reset(probe_ent->mmio_base)) { | 2016 | writel(0, mmio + HC_MAIN_IRQ_MASK_OFS); |
1389 | rc = 1; | 2017 | |
2018 | rc = mv_chip_id(pdev, hpriv, board_idx); | ||
2019 | if (rc) | ||
1390 | goto done; | 2020 | goto done; |
1391 | } | ||
1392 | 2021 | ||
1393 | n_hc = mv_get_hc_count(probe_ent->host_flags); | 2022 | n_hc = mv_get_hc_count(probe_ent->host_flags); |
1394 | probe_ent->n_ports = MV_PORTS_PER_HC * n_hc; | 2023 | probe_ent->n_ports = MV_PORTS_PER_HC * n_hc; |
1395 | 2024 | ||
2025 | for (port = 0; port < probe_ent->n_ports; port++) | ||
2026 | hpriv->ops->read_preamp(hpriv, port, mmio); | ||
2027 | |||
2028 | rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc); | ||
2029 | if (rc) | ||
2030 | goto done; | ||
2031 | |||
2032 | hpriv->ops->reset_flash(hpriv, mmio); | ||
2033 | hpriv->ops->reset_bus(pdev, mmio); | ||
2034 | hpriv->ops->enable_leds(hpriv, mmio); | ||
2035 | |||
1396 | for (port = 0; port < probe_ent->n_ports; port++) { | 2036 | for (port = 0; port < probe_ent->n_ports; port++) { |
1397 | port_mmio = mv_port_base(mmio, port); | 2037 | if (IS_60XX(hpriv)) { |
2038 | void __iomem *port_mmio = mv_port_base(mmio, port); | ||
2039 | |||
2040 | u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); | ||
2041 | ifctl |= (1 << 12); | ||
2042 | writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); | ||
2043 | } | ||
2044 | |||
2045 | hpriv->ops->phy_errata(hpriv, mmio, port); | ||
2046 | } | ||
2047 | |||
2048 | for (port = 0; port < probe_ent->n_ports; port++) { | ||
2049 | void __iomem *port_mmio = mv_port_base(mmio, port); | ||
1398 | mv_port_init(&probe_ent->port[port], port_mmio); | 2050 | mv_port_init(&probe_ent->port[port], port_mmio); |
1399 | } | 2051 | } |
1400 | 2052 | ||
@@ -1418,11 +2070,12 @@ static int mv_host_init(struct ata_probe_ent *probe_ent) | |||
1418 | writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS); | 2070 | writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS); |
1419 | 2071 | ||
1420 | VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x " | 2072 | VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x " |
1421 | "PCI int cause/mask=0x%08x/0x%08x\n", | 2073 | "PCI int cause/mask=0x%08x/0x%08x\n", |
1422 | readl(mmio + HC_MAIN_IRQ_CAUSE_OFS), | 2074 | readl(mmio + HC_MAIN_IRQ_CAUSE_OFS), |
1423 | readl(mmio + HC_MAIN_IRQ_MASK_OFS), | 2075 | readl(mmio + HC_MAIN_IRQ_MASK_OFS), |
1424 | readl(mmio + PCI_IRQ_CAUSE_OFS), | 2076 | readl(mmio + PCI_IRQ_CAUSE_OFS), |
1425 | readl(mmio + PCI_IRQ_MASK_OFS)); | 2077 | readl(mmio + PCI_IRQ_MASK_OFS)); |
2078 | |||
1426 | done: | 2079 | done: |
1427 | return rc; | 2080 | return rc; |
1428 | } | 2081 | } |
@@ -1458,7 +2111,7 @@ static void mv_print_info(struct ata_probe_ent *probe_ent) | |||
1458 | 2111 | ||
1459 | dev_printk(KERN_INFO, &pdev->dev, | 2112 | dev_printk(KERN_INFO, &pdev->dev, |
1460 | "%u slots %u ports %s mode IRQ via %s\n", | 2113 | "%u slots %u ports %s mode IRQ via %s\n", |
1461 | (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports, | 2114 | (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports, |
1462 | scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx"); | 2115 | scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx"); |
1463 | } | 2116 | } |
1464 | 2117 | ||
@@ -1528,7 +2181,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1528 | probe_ent->private_data = hpriv; | 2181 | probe_ent->private_data = hpriv; |
1529 | 2182 | ||
1530 | /* initialize adapter */ | 2183 | /* initialize adapter */ |
1531 | rc = mv_host_init(probe_ent); | 2184 | rc = mv_init_host(pdev, probe_ent, board_idx); |
1532 | if (rc) { | 2185 | if (rc) { |
1533 | goto err_out_hpriv; | 2186 | goto err_out_hpriv; |
1534 | } | 2187 | } |
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 242d906987ad..8a8e3e3ef0ed 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include "sata_promise.h" | 46 | #include "sata_promise.h" |
47 | 47 | ||
48 | #define DRV_NAME "sata_promise" | 48 | #define DRV_NAME "sata_promise" |
49 | #define DRV_VERSION "1.02" | 49 | #define DRV_VERSION "1.03" |
50 | 50 | ||
51 | 51 | ||
52 | enum { | 52 | enum { |
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index b2f6324a2eb2..a8987f5ff5cc 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #include <linux/libata.h> | 41 | #include <linux/libata.h> |
42 | 42 | ||
43 | #define DRV_NAME "sata_qstor" | 43 | #define DRV_NAME "sata_qstor" |
44 | #define DRV_VERSION "0.04" | 44 | #define DRV_VERSION "0.05" |
45 | 45 | ||
46 | enum { | 46 | enum { |
47 | QS_PORTS = 4, | 47 | QS_PORTS = 4, |
@@ -268,7 +268,7 @@ static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) | |||
268 | writel(val, (void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8))); | 268 | writel(val, (void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8))); |
269 | } | 269 | } |
270 | 270 | ||
271 | static void qs_fill_sg(struct ata_queued_cmd *qc) | 271 | static unsigned int qs_fill_sg(struct ata_queued_cmd *qc) |
272 | { | 272 | { |
273 | struct scatterlist *sg; | 273 | struct scatterlist *sg; |
274 | struct ata_port *ap = qc->ap; | 274 | struct ata_port *ap = qc->ap; |
@@ -296,6 +296,8 @@ static void qs_fill_sg(struct ata_queued_cmd *qc) | |||
296 | (unsigned long long)addr, len); | 296 | (unsigned long long)addr, len); |
297 | nelem++; | 297 | nelem++; |
298 | } | 298 | } |
299 | |||
300 | return nelem; | ||
299 | } | 301 | } |
300 | 302 | ||
301 | static void qs_qc_prep(struct ata_queued_cmd *qc) | 303 | static void qs_qc_prep(struct ata_queued_cmd *qc) |
@@ -304,6 +306,7 @@ static void qs_qc_prep(struct ata_queued_cmd *qc) | |||
304 | u8 dflags = QS_DF_PORD, *buf = pp->pkt; | 306 | u8 dflags = QS_DF_PORD, *buf = pp->pkt; |
305 | u8 hflags = QS_HF_DAT | QS_HF_IEN | QS_HF_VLD; | 307 | u8 hflags = QS_HF_DAT | QS_HF_IEN | QS_HF_VLD; |
306 | u64 addr; | 308 | u64 addr; |
309 | unsigned int nelem; | ||
307 | 310 | ||
308 | VPRINTK("ENTER\n"); | 311 | VPRINTK("ENTER\n"); |
309 | 312 | ||
@@ -313,7 +316,7 @@ static void qs_qc_prep(struct ata_queued_cmd *qc) | |||
313 | return; | 316 | return; |
314 | } | 317 | } |
315 | 318 | ||
316 | qs_fill_sg(qc); | 319 | nelem = qs_fill_sg(qc); |
317 | 320 | ||
318 | if ((qc->tf.flags & ATA_TFLAG_WRITE)) | 321 | if ((qc->tf.flags & ATA_TFLAG_WRITE)) |
319 | hflags |= QS_HF_DIRO; | 322 | hflags |= QS_HF_DIRO; |
@@ -324,7 +327,7 @@ static void qs_qc_prep(struct ata_queued_cmd *qc) | |||
324 | buf[ 0] = QS_HCB_HDR; | 327 | buf[ 0] = QS_HCB_HDR; |
325 | buf[ 1] = hflags; | 328 | buf[ 1] = hflags; |
326 | *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE); | 329 | *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE); |
327 | *(__le32 *)(&buf[ 8]) = cpu_to_le32(qc->n_elem); | 330 | *(__le32 *)(&buf[ 8]) = cpu_to_le32(nelem); |
328 | addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES; | 331 | addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES; |
329 | *(__le64 *)(&buf[16]) = cpu_to_le64(addr); | 332 | *(__le64 *)(&buf[16]) = cpu_to_le64(addr); |
330 | 333 | ||
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index d3198d9a72c1..cb1933a3bd55 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c | |||
@@ -139,6 +139,7 @@ enum { | |||
139 | PORT_CS_DEV_RST = (1 << 1), /* device reset */ | 139 | PORT_CS_DEV_RST = (1 << 1), /* device reset */ |
140 | PORT_CS_INIT = (1 << 2), /* port initialize */ | 140 | PORT_CS_INIT = (1 << 2), /* port initialize */ |
141 | PORT_CS_IRQ_WOC = (1 << 3), /* interrupt write one to clear */ | 141 | PORT_CS_IRQ_WOC = (1 << 3), /* interrupt write one to clear */ |
142 | PORT_CS_CDB16 = (1 << 5), /* 0=12b cdb, 1=16b cdb */ | ||
142 | PORT_CS_RESUME = (1 << 6), /* port resume */ | 143 | PORT_CS_RESUME = (1 << 6), /* port resume */ |
143 | PORT_CS_32BIT_ACTV = (1 << 10), /* 32-bit activation */ | 144 | PORT_CS_32BIT_ACTV = (1 << 10), /* 32-bit activation */ |
144 | PORT_CS_PM_EN = (1 << 13), /* port multiplier enable */ | 145 | PORT_CS_PM_EN = (1 << 13), /* port multiplier enable */ |
@@ -188,11 +189,29 @@ enum { | |||
188 | PORT_CERR_XFR_PCIPERR = 35, /* PSD ecode 11 - PCI prity err during transfer */ | 189 | PORT_CERR_XFR_PCIPERR = 35, /* PSD ecode 11 - PCI prity err during transfer */ |
189 | PORT_CERR_SENDSERVICE = 36, /* FIS received while sending service */ | 190 | PORT_CERR_SENDSERVICE = 36, /* FIS received while sending service */ |
190 | 191 | ||
192 | /* bits of PRB control field */ | ||
193 | PRB_CTRL_PROTOCOL = (1 << 0), /* override def. ATA protocol */ | ||
194 | PRB_CTRL_PACKET_READ = (1 << 4), /* PACKET cmd read */ | ||
195 | PRB_CTRL_PACKET_WRITE = (1 << 5), /* PACKET cmd write */ | ||
196 | PRB_CTRL_NIEN = (1 << 6), /* Mask completion irq */ | ||
197 | PRB_CTRL_SRST = (1 << 7), /* Soft reset request (ign BSY?) */ | ||
198 | |||
199 | /* PRB protocol field */ | ||
200 | PRB_PROT_PACKET = (1 << 0), | ||
201 | PRB_PROT_TCQ = (1 << 1), | ||
202 | PRB_PROT_NCQ = (1 << 2), | ||
203 | PRB_PROT_READ = (1 << 3), | ||
204 | PRB_PROT_WRITE = (1 << 4), | ||
205 | PRB_PROT_TRANSPARENT = (1 << 5), | ||
206 | |||
191 | /* | 207 | /* |
192 | * Other constants | 208 | * Other constants |
193 | */ | 209 | */ |
194 | SGE_TRM = (1 << 31), /* Last SGE in chain */ | 210 | SGE_TRM = (1 << 31), /* Last SGE in chain */ |
195 | PRB_SOFT_RST = (1 << 7), /* Soft reset request (ign BSY?) */ | 211 | SGE_LNK = (1 << 30), /* linked list |
212 | Points to SGT, not SGE */ | ||
213 | SGE_DRD = (1 << 29), /* discard data read (/dev/null) | ||
214 | data address ignored */ | ||
196 | 215 | ||
197 | /* board id */ | 216 | /* board id */ |
198 | BID_SIL3124 = 0, | 217 | BID_SIL3124 = 0, |
@@ -687,6 +706,7 @@ static void sil24_port_stop(struct ata_port *ap) | |||
687 | struct sil24_port_priv *pp = ap->private_data; | 706 | struct sil24_port_priv *pp = ap->private_data; |
688 | 707 | ||
689 | sil24_cblk_free(pp, dev); | 708 | sil24_cblk_free(pp, dev); |
709 | ata_pad_free(ap, dev); | ||
690 | kfree(pp); | 710 | kfree(pp); |
691 | } | 711 | } |
692 | 712 | ||
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 57e5a9d964c3..6e7f7c83a75a 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c | |||
@@ -54,7 +54,7 @@ | |||
54 | #endif /* CONFIG_PPC_OF */ | 54 | #endif /* CONFIG_PPC_OF */ |
55 | 55 | ||
56 | #define DRV_NAME "sata_svw" | 56 | #define DRV_NAME "sata_svw" |
57 | #define DRV_VERSION "1.06" | 57 | #define DRV_VERSION "1.07" |
58 | 58 | ||
59 | /* Taskfile registers offsets */ | 59 | /* Taskfile registers offsets */ |
60 | #define K2_SATA_TF_CMD_OFFSET 0x00 | 60 | #define K2_SATA_TF_CMD_OFFSET 0x00 |
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index b4bbe48acab0..dcc3ad9a9d6e 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include "sata_promise.h" | 46 | #include "sata_promise.h" |
47 | 47 | ||
48 | #define DRV_NAME "sata_sx4" | 48 | #define DRV_NAME "sata_sx4" |
49 | #define DRV_VERSION "0.7" | 49 | #define DRV_VERSION "0.8" |
50 | 50 | ||
51 | 51 | ||
52 | enum { | 52 | enum { |
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 77a6e4b9262d..fcfa486965b4 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c | |||
@@ -47,7 +47,7 @@ | |||
47 | #include <linux/libata.h> | 47 | #include <linux/libata.h> |
48 | 48 | ||
49 | #define DRV_NAME "sata_vsc" | 49 | #define DRV_NAME "sata_vsc" |
50 | #define DRV_VERSION "1.0" | 50 | #define DRV_VERSION "1.1" |
51 | 51 | ||
52 | /* Interrupt register offsets (from chip base address) */ | 52 | /* Interrupt register offsets (from chip base address) */ |
53 | #define VSC_SATA_INT_STAT_OFFSET 0x00 | 53 | #define VSC_SATA_INT_STAT_OFFSET 0x00 |
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 2efb317153ce..67e9afa000c1 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/keyboard.h> | 34 | #include <linux/keyboard.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/pm.h> | 36 | #include <linux/pm.h> |
37 | #include <linux/pm_legacy.h> | ||
37 | #include <linux/bitops.h> | 38 | #include <linux/bitops.h> |
38 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
39 | 40 | ||
@@ -1343,7 +1344,7 @@ static void show_serial_version(void) | |||
1343 | printk("MC68328 serial driver version 1.00\n"); | 1344 | printk("MC68328 serial driver version 1.00\n"); |
1344 | } | 1345 | } |
1345 | 1346 | ||
1346 | #ifdef CONFIG_PM | 1347 | #ifdef CONFIG_PM_LEGACY |
1347 | /* Serial Power management | 1348 | /* Serial Power management |
1348 | * The console (currently fixed at line 0) is a special case for power | 1349 | * The console (currently fixed at line 0) is a special case for power |
1349 | * management because the kernel is so chatty. The console will be | 1350 | * management because the kernel is so chatty. The console will be |
@@ -1393,7 +1394,7 @@ void startup_console(void) | |||
1393 | struct m68k_serial *info = &m68k_soft[0]; | 1394 | struct m68k_serial *info = &m68k_soft[0]; |
1394 | startup(info); | 1395 | startup(info); |
1395 | } | 1396 | } |
1396 | #endif | 1397 | #endif /* CONFIG_PM_LEGACY */ |
1397 | 1398 | ||
1398 | 1399 | ||
1399 | static struct tty_operations rs_ops = { | 1400 | static struct tty_operations rs_ops = { |
@@ -1486,7 +1487,7 @@ rs68328_init(void) | |||
1486 | IRQ_FLG_STD, | 1487 | IRQ_FLG_STD, |
1487 | "M68328_UART", NULL)) | 1488 | "M68328_UART", NULL)) |
1488 | panic("Unable to attach 68328 serial interrupt\n"); | 1489 | panic("Unable to attach 68328 serial interrupt\n"); |
1489 | #ifdef CONFIG_PM | 1490 | #ifdef CONFIG_PM_LEGACY |
1490 | serial_pm[i] = pm_register(PM_SYS_DEV, PM_SYS_COM, serial_pm_callback); | 1491 | serial_pm[i] = pm_register(PM_SYS_DEV, PM_SYS_COM, serial_pm_callback); |
1491 | if (serial_pm[i]) | 1492 | if (serial_pm[i]) |
1492 | serial_pm[i]->data = info; | 1493 | serial_pm[i]->data = info; |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 3742753241ee..e08510d09ff6 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -999,7 +999,10 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | |||
999 | serial_outp(up, UART_MCR, save_mcr); | 999 | serial_outp(up, UART_MCR, save_mcr); |
1000 | serial8250_clear_fifos(up); | 1000 | serial8250_clear_fifos(up); |
1001 | (void)serial_in(up, UART_RX); | 1001 | (void)serial_in(up, UART_RX); |
1002 | serial_outp(up, UART_IER, 0); | 1002 | if (up->capabilities & UART_CAP_UUE) |
1003 | serial_outp(up, UART_IER, UART_IER_UUE); | ||
1004 | else | ||
1005 | serial_outp(up, UART_IER, 0); | ||
1003 | 1006 | ||
1004 | out: | 1007 | out: |
1005 | spin_unlock_irqrestore(&up->port.lock, flags); | 1008 | spin_unlock_irqrestore(&up->port.lock, flags); |
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 5d8660a42b77..b79ed0665d51 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c | |||
@@ -323,6 +323,8 @@ static const struct pnp_device_id pnp_dev_table[] = { | |||
323 | { "USR9180", 0 }, | 323 | { "USR9180", 0 }, |
324 | /* U.S. Robotics 56K Voice INT PnP*/ | 324 | /* U.S. Robotics 56K Voice INT PnP*/ |
325 | { "USR9190", 0 }, | 325 | { "USR9190", 0 }, |
326 | /* HP Compaq Tablet PC tc1100 Wacom tablet */ | ||
327 | { "WACF005", 0 }, | ||
326 | /* Rockwell's (PORALiNK) 33600 INT PNP */ | 328 | /* Rockwell's (PORALiNK) 33600 INT PNP */ |
327 | { "WCI0003", 0 }, | 329 | { "WCI0003", 0 }, |
328 | /* Unkown PnP modems */ | 330 | /* Unkown PnP modems */ |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 25825f2aba22..987d22b53c22 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * Based on ppc8xx.c by Thomas Gleixner | 7 | * Based on ppc8xx.c by Thomas Gleixner |
8 | * Based on drivers/serial/amba.c by Russell King | 8 | * Based on drivers/serial/amba.c by Russell King |
9 | * | 9 | * |
10 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 10 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) |
11 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 11 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
12 | * | 12 | * |
13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 13 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 4b0786e7eb7f..d789ee55cbb7 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Driver for CPM (SCC/SMC) serial ports; CPM1 definitions | 4 | * Driver for CPM (SCC/SMC) serial ports; CPM1 definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 6 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) |
7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
8 | * | 8 | * |
9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index 15ad58d94889..fd9e53ed3feb 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Driver for CPM (SCC/SMC) serial ports; CPM2 definitions | 4 | * Driver for CPM (SCC/SMC) serial ports; CPM2 definitions |
5 | * | 5 | * |
6 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2) | 6 | * Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2) |
7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) | 7 | * Pantelis Antoniou (panto@intracom.gr) (CPM1) |
8 | * | 8 | * |
9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. | 9 | * Copyright (C) 2004 Freescale Semiconductor, Inc. |
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index e63b9dffc8d7..4d8516d1bb71 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * dz.c: Serial port driver for DECStations equiped | 2 | * dz.c: Serial port driver for DECStations equiped |
3 | * with the DZ chipset. | 3 | * with the DZ chipset. |
4 | * | 4 | * |
5 | * Copyright (C) 1998 Olivier A. D. Lebaillif | 5 | * Copyright (C) 1998 Olivier A. D. Lebaillif |
6 | * | 6 | * |
7 | * Email: olivier.lebaillif@ifrsys.com | 7 | * Email: olivier.lebaillif@ifrsys.com |
8 | * | 8 | * |
9 | * [31-AUG-98] triemer | 9 | * [31-AUG-98] triemer |
@@ -11,14 +11,14 @@ | |||
11 | * removed base_addr code - moving address assignment to setup.c | 11 | * removed base_addr code - moving address assignment to setup.c |
12 | * Changed name of dz_init to rs_init to be consistent with tc code | 12 | * Changed name of dz_init to rs_init to be consistent with tc code |
13 | * [13-NOV-98] triemer fixed code to receive characters | 13 | * [13-NOV-98] triemer fixed code to receive characters |
14 | * after patches by harald to irq code. | 14 | * after patches by harald to irq code. |
15 | * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout | 15 | * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout |
16 | * field from "current" - somewhere between 2.1.121 and 2.1.131 | 16 | * field from "current" - somewhere between 2.1.121 and 2.1.131 |
17 | Qua Jun 27 15:02:26 BRT 2001 | 17 | Qua Jun 27 15:02:26 BRT 2001 |
18 | * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups | 18 | * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups |
19 | * | 19 | * |
20 | * Parts (C) 1999 David Airlie, airlied@linux.ie | 20 | * Parts (C) 1999 David Airlie, airlied@linux.ie |
21 | * [07-SEP-99] Bugfixes | 21 | * [07-SEP-99] Bugfixes |
22 | * | 22 | * |
23 | * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk> | 23 | * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk> |
24 | * Converted to new serial core | 24 | * Converted to new serial core |
@@ -64,7 +64,7 @@ static struct dz_port dz_ports[DZ_NB_PORT]; | |||
64 | 64 | ||
65 | #ifdef DEBUG_DZ | 65 | #ifdef DEBUG_DZ |
66 | /* | 66 | /* |
67 | * debugging code to send out chars via prom | 67 | * debugging code to send out chars via prom |
68 | */ | 68 | */ |
69 | static void debug_console(const char *s, int count) | 69 | static void debug_console(const char *s, int count) |
70 | { | 70 | { |
@@ -82,7 +82,7 @@ static void debug_console(const char *s, int count) | |||
82 | * ------------------------------------------------------------ | 82 | * ------------------------------------------------------------ |
83 | * dz_in () and dz_out () | 83 | * dz_in () and dz_out () |
84 | * | 84 | * |
85 | * These routines are used to access the registers of the DZ | 85 | * These routines are used to access the registers of the DZ |
86 | * chip, hiding relocation differences between implementation. | 86 | * chip, hiding relocation differences between implementation. |
87 | * ------------------------------------------------------------ | 87 | * ------------------------------------------------------------ |
88 | */ | 88 | */ |
@@ -106,8 +106,8 @@ static inline void dz_out(struct dz_port *dport, unsigned offset, | |||
106 | * ------------------------------------------------------------ | 106 | * ------------------------------------------------------------ |
107 | * rs_stop () and rs_start () | 107 | * rs_stop () and rs_start () |
108 | * | 108 | * |
109 | * These routines are called before setting or resetting | 109 | * These routines are called before setting or resetting |
110 | * tty->stopped. They enable or disable transmitter interrupts, | 110 | * tty->stopped. They enable or disable transmitter interrupts, |
111 | * as necessary. | 111 | * as necessary. |
112 | * ------------------------------------------------------------ | 112 | * ------------------------------------------------------------ |
113 | */ | 113 | */ |
@@ -156,17 +156,17 @@ static void dz_enable_ms(struct uart_port *port) | |||
156 | 156 | ||
157 | /* | 157 | /* |
158 | * ------------------------------------------------------------ | 158 | * ------------------------------------------------------------ |
159 | * Here starts the interrupt handling routines. All of the | 159 | * Here starts the interrupt handling routines. All of the |
160 | * following subroutines are declared as inline and are folded | 160 | * following subroutines are declared as inline and are folded |
161 | * into dz_interrupt. They were separated out for readability's | 161 | * into dz_interrupt. They were separated out for readability's |
162 | * sake. | 162 | * sake. |
163 | * | 163 | * |
164 | * Note: rs_interrupt() is a "fast" interrupt, which means that it | 164 | * Note: rs_interrupt() is a "fast" interrupt, which means that it |
165 | * runs with interrupts turned off. People who may want to modify | 165 | * runs with interrupts turned off. People who may want to modify |
166 | * rs_interrupt() should try to keep the interrupt handler as fast as | 166 | * rs_interrupt() should try to keep the interrupt handler as fast as |
167 | * possible. After you are done making modifications, it is not a bad | 167 | * possible. After you are done making modifications, it is not a bad |
168 | * idea to do: | 168 | * idea to do: |
169 | * | 169 | * |
170 | * make drivers/serial/dz.s | 170 | * make drivers/serial/dz.s |
171 | * | 171 | * |
172 | * and look at the resulting assemble code in dz.s. | 172 | * and look at the resulting assemble code in dz.s. |
@@ -403,7 +403,7 @@ static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl) | |||
403 | * startup () | 403 | * startup () |
404 | * | 404 | * |
405 | * various initialization tasks | 405 | * various initialization tasks |
406 | * ------------------------------------------------------------------- | 406 | * ------------------------------------------------------------------- |
407 | */ | 407 | */ |
408 | static int dz_startup(struct uart_port *uport) | 408 | static int dz_startup(struct uart_port *uport) |
409 | { | 409 | { |
@@ -430,13 +430,13 @@ static int dz_startup(struct uart_port *uport) | |||
430 | return 0; | 430 | return 0; |
431 | } | 431 | } |
432 | 432 | ||
433 | /* | 433 | /* |
434 | * ------------------------------------------------------------------- | 434 | * ------------------------------------------------------------------- |
435 | * shutdown () | 435 | * shutdown () |
436 | * | 436 | * |
437 | * This routine will shutdown a serial port; interrupts are disabled, and | 437 | * This routine will shutdown a serial port; interrupts are disabled, and |
438 | * DTR is dropped if the hangup on close termio flag is on. | 438 | * DTR is dropped if the hangup on close termio flag is on. |
439 | * ------------------------------------------------------------------- | 439 | * ------------------------------------------------------------------- |
440 | */ | 440 | */ |
441 | static void dz_shutdown(struct uart_port *uport) | 441 | static void dz_shutdown(struct uart_port *uport) |
442 | { | 442 | { |
@@ -451,7 +451,7 @@ static void dz_shutdown(struct uart_port *uport) | |||
451 | * release the bus after transmitting. This must be done when | 451 | * release the bus after transmitting. This must be done when |
452 | * the transmit shift register is empty, not be done when the | 452 | * the transmit shift register is empty, not be done when the |
453 | * transmit holding register is empty. This functionality | 453 | * transmit holding register is empty. This functionality |
454 | * allows an RS485 driver to be written in user space. | 454 | * allows an RS485 driver to be written in user space. |
455 | */ | 455 | */ |
456 | static unsigned int dz_tx_empty(struct uart_port *uport) | 456 | static unsigned int dz_tx_empty(struct uart_port *uport) |
457 | { | 457 | { |
@@ -645,9 +645,9 @@ static void __init dz_init_ports(void) | |||
645 | 645 | ||
646 | if (mips_machtype == MACH_DS23100 || | 646 | if (mips_machtype == MACH_DS23100 || |
647 | mips_machtype == MACH_DS5100) | 647 | mips_machtype == MACH_DS5100) |
648 | base = (unsigned long) KN01_DZ11_BASE; | 648 | base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_DZ11); |
649 | else | 649 | else |
650 | base = (unsigned long) KN02_DZ11_BASE; | 650 | base = CKSEG1ADDR(KN02_SLOT_BASE + KN02_DZ11); |
651 | 651 | ||
652 | for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { | 652 | for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { |
653 | spin_lock_init(&dport->port.lock); | 653 | spin_lock_init(&dport->port.lock); |
@@ -695,13 +695,13 @@ static void dz_console_put_char(struct dz_port *dport, unsigned char ch) | |||
695 | 695 | ||
696 | spin_unlock_irqrestore(&dport->port.lock, flags); | 696 | spin_unlock_irqrestore(&dport->port.lock, flags); |
697 | } | 697 | } |
698 | /* | 698 | /* |
699 | * ------------------------------------------------------------------- | 699 | * ------------------------------------------------------------------- |
700 | * dz_console_print () | 700 | * dz_console_print () |
701 | * | 701 | * |
702 | * dz_console_print is registered for printk. | 702 | * dz_console_print is registered for printk. |
703 | * The console must be locked when we get here. | 703 | * The console must be locked when we get here. |
704 | * ------------------------------------------------------------------- | 704 | * ------------------------------------------------------------------- |
705 | */ | 705 | */ |
706 | static void dz_console_print(struct console *cons, | 706 | static void dz_console_print(struct console *cons, |
707 | const char *str, | 707 | const char *str, |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 5d3cb8486447..b8727d9bf690 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -725,7 +725,7 @@ mpc52xx_uart_probe(struct platform_device *dev) | |||
725 | int i, idx, ret; | 725 | int i, idx, ret; |
726 | 726 | ||
727 | /* Check validity & presence */ | 727 | /* Check validity & presence */ |
728 | idx = pdev->id; | 728 | idx = dev->id; |
729 | if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM) | 729 | if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM) |
730 | return -EINVAL; | 730 | return -EINVAL; |
731 | 731 | ||
@@ -748,7 +748,7 @@ mpc52xx_uart_probe(struct platform_device *dev) | |||
748 | port->ops = &mpc52xx_uart_ops; | 748 | port->ops = &mpc52xx_uart_ops; |
749 | 749 | ||
750 | /* Search for IRQ and mapbase */ | 750 | /* Search for IRQ and mapbase */ |
751 | for (i=0 ; i<pdev->num_resources ; i++, res++) { | 751 | for (i=0 ; i<dev->num_resources ; i++, res++) { |
752 | if (res->flags & IORESOURCE_MEM) | 752 | if (res->flags & IORESOURCE_MEM) |
753 | port->mapbase = res->start; | 753 | port->mapbase = res->start; |
754 | else if (res->flags & IORESOURCE_IRQ) | 754 | else if (res->flags & IORESOURCE_IRQ) |
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index fd9deee20e05..0e3daf6d7b50 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c | |||
@@ -156,7 +156,7 @@ static void sa1100_stop_tx(struct uart_port *port) | |||
156 | } | 156 | } |
157 | 157 | ||
158 | /* | 158 | /* |
159 | * interrupts may not be disabled on entry | 159 | * port locked and interrupts disabled |
160 | */ | 160 | */ |
161 | static void sa1100_start_tx(struct uart_port *port) | 161 | static void sa1100_start_tx(struct uart_port *port) |
162 | { | 162 | { |
@@ -164,11 +164,9 @@ static void sa1100_start_tx(struct uart_port *port) | |||
164 | unsigned long flags; | 164 | unsigned long flags; |
165 | u32 utcr3; | 165 | u32 utcr3; |
166 | 166 | ||
167 | spin_lock_irqsave(&sport->port.lock, flags); | ||
168 | utcr3 = UART_GET_UTCR3(sport); | 167 | utcr3 = UART_GET_UTCR3(sport); |
169 | sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS); | 168 | sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_TFS); |
170 | UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE); | 169 | UART_PUT_UTCR3(sport, utcr3 | UTCR3_TIE); |
171 | spin_unlock_irqrestore(&sport->port.lock, flags); | ||
172 | } | 170 | } |
173 | 171 | ||
174 | /* | 172 | /* |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 427a23858076..2331296e1e17 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -209,33 +209,45 @@ static void uart_shutdown(struct uart_state *state) | |||
209 | struct uart_info *info = state->info; | 209 | struct uart_info *info = state->info; |
210 | struct uart_port *port = state->port; | 210 | struct uart_port *port = state->port; |
211 | 211 | ||
212 | if (!(info->flags & UIF_INITIALIZED)) | ||
213 | return; | ||
214 | |||
215 | /* | 212 | /* |
216 | * Turn off DTR and RTS early. | 213 | * Set the TTY IO error marker |
217 | */ | 214 | */ |
218 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) | 215 | if (info->tty) |
219 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 216 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
220 | 217 | ||
221 | /* | 218 | if (info->flags & UIF_INITIALIZED) { |
222 | * clear delta_msr_wait queue to avoid mem leaks: we may free | 219 | info->flags &= ~UIF_INITIALIZED; |
223 | * the irq here so the queue might never be woken up. Note | ||
224 | * that we won't end up waiting on delta_msr_wait again since | ||
225 | * any outstanding file descriptors should be pointing at | ||
226 | * hung_up_tty_fops now. | ||
227 | */ | ||
228 | wake_up_interruptible(&info->delta_msr_wait); | ||
229 | 220 | ||
230 | /* | 221 | /* |
231 | * Free the IRQ and disable the port. | 222 | * Turn off DTR and RTS early. |
232 | */ | 223 | */ |
233 | port->ops->shutdown(port); | 224 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) |
225 | uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
226 | |||
227 | /* | ||
228 | * clear delta_msr_wait queue to avoid mem leaks: we may free | ||
229 | * the irq here so the queue might never be woken up. Note | ||
230 | * that we won't end up waiting on delta_msr_wait again since | ||
231 | * any outstanding file descriptors should be pointing at | ||
232 | * hung_up_tty_fops now. | ||
233 | */ | ||
234 | wake_up_interruptible(&info->delta_msr_wait); | ||
235 | |||
236 | /* | ||
237 | * Free the IRQ and disable the port. | ||
238 | */ | ||
239 | port->ops->shutdown(port); | ||
240 | |||
241 | /* | ||
242 | * Ensure that the IRQ handler isn't running on another CPU. | ||
243 | */ | ||
244 | synchronize_irq(port->irq); | ||
245 | } | ||
234 | 246 | ||
235 | /* | 247 | /* |
236 | * Ensure that the IRQ handler isn't running on another CPU. | 248 | * kill off our tasklet |
237 | */ | 249 | */ |
238 | synchronize_irq(port->irq); | 250 | tasklet_kill(&info->tlet); |
239 | 251 | ||
240 | /* | 252 | /* |
241 | * Free the transmit buffer page. | 253 | * Free the transmit buffer page. |
@@ -244,15 +256,6 @@ static void uart_shutdown(struct uart_state *state) | |||
244 | free_page((unsigned long)info->xmit.buf); | 256 | free_page((unsigned long)info->xmit.buf); |
245 | info->xmit.buf = NULL; | 257 | info->xmit.buf = NULL; |
246 | } | 258 | } |
247 | |||
248 | /* | ||
249 | * kill off our tasklet | ||
250 | */ | ||
251 | tasklet_kill(&info->tlet); | ||
252 | if (info->tty) | ||
253 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
254 | |||
255 | info->flags &= ~UIF_INITIALIZED; | ||
256 | } | 259 | } |
257 | 260 | ||
258 | /** | 261 | /** |
@@ -1928,14 +1931,25 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
1928 | 1931 | ||
1929 | if (state->info && state->info->flags & UIF_INITIALIZED) { | 1932 | if (state->info && state->info->flags & UIF_INITIALIZED) { |
1930 | struct uart_ops *ops = port->ops; | 1933 | struct uart_ops *ops = port->ops; |
1934 | int ret; | ||
1931 | 1935 | ||
1932 | ops->set_mctrl(port, 0); | 1936 | ops->set_mctrl(port, 0); |
1933 | ops->startup(port); | 1937 | ret = ops->startup(port); |
1934 | uart_change_speed(state, NULL); | 1938 | if (ret == 0) { |
1935 | spin_lock_irq(&port->lock); | 1939 | uart_change_speed(state, NULL); |
1936 | ops->set_mctrl(port, port->mctrl); | 1940 | spin_lock_irq(&port->lock); |
1937 | ops->start_tx(port); | 1941 | ops->set_mctrl(port, port->mctrl); |
1938 | spin_unlock_irq(&port->lock); | 1942 | ops->start_tx(port); |
1943 | spin_unlock_irq(&port->lock); | ||
1944 | } else { | ||
1945 | /* | ||
1946 | * Failed to resume - maybe hardware went away? | ||
1947 | * Clear the "initialized" flag so we won't try | ||
1948 | * to call the low level drivers shutdown method. | ||
1949 | */ | ||
1950 | state->info->flags &= ~UIF_INITIALIZED; | ||
1951 | uart_shutdown(state); | ||
1952 | } | ||
1939 | } | 1953 | } |
1940 | 1954 | ||
1941 | up(&state->sem); | 1955 | up(&state->sem); |
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index c52af73a251b..6756d0fab6fe 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * DECstation changes | 7 | * DECstation changes |
8 | * Copyright (C) 1998-2000 Harald Koerfgen | 8 | * Copyright (C) 1998-2000 Harald Koerfgen |
9 | * Copyright (C) 2000, 2001, 2002, 2003, 2004 Maciej W. Rozycki | 9 | * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Maciej W. Rozycki |
10 | * | 10 | * |
11 | * For the rest of the code the original Copyright applies: | 11 | * For the rest of the code the original Copyright applies: |
12 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) | 12 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) |
@@ -55,6 +55,7 @@ | |||
55 | #include <linux/delay.h> | 55 | #include <linux/delay.h> |
56 | #include <linux/init.h> | 56 | #include <linux/init.h> |
57 | #include <linux/ioport.h> | 57 | #include <linux/ioport.h> |
58 | #include <linux/spinlock.h> | ||
58 | #ifdef CONFIG_SERIAL_DEC_CONSOLE | 59 | #ifdef CONFIG_SERIAL_DEC_CONSOLE |
59 | #include <linux/console.h> | 60 | #include <linux/console.h> |
60 | #endif | 61 | #endif |
@@ -63,7 +64,6 @@ | |||
63 | #include <asm/pgtable.h> | 64 | #include <asm/pgtable.h> |
64 | #include <asm/irq.h> | 65 | #include <asm/irq.h> |
65 | #include <asm/system.h> | 66 | #include <asm/system.h> |
66 | #include <asm/uaccess.h> | ||
67 | #include <asm/bootinfo.h> | 67 | #include <asm/bootinfo.h> |
68 | 68 | ||
69 | #include <asm/dec/interrupts.h> | 69 | #include <asm/dec/interrupts.h> |
@@ -128,6 +128,8 @@ static struct zs_parms ds_parms = { | |||
128 | 128 | ||
129 | #define BUS_PRESENT (DS_BUS_PRESENT) | 129 | #define BUS_PRESENT (DS_BUS_PRESENT) |
130 | 130 | ||
131 | DEFINE_SPINLOCK(zs_lock); | ||
132 | |||
131 | struct dec_zschannel zs_channels[NUM_CHANNELS]; | 133 | struct dec_zschannel zs_channels[NUM_CHANNELS]; |
132 | struct dec_serial zs_soft[NUM_CHANNELS]; | 134 | struct dec_serial zs_soft[NUM_CHANNELS]; |
133 | int zs_channels_found; | 135 | int zs_channels_found; |
@@ -159,8 +161,6 @@ static unsigned char zs_init_regs[16] __initdata = { | |||
159 | 0 /* write 15 */ | 161 | 0 /* write 15 */ |
160 | }; | 162 | }; |
161 | 163 | ||
162 | DECLARE_TASK_QUEUE(tq_zs_serial); | ||
163 | |||
164 | static struct tty_driver *serial_driver; | 164 | static struct tty_driver *serial_driver; |
165 | 165 | ||
166 | /* serial subtype definitions */ | 166 | /* serial subtype definitions */ |
@@ -294,8 +294,7 @@ static inline void zs_rtsdtr(struct dec_serial *info, int which, int set) | |||
294 | { | 294 | { |
295 | unsigned long flags; | 295 | unsigned long flags; |
296 | 296 | ||
297 | 297 | spin_lock_irqsave(&zs_lock, flags); | |
298 | save_flags(flags); cli(); | ||
299 | if (info->zs_channel != info->zs_chan_a) { | 298 | if (info->zs_channel != info->zs_chan_a) { |
300 | if (set) { | 299 | if (set) { |
301 | info->zs_chan_a->curregs[5] |= (which & (RTS | DTR)); | 300 | info->zs_chan_a->curregs[5] |= (which & (RTS | DTR)); |
@@ -304,7 +303,7 @@ static inline void zs_rtsdtr(struct dec_serial *info, int which, int set) | |||
304 | } | 303 | } |
305 | write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); | 304 | write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); |
306 | } | 305 | } |
307 | restore_flags(flags); | 306 | spin_unlock_irqrestore(&zs_lock, flags); |
308 | } | 307 | } |
309 | 308 | ||
310 | /* Utility routines for the Zilog */ | 309 | /* Utility routines for the Zilog */ |
@@ -345,12 +344,10 @@ static inline void rs_recv_clear(struct dec_zschannel *zsc) | |||
345 | * This routine is used by the interrupt handler to schedule | 344 | * This routine is used by the interrupt handler to schedule |
346 | * processing in the software interrupt portion of the driver. | 345 | * processing in the software interrupt portion of the driver. |
347 | */ | 346 | */ |
348 | static _INLINE_ void rs_sched_event(struct dec_serial *info, | 347 | static _INLINE_ void rs_sched_event(struct dec_serial *info, int event) |
349 | int event) | ||
350 | { | 348 | { |
351 | info->event |= 1 << event; | 349 | info->event |= 1 << event; |
352 | queue_task(&info->tqueue, &tq_zs_serial); | 350 | tasklet_schedule(&info->tlet); |
353 | mark_bh(SERIAL_BH); | ||
354 | } | 351 | } |
355 | 352 | ||
356 | static _INLINE_ void receive_chars(struct dec_serial *info, | 353 | static _INLINE_ void receive_chars(struct dec_serial *info, |
@@ -497,9 +494,10 @@ static _INLINE_ void status_handle(struct dec_serial *info) | |||
497 | /* | 494 | /* |
498 | * This is the serial driver's generic interrupt routine | 495 | * This is the serial driver's generic interrupt routine |
499 | */ | 496 | */ |
500 | void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) | 497 | static irqreturn_t rs_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
501 | { | 498 | { |
502 | struct dec_serial *info = (struct dec_serial *) dev_id; | 499 | struct dec_serial *info = (struct dec_serial *) dev_id; |
500 | irqreturn_t status = IRQ_NONE; | ||
503 | unsigned char zs_intreg; | 501 | unsigned char zs_intreg; |
504 | int shift; | 502 | int shift; |
505 | 503 | ||
@@ -521,6 +519,8 @@ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
521 | if ((zs_intreg & CHAN_IRQMASK) == 0) | 519 | if ((zs_intreg & CHAN_IRQMASK) == 0) |
522 | break; | 520 | break; |
523 | 521 | ||
522 | status = IRQ_HANDLED; | ||
523 | |||
524 | if (zs_intreg & CHBRxIP) { | 524 | if (zs_intreg & CHBRxIP) { |
525 | receive_chars(info, regs); | 525 | receive_chars(info, regs); |
526 | } | 526 | } |
@@ -534,6 +534,8 @@ void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
534 | 534 | ||
535 | /* Why do we need this ? */ | 535 | /* Why do we need this ? */ |
536 | write_zsreg(info->zs_channel, 0, RES_H_IUS); | 536 | write_zsreg(info->zs_channel, 0, RES_H_IUS); |
537 | |||
538 | return status; | ||
537 | } | 539 | } |
538 | 540 | ||
539 | #ifdef ZS_DEBUG_REGS | 541 | #ifdef ZS_DEBUG_REGS |
@@ -578,12 +580,12 @@ static void rs_stop(struct tty_struct *tty) | |||
578 | return; | 580 | return; |
579 | 581 | ||
580 | #if 1 | 582 | #if 1 |
581 | save_flags(flags); cli(); | 583 | spin_lock_irqsave(&zs_lock, flags); |
582 | if (info->zs_channel->curregs[5] & TxENAB) { | 584 | if (info->zs_channel->curregs[5] & TxENAB) { |
583 | info->zs_channel->curregs[5] &= ~TxENAB; | 585 | info->zs_channel->curregs[5] &= ~TxENAB; |
584 | write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); | 586 | write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); |
585 | } | 587 | } |
586 | restore_flags(flags); | 588 | spin_unlock_irqrestore(&zs_lock, flags); |
587 | #endif | 589 | #endif |
588 | } | 590 | } |
589 | 591 | ||
@@ -595,7 +597,7 @@ static void rs_start(struct tty_struct *tty) | |||
595 | if (serial_paranoia_check(info, tty->name, "rs_start")) | 597 | if (serial_paranoia_check(info, tty->name, "rs_start")) |
596 | return; | 598 | return; |
597 | 599 | ||
598 | save_flags(flags); cli(); | 600 | spin_lock_irqsave(&zs_lock, flags); |
599 | #if 1 | 601 | #if 1 |
600 | if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) { | 602 | if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) { |
601 | info->zs_channel->curregs[5] |= TxENAB; | 603 | info->zs_channel->curregs[5] |= TxENAB; |
@@ -606,7 +608,7 @@ static void rs_start(struct tty_struct *tty) | |||
606 | transmit_chars(info); | 608 | transmit_chars(info); |
607 | } | 609 | } |
608 | #endif | 610 | #endif |
609 | restore_flags(flags); | 611 | spin_unlock_irqrestore(&zs_lock, flags); |
610 | } | 612 | } |
611 | 613 | ||
612 | /* | 614 | /* |
@@ -618,12 +620,8 @@ static void rs_start(struct tty_struct *tty) | |||
618 | * interrupt driver proper are done; the interrupt driver schedules | 620 | * interrupt driver proper are done; the interrupt driver schedules |
619 | * them using rs_sched_event(), and they get done here. | 621 | * them using rs_sched_event(), and they get done here. |
620 | */ | 622 | */ |
621 | static void do_serial_bh(void) | ||
622 | { | ||
623 | run_task_queue(&tq_zs_serial); | ||
624 | } | ||
625 | 623 | ||
626 | static void do_softint(void *private_) | 624 | static void do_softint(unsigned long private_) |
627 | { | 625 | { |
628 | struct dec_serial *info = (struct dec_serial *) private_; | 626 | struct dec_serial *info = (struct dec_serial *) private_; |
629 | struct tty_struct *tty; | 627 | struct tty_struct *tty; |
@@ -634,10 +632,11 @@ static void do_softint(void *private_) | |||
634 | 632 | ||
635 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { | 633 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { |
636 | tty_wakeup(tty); | 634 | tty_wakeup(tty); |
635 | wake_up_interruptible(&tty->write_wait); | ||
637 | } | 636 | } |
638 | } | 637 | } |
639 | 638 | ||
640 | int zs_startup(struct dec_serial * info) | 639 | static int zs_startup(struct dec_serial * info) |
641 | { | 640 | { |
642 | unsigned long flags; | 641 | unsigned long flags; |
643 | 642 | ||
@@ -650,7 +649,7 @@ int zs_startup(struct dec_serial * info) | |||
650 | return -ENOMEM; | 649 | return -ENOMEM; |
651 | } | 650 | } |
652 | 651 | ||
653 | save_flags(flags); cli(); | 652 | spin_lock_irqsave(&zs_lock, flags); |
654 | 653 | ||
655 | #ifdef SERIAL_DEBUG_OPEN | 654 | #ifdef SERIAL_DEBUG_OPEN |
656 | printk("starting up ttyS%d (irq %d)...", info->line, info->irq); | 655 | printk("starting up ttyS%d (irq %d)...", info->line, info->irq); |
@@ -706,7 +705,7 @@ int zs_startup(struct dec_serial * info) | |||
706 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 705 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
707 | 706 | ||
708 | info->flags |= ZILOG_INITIALIZED; | 707 | info->flags |= ZILOG_INITIALIZED; |
709 | restore_flags(flags); | 708 | spin_unlock_irqrestore(&zs_lock, flags); |
710 | return 0; | 709 | return 0; |
711 | } | 710 | } |
712 | 711 | ||
@@ -726,7 +725,7 @@ static void shutdown(struct dec_serial * info) | |||
726 | info->irq); | 725 | info->irq); |
727 | #endif | 726 | #endif |
728 | 727 | ||
729 | save_flags(flags); cli(); /* Disable interrupts */ | 728 | spin_lock_irqsave(&zs_lock, flags); |
730 | 729 | ||
731 | if (info->xmit_buf) { | 730 | if (info->xmit_buf) { |
732 | free_page((unsigned long) info->xmit_buf); | 731 | free_page((unsigned long) info->xmit_buf); |
@@ -749,7 +748,7 @@ static void shutdown(struct dec_serial * info) | |||
749 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 748 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
750 | 749 | ||
751 | info->flags &= ~ZILOG_INITIALIZED; | 750 | info->flags &= ~ZILOG_INITIALIZED; |
752 | restore_flags(flags); | 751 | spin_unlock_irqrestore(&zs_lock, flags); |
753 | } | 752 | } |
754 | 753 | ||
755 | /* | 754 | /* |
@@ -785,7 +784,7 @@ static void change_speed(struct dec_serial *info) | |||
785 | i += 15; | 784 | i += 15; |
786 | } | 785 | } |
787 | 786 | ||
788 | save_flags(flags); cli(); | 787 | spin_lock_irqsave(&zs_lock, flags); |
789 | info->zs_baud = baud_table[i]; | 788 | info->zs_baud = baud_table[i]; |
790 | if (info->zs_baud) { | 789 | if (info->zs_baud) { |
791 | brg = BPS_TO_BRG(info->zs_baud, zs_parms->clock/info->clk_divisor); | 790 | brg = BPS_TO_BRG(info->zs_baud, zs_parms->clock/info->clk_divisor); |
@@ -858,7 +857,7 @@ static void change_speed(struct dec_serial *info) | |||
858 | /* Load up the new values */ | 857 | /* Load up the new values */ |
859 | load_zsregs(info->zs_channel, info->zs_channel->curregs); | 858 | load_zsregs(info->zs_channel, info->zs_channel->curregs); |
860 | 859 | ||
861 | restore_flags(flags); | 860 | spin_unlock_irqrestore(&zs_lock, flags); |
862 | } | 861 | } |
863 | 862 | ||
864 | static void rs_flush_chars(struct tty_struct *tty) | 863 | static void rs_flush_chars(struct tty_struct *tty) |
@@ -874,9 +873,9 @@ static void rs_flush_chars(struct tty_struct *tty) | |||
874 | return; | 873 | return; |
875 | 874 | ||
876 | /* Enable transmitter */ | 875 | /* Enable transmitter */ |
877 | save_flags(flags); cli(); | 876 | spin_lock_irqsave(&zs_lock, flags); |
878 | transmit_chars(info); | 877 | transmit_chars(info); |
879 | restore_flags(flags); | 878 | spin_unlock_irqrestore(&zs_lock, flags); |
880 | } | 879 | } |
881 | 880 | ||
882 | static int rs_write(struct tty_struct * tty, | 881 | static int rs_write(struct tty_struct * tty, |
@@ -892,26 +891,17 @@ static int rs_write(struct tty_struct * tty, | |||
892 | if (!tty || !info->xmit_buf) | 891 | if (!tty || !info->xmit_buf) |
893 | return 0; | 892 | return 0; |
894 | 893 | ||
895 | save_flags(flags); | ||
896 | while (1) { | 894 | while (1) { |
897 | cli(); | 895 | spin_lock_irqsave(&zs_lock, flags); |
898 | c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, | 896 | c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, |
899 | SERIAL_XMIT_SIZE - info->xmit_head)); | 897 | SERIAL_XMIT_SIZE - info->xmit_head)); |
900 | if (c <= 0) | 898 | if (c <= 0) |
901 | break; | 899 | break; |
902 | 900 | ||
903 | if (from_user) { | 901 | memcpy(info->xmit_buf + info->xmit_head, buf, c); |
904 | down(&tmp_buf_sem); | ||
905 | copy_from_user(tmp_buf, buf, c); | ||
906 | c = min(c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, | ||
907 | SERIAL_XMIT_SIZE - info->xmit_head)); | ||
908 | memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); | ||
909 | up(&tmp_buf_sem); | ||
910 | } else | ||
911 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | ||
912 | info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); | 902 | info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); |
913 | info->xmit_cnt += c; | 903 | info->xmit_cnt += c; |
914 | restore_flags(flags); | 904 | spin_unlock_irqrestore(&zs_lock, flags); |
915 | buf += c; | 905 | buf += c; |
916 | count -= c; | 906 | count -= c; |
917 | total += c; | 907 | total += c; |
@@ -920,7 +910,7 @@ static int rs_write(struct tty_struct * tty, | |||
920 | if (info->xmit_cnt && !tty->stopped && !info->tx_stopped | 910 | if (info->xmit_cnt && !tty->stopped && !info->tx_stopped |
921 | && !info->tx_active) | 911 | && !info->tx_active) |
922 | transmit_chars(info); | 912 | transmit_chars(info); |
923 | restore_flags(flags); | 913 | spin_unlock_irqrestore(&zs_lock, flags); |
924 | return total; | 914 | return total; |
925 | } | 915 | } |
926 | 916 | ||
@@ -952,9 +942,9 @@ static void rs_flush_buffer(struct tty_struct *tty) | |||
952 | 942 | ||
953 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) | 943 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) |
954 | return; | 944 | return; |
955 | cli(); | 945 | spin_lock_irq(&zs_lock); |
956 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 946 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
957 | sti(); | 947 | spin_unlock_irq(&zs_lock); |
958 | tty_wakeup(tty); | 948 | tty_wakeup(tty); |
959 | } | 949 | } |
960 | 950 | ||
@@ -982,11 +972,11 @@ static void rs_throttle(struct tty_struct * tty) | |||
982 | return; | 972 | return; |
983 | 973 | ||
984 | if (I_IXOFF(tty)) { | 974 | if (I_IXOFF(tty)) { |
985 | save_flags(flags); cli(); | 975 | spin_lock_irqsave(&zs_lock, flags); |
986 | info->x_char = STOP_CHAR(tty); | 976 | info->x_char = STOP_CHAR(tty); |
987 | if (!info->tx_active) | 977 | if (!info->tx_active) |
988 | transmit_chars(info); | 978 | transmit_chars(info); |
989 | restore_flags(flags); | 979 | spin_unlock_irqrestore(&zs_lock, flags); |
990 | } | 980 | } |
991 | 981 | ||
992 | if (C_CRTSCTS(tty)) { | 982 | if (C_CRTSCTS(tty)) { |
@@ -1010,7 +1000,7 @@ static void rs_unthrottle(struct tty_struct * tty) | |||
1010 | return; | 1000 | return; |
1011 | 1001 | ||
1012 | if (I_IXOFF(tty)) { | 1002 | if (I_IXOFF(tty)) { |
1013 | save_flags(flags); cli(); | 1003 | spin_lock_irqsave(&zs_lock, flags); |
1014 | if (info->x_char) | 1004 | if (info->x_char) |
1015 | info->x_char = 0; | 1005 | info->x_char = 0; |
1016 | else { | 1006 | else { |
@@ -1018,7 +1008,7 @@ static void rs_unthrottle(struct tty_struct * tty) | |||
1018 | if (!info->tx_active) | 1008 | if (!info->tx_active) |
1019 | transmit_chars(info); | 1009 | transmit_chars(info); |
1020 | } | 1010 | } |
1021 | restore_flags(flags); | 1011 | spin_unlock_irqrestore(&zs_lock, flags); |
1022 | } | 1012 | } |
1023 | 1013 | ||
1024 | if (C_CRTSCTS(tty)) { | 1014 | if (C_CRTSCTS(tty)) { |
@@ -1111,9 +1101,9 @@ static int get_lsr_info(struct dec_serial * info, unsigned int *value) | |||
1111 | { | 1101 | { |
1112 | unsigned char status; | 1102 | unsigned char status; |
1113 | 1103 | ||
1114 | cli(); | 1104 | spin_lock(&zs_lock); |
1115 | status = read_zsreg(info->zs_channel, 0); | 1105 | status = read_zsreg(info->zs_channel, 0); |
1116 | sti(); | 1106 | spin_unlock_irq(&zs_lock); |
1117 | put_user(status,value); | 1107 | put_user(status,value); |
1118 | return 0; | 1108 | return 0; |
1119 | } | 1109 | } |
@@ -1136,11 +1126,11 @@ static int rs_tiocmget(struct tty_struct *tty, struct file *file) | |||
1136 | if (info->zs_channel == info->zs_chan_a) | 1126 | if (info->zs_channel == info->zs_chan_a) |
1137 | result = 0; | 1127 | result = 0; |
1138 | else { | 1128 | else { |
1139 | cli(); | 1129 | spin_lock(&zs_lock); |
1140 | control = info->zs_chan_a->curregs[5]; | 1130 | control = info->zs_chan_a->curregs[5]; |
1141 | status_a = read_zsreg(info->zs_chan_a, 0); | 1131 | status_a = read_zsreg(info->zs_chan_a, 0); |
1142 | status_b = read_zsreg(info->zs_channel, 0); | 1132 | status_b = read_zsreg(info->zs_channel, 0); |
1143 | sti(); | 1133 | spin_unlock_irq(&zs_lock); |
1144 | result = ((control & RTS) ? TIOCM_RTS: 0) | 1134 | result = ((control & RTS) ? TIOCM_RTS: 0) |
1145 | | ((control & DTR) ? TIOCM_DTR: 0) | 1135 | | ((control & DTR) ? TIOCM_DTR: 0) |
1146 | | ((status_b & DCD) ? TIOCM_CAR: 0) | 1136 | | ((status_b & DCD) ? TIOCM_CAR: 0) |
@@ -1155,8 +1145,6 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file, | |||
1155 | unsigned int set, unsigned int clear) | 1145 | unsigned int set, unsigned int clear) |
1156 | { | 1146 | { |
1157 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; | 1147 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; |
1158 | int error; | ||
1159 | unsigned int arg, bits; | ||
1160 | 1148 | ||
1161 | if (info->hook) | 1149 | if (info->hook) |
1162 | return -ENODEV; | 1150 | return -ENODEV; |
@@ -1170,8 +1158,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file, | |||
1170 | if (info->zs_channel == info->zs_chan_a) | 1158 | if (info->zs_channel == info->zs_chan_a) |
1171 | return 0; | 1159 | return 0; |
1172 | 1160 | ||
1173 | get_user(arg, value); | 1161 | spin_lock(&zs_lock); |
1174 | cli(); | ||
1175 | if (set & TIOCM_RTS) | 1162 | if (set & TIOCM_RTS) |
1176 | info->zs_chan_a->curregs[5] |= RTS; | 1163 | info->zs_chan_a->curregs[5] |= RTS; |
1177 | if (set & TIOCM_DTR) | 1164 | if (set & TIOCM_DTR) |
@@ -1181,7 +1168,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file, | |||
1181 | if (clear & TIOCM_DTR) | 1168 | if (clear & TIOCM_DTR) |
1182 | info->zs_chan_a->curregs[5] &= ~DTR; | 1169 | info->zs_chan_a->curregs[5] &= ~DTR; |
1183 | write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); | 1170 | write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); |
1184 | sti(); | 1171 | spin_unlock_irq(&zs_lock); |
1185 | return 0; | 1172 | return 0; |
1186 | } | 1173 | } |
1187 | 1174 | ||
@@ -1198,19 +1185,18 @@ static void rs_break(struct tty_struct *tty, int break_state) | |||
1198 | if (!info->port) | 1185 | if (!info->port) |
1199 | return; | 1186 | return; |
1200 | 1187 | ||
1201 | save_flags(flags); cli(); | 1188 | spin_lock_irqsave(&zs_lock, flags); |
1202 | if (break_state == -1) | 1189 | if (break_state == -1) |
1203 | info->zs_channel->curregs[5] |= SND_BRK; | 1190 | info->zs_channel->curregs[5] |= SND_BRK; |
1204 | else | 1191 | else |
1205 | info->zs_channel->curregs[5] &= ~SND_BRK; | 1192 | info->zs_channel->curregs[5] &= ~SND_BRK; |
1206 | write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); | 1193 | write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); |
1207 | restore_flags(flags); | 1194 | spin_unlock_irqrestore(&zs_lock, flags); |
1208 | } | 1195 | } |
1209 | 1196 | ||
1210 | static int rs_ioctl(struct tty_struct *tty, struct file * file, | 1197 | static int rs_ioctl(struct tty_struct *tty, struct file * file, |
1211 | unsigned int cmd, unsigned long arg) | 1198 | unsigned int cmd, unsigned long arg) |
1212 | { | 1199 | { |
1213 | int error; | ||
1214 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; | 1200 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; |
1215 | 1201 | ||
1216 | if (info->hook) | 1202 | if (info->hook) |
@@ -1287,10 +1273,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
1287 | if (!info || serial_paranoia_check(info, tty->name, "rs_close")) | 1273 | if (!info || serial_paranoia_check(info, tty->name, "rs_close")) |
1288 | return; | 1274 | return; |
1289 | 1275 | ||
1290 | save_flags(flags); cli(); | 1276 | spin_lock_irqsave(&zs_lock, flags); |
1291 | 1277 | ||
1292 | if (tty_hung_up_p(filp)) { | 1278 | if (tty_hung_up_p(filp)) { |
1293 | restore_flags(flags); | 1279 | spin_unlock_irqrestore(&zs_lock, flags); |
1294 | return; | 1280 | return; |
1295 | } | 1281 | } |
1296 | 1282 | ||
@@ -1315,7 +1301,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
1315 | info->count = 0; | 1301 | info->count = 0; |
1316 | } | 1302 | } |
1317 | if (info->count) { | 1303 | if (info->count) { |
1318 | restore_flags(flags); | 1304 | spin_unlock_irqrestore(&zs_lock, flags); |
1319 | return; | 1305 | return; |
1320 | } | 1306 | } |
1321 | info->flags |= ZILOG_CLOSING; | 1307 | info->flags |= ZILOG_CLOSING; |
@@ -1358,7 +1344,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
1358 | } | 1344 | } |
1359 | info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CLOSING); | 1345 | info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CLOSING); |
1360 | wake_up_interruptible(&info->close_wait); | 1346 | wake_up_interruptible(&info->close_wait); |
1361 | restore_flags(flags); | 1347 | spin_unlock_irqrestore(&zs_lock, flags); |
1362 | } | 1348 | } |
1363 | 1349 | ||
1364 | /* | 1350 | /* |
@@ -1398,7 +1384,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1398 | /* | 1384 | /* |
1399 | * rs_hangup() --- called by tty_hangup() when a hangup is signaled. | 1385 | * rs_hangup() --- called by tty_hangup() when a hangup is signaled. |
1400 | */ | 1386 | */ |
1401 | void rs_hangup(struct tty_struct *tty) | 1387 | static void rs_hangup(struct tty_struct *tty) |
1402 | { | 1388 | { |
1403 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; | 1389 | struct dec_serial * info = (struct dec_serial *)tty->driver_data; |
1404 | 1390 | ||
@@ -1466,16 +1452,16 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1466 | printk("block_til_ready before block: ttyS%d, count = %d\n", | 1452 | printk("block_til_ready before block: ttyS%d, count = %d\n", |
1467 | info->line, info->count); | 1453 | info->line, info->count); |
1468 | #endif | 1454 | #endif |
1469 | cli(); | 1455 | spin_lock(&zs_lock); |
1470 | if (!tty_hung_up_p(filp)) | 1456 | if (!tty_hung_up_p(filp)) |
1471 | info->count--; | 1457 | info->count--; |
1472 | sti(); | 1458 | spin_unlock_irq(&zs_lock); |
1473 | info->blocked_open++; | 1459 | info->blocked_open++; |
1474 | while (1) { | 1460 | while (1) { |
1475 | cli(); | 1461 | spin_lock(&zs_lock); |
1476 | if (tty->termios->c_cflag & CBAUD) | 1462 | if (tty->termios->c_cflag & CBAUD) |
1477 | zs_rtsdtr(info, RTS | DTR, 1); | 1463 | zs_rtsdtr(info, RTS | DTR, 1); |
1478 | sti(); | 1464 | spin_unlock_irq(&zs_lock); |
1479 | set_current_state(TASK_INTERRUPTIBLE); | 1465 | set_current_state(TASK_INTERRUPTIBLE); |
1480 | if (tty_hung_up_p(filp) || | 1466 | if (tty_hung_up_p(filp) || |
1481 | !(info->flags & ZILOG_INITIALIZED)) { | 1467 | !(info->flags & ZILOG_INITIALIZED)) { |
@@ -1523,7 +1509,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1523 | * the IRQ chain. It also performs the serial-specific | 1509 | * the IRQ chain. It also performs the serial-specific |
1524 | * initialization for the tty structure. | 1510 | * initialization for the tty structure. |
1525 | */ | 1511 | */ |
1526 | int rs_open(struct tty_struct *tty, struct file * filp) | 1512 | static int rs_open(struct tty_struct *tty, struct file * filp) |
1527 | { | 1513 | { |
1528 | struct dec_serial *info; | 1514 | struct dec_serial *info; |
1529 | int retval, line; | 1515 | int retval, line; |
@@ -1706,7 +1692,7 @@ static void __init probe_sccs(void) | |||
1706 | } | 1692 | } |
1707 | } | 1693 | } |
1708 | 1694 | ||
1709 | save_and_cli(flags); | 1695 | spin_lock_irqsave(&zs_lock, flags); |
1710 | for (n = 0; n < zs_channels_found; n++) { | 1696 | for (n = 0; n < zs_channels_found; n++) { |
1711 | if (n % 2 == 0) { | 1697 | if (n % 2 == 0) { |
1712 | write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES); | 1698 | write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES); |
@@ -1716,7 +1702,7 @@ static void __init probe_sccs(void) | |||
1716 | load_zsregs(zs_soft[n].zs_channel, | 1702 | load_zsregs(zs_soft[n].zs_channel, |
1717 | zs_soft[n].zs_channel->curregs); | 1703 | zs_soft[n].zs_channel->curregs); |
1718 | } | 1704 | } |
1719 | restore_flags(flags); | 1705 | spin_unlock_irqrestore(&zs_lock, flags); |
1720 | } | 1706 | } |
1721 | 1707 | ||
1722 | static struct tty_operations serial_ops = { | 1708 | static struct tty_operations serial_ops = { |
@@ -1749,9 +1735,6 @@ int __init zs_init(void) | |||
1749 | if(!BUS_PRESENT) | 1735 | if(!BUS_PRESENT) |
1750 | return -ENODEV; | 1736 | return -ENODEV; |
1751 | 1737 | ||
1752 | /* Setup base handler, and timer table. */ | ||
1753 | init_bh(SERIAL_BH, do_serial_bh); | ||
1754 | |||
1755 | /* Find out how many Z8530 SCCs we have */ | 1738 | /* Find out how many Z8530 SCCs we have */ |
1756 | if (zs_chain == 0) | 1739 | if (zs_chain == 0) |
1757 | probe_sccs(); | 1740 | probe_sccs(); |
@@ -1800,8 +1783,7 @@ int __init zs_init(void) | |||
1800 | info->event = 0; | 1783 | info->event = 0; |
1801 | info->count = 0; | 1784 | info->count = 0; |
1802 | info->blocked_open = 0; | 1785 | info->blocked_open = 0; |
1803 | info->tqueue.routine = do_softint; | 1786 | tasklet_init(&info->tlet, do_softint, (unsigned long)info); |
1804 | info->tqueue.data = info; | ||
1805 | init_waitqueue_head(&info->open_wait); | 1787 | init_waitqueue_head(&info->open_wait); |
1806 | init_waitqueue_head(&info->close_wait); | 1788 | init_waitqueue_head(&info->close_wait); |
1807 | printk("ttyS%02d at 0x%08x (irq = %d) is a Z85C30 SCC\n", | 1789 | printk("ttyS%02d at 0x%08x (irq = %d) is a Z85C30 SCC\n", |
@@ -1833,8 +1815,7 @@ int __init zs_init(void) | |||
1833 | /* | 1815 | /* |
1834 | * polling I/O routines | 1816 | * polling I/O routines |
1835 | */ | 1817 | */ |
1836 | static int | 1818 | static int zs_poll_tx_char(void *handle, unsigned char ch) |
1837 | zs_poll_tx_char(void *handle, unsigned char ch) | ||
1838 | { | 1819 | { |
1839 | struct dec_serial *info = handle; | 1820 | struct dec_serial *info = handle; |
1840 | struct dec_zschannel *chan = info->zs_channel; | 1821 | struct dec_zschannel *chan = info->zs_channel; |
@@ -1857,8 +1838,7 @@ zs_poll_tx_char(void *handle, unsigned char ch) | |||
1857 | return -ENODEV; | 1838 | return -ENODEV; |
1858 | } | 1839 | } |
1859 | 1840 | ||
1860 | static int | 1841 | static int zs_poll_rx_char(void *handle) |
1861 | zs_poll_rx_char(void *handle) | ||
1862 | { | 1842 | { |
1863 | struct dec_serial *info = handle; | 1843 | struct dec_serial *info = handle; |
1864 | struct dec_zschannel *chan = info->zs_channel; | 1844 | struct dec_zschannel *chan = info->zs_channel; |
@@ -2037,7 +2017,7 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
2037 | } | 2017 | } |
2038 | co->cflag = cflag; | 2018 | co->cflag = cflag; |
2039 | 2019 | ||
2040 | save_and_cli(flags); | 2020 | spin_lock_irqsave(&zs_lock, flags); |
2041 | 2021 | ||
2042 | /* | 2022 | /* |
2043 | * Set up the baud rate generator. | 2023 | * Set up the baud rate generator. |
@@ -2092,7 +2072,7 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
2092 | zs_soft[co->index].clk_divisor = clk_divisor; | 2072 | zs_soft[co->index].clk_divisor = clk_divisor; |
2093 | zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]); | 2073 | zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]); |
2094 | 2074 | ||
2095 | restore_flags(flags); | 2075 | spin_unlock_irqrestore(&zs_lock, flags); |
2096 | 2076 | ||
2097 | return 0; | 2077 | return 0; |
2098 | } | 2078 | } |
@@ -2229,5 +2209,3 @@ void __init zs_kgdb_hook(int tty_num) | |||
2229 | set_debug_traps(); /* init stub */ | 2209 | set_debug_traps(); /* init stub */ |
2230 | } | 2210 | } |
2231 | #endif /* ifdef CONFIG_KGDB */ | 2211 | #endif /* ifdef CONFIG_KGDB */ |
2232 | |||
2233 | |||
diff --git a/drivers/tc/zs.h b/drivers/tc/zs.h index c52edffa6049..13512200ceba 100644 --- a/drivers/tc/zs.h +++ b/drivers/tc/zs.h | |||
@@ -6,14 +6,14 @@ | |||
6 | * | 6 | * |
7 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) | 7 | * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) |
8 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | 8 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) |
9 | * Copyright (C) 2004 Maciej W. Rozycki | 9 | * Copyright (C) 2004, 2005 Maciej W. Rozycki |
10 | */ | 10 | */ |
11 | #ifndef _DECSERIAL_H | 11 | #ifndef _DECSERIAL_H |
12 | #define _DECSERIAL_H | 12 | #define _DECSERIAL_H |
13 | 13 | ||
14 | #include <asm/dec/serial.h> | 14 | #include <asm/dec/serial.h> |
15 | 15 | ||
16 | #define NUM_ZSREGS 16 | 16 | #define NUM_ZSREGS 16 |
17 | 17 | ||
18 | struct serial_struct { | 18 | struct serial_struct { |
19 | int type; | 19 | int type; |
@@ -139,8 +139,7 @@ struct dec_serial { | |||
139 | int xmit_head; | 139 | int xmit_head; |
140 | int xmit_tail; | 140 | int xmit_tail; |
141 | int xmit_cnt; | 141 | int xmit_cnt; |
142 | struct tq_struct tqueue; | 142 | struct tasklet_struct tlet; |
143 | struct tq_struct tqueue_hangup; | ||
144 | wait_queue_head_t open_wait; | 143 | wait_queue_head_t open_wait; |
145 | wait_queue_head_t close_wait; | 144 | wait_queue_head_t close_wait; |
146 | }; | 145 | }; |
@@ -282,7 +281,7 @@ struct dec_serial { | |||
282 | #define DLC 4 /* Disable Lower Chain */ | 281 | #define DLC 4 /* Disable Lower Chain */ |
283 | #define MIE 8 /* Master Interrupt Enable */ | 282 | #define MIE 8 /* Master Interrupt Enable */ |
284 | #define STATHI 0x10 /* Status high */ | 283 | #define STATHI 0x10 /* Status high */ |
285 | #define SOFTACK 0x20 /* Software Interrupt Acknowledge */ | 284 | #define SOFTACK 0x20 /* Software Interrupt Acknowledge */ |
286 | #define NORESET 0 /* No reset on write to R9 */ | 285 | #define NORESET 0 /* No reset on write to R9 */ |
287 | #define CHRB 0x40 /* Reset channel B */ | 286 | #define CHRB 0x40 /* Reset channel B */ |
288 | #define CHRA 0x80 /* Reset channel A */ | 287 | #define CHRA 0x80 /* Reset channel A */ |
@@ -395,8 +394,8 @@ struct dec_serial { | |||
395 | /* Read Register 15 (value of WR 15) */ | 394 | /* Read Register 15 (value of WR 15) */ |
396 | 395 | ||
397 | /* Misc macros */ | 396 | /* Misc macros */ |
398 | #define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES)) | 397 | #define ZS_CLEARERR(channel) (write_zsreg(channel, 0, ERR_RES)) |
399 | #define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ | 398 | #define ZS_CLEARFIFO(channel) do { volatile unsigned char garbage; \ |
400 | garbage = read_zsdata(channel); \ | 399 | garbage = read_zsdata(channel); \ |
401 | garbage = read_zsdata(channel); \ | 400 | garbage = read_zsdata(channel); \ |
402 | garbage = read_zsdata(channel); \ | 401 | garbage = read_zsdata(channel); \ |
diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile index 751f297be2ef..85099718c683 100644 --- a/drivers/usb/atm/Makefile +++ b/drivers/usb/atm/Makefile | |||
@@ -6,3 +6,7 @@ obj-$(CONFIG_USB_CXACRU) += cxacru.o | |||
6 | obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o | 6 | obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o |
7 | obj-$(CONFIG_USB_ATM) += usbatm.o | 7 | obj-$(CONFIG_USB_ATM) += usbatm.o |
8 | obj-$(CONFIG_USB_XUSBATM) += xusbatm.o | 8 | obj-$(CONFIG_USB_XUSBATM) += xusbatm.o |
9 | |||
10 | ifeq ($(CONFIG_USB_DEBUG),y) | ||
11 | EXTRA_CFLAGS += -DDEBUG | ||
12 | endif | ||
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h index 936646457935..1adacd60d713 100644 --- a/drivers/usb/atm/usbatm.h +++ b/drivers/usb/atm/usbatm.h | |||
@@ -27,14 +27,9 @@ | |||
27 | #include <linux/config.h> | 27 | #include <linux/config.h> |
28 | 28 | ||
29 | /* | 29 | /* |
30 | #define DEBUG | ||
31 | #define VERBOSE_DEBUG | 30 | #define VERBOSE_DEBUG |
32 | */ | 31 | */ |
33 | 32 | ||
34 | #if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) | ||
35 | # define DEBUG | ||
36 | #endif | ||
37 | |||
38 | #include <asm/semaphore.h> | 33 | #include <asm/semaphore.h> |
39 | #include <linux/atm.h> | 34 | #include <linux/atm.h> |
40 | #include <linux/atmdev.h> | 35 | #include <linux/atmdev.h> |
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index dd1c4d2a0c31..86d5c380892d 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile | |||
@@ -14,3 +14,7 @@ ifeq ($(CONFIG_USB_DEVICEFS),y) | |||
14 | endif | 14 | endif |
15 | 15 | ||
16 | obj-$(CONFIG_USB) += usbcore.o | 16 | obj-$(CONFIG_USB) += usbcore.o |
17 | |||
18 | ifeq ($(CONFIG_USB_DEBUG),y) | ||
19 | EXTRA_CFLAGS += -DDEBUG | ||
20 | endif | ||
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 57e800ac3cee..419c9943a7cb 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c | |||
@@ -15,14 +15,6 @@ | |||
15 | #include <asm/scatterlist.h> | 15 | #include <asm/scatterlist.h> |
16 | #include <linux/dma-mapping.h> | 16 | #include <linux/dma-mapping.h> |
17 | #include <linux/dmapool.h> | 17 | #include <linux/dmapool.h> |
18 | |||
19 | |||
20 | #ifdef CONFIG_USB_DEBUG | ||
21 | #define DEBUG | ||
22 | #else | ||
23 | #undef DEBUG | ||
24 | #endif | ||
25 | |||
26 | #include <linux/usb.h> | 18 | #include <linux/usb.h> |
27 | #include "hcd.h" | 19 | #include "hcd.h" |
28 | 20 | ||
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 993019500cc3..a9d89c78cc20 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c | |||
@@ -1,9 +1,4 @@ | |||
1 | #include <linux/config.h> | 1 | #include <linux/config.h> |
2 | |||
3 | #ifdef CONFIG_USB_DEBUG | ||
4 | #define DEBUG | ||
5 | #endif | ||
6 | |||
7 | #include <linux/usb.h> | 2 | #include <linux/usb.h> |
8 | #include <linux/module.h> | 3 | #include <linux/module.h> |
9 | #include <linux/init.h> | 4 | #include <linux/init.h> |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 942cd437dc48..b1d6e9af732d 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -1392,13 +1392,13 @@ static int proc_ioctl_default(struct dev_state *ps, void __user *arg) | |||
1392 | } | 1392 | } |
1393 | 1393 | ||
1394 | #ifdef CONFIG_COMPAT | 1394 | #ifdef CONFIG_COMPAT |
1395 | static int proc_ioctl_compat(struct dev_state *ps, void __user *arg) | 1395 | static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg) |
1396 | { | 1396 | { |
1397 | struct usbdevfs_ioctl32 __user *uioc; | 1397 | struct usbdevfs_ioctl32 __user *uioc; |
1398 | struct usbdevfs_ioctl ctrl; | 1398 | struct usbdevfs_ioctl ctrl; |
1399 | u32 udata; | 1399 | u32 udata; |
1400 | 1400 | ||
1401 | uioc = compat_ptr(arg); | 1401 | uioc = compat_ptr((long)arg); |
1402 | if (get_user(ctrl.ifno, &uioc->ifno) || | 1402 | if (get_user(ctrl.ifno, &uioc->ifno) || |
1403 | get_user(ctrl.ioctl_code, &uioc->ioctl_code) || | 1403 | get_user(ctrl.ioctl_code, &uioc->ioctl_code) || |
1404 | __get_user(udata, &uioc->data)) | 1404 | __get_user(udata, &uioc->data)) |
@@ -1511,7 +1511,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
1511 | 1511 | ||
1512 | case USBDEVFS_IOCTL32: | 1512 | case USBDEVFS_IOCTL32: |
1513 | snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__); | 1513 | snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__); |
1514 | ret = proc_ioctl_compat(ps, p); | 1514 | ret = proc_ioctl_compat(ps, (compat_uptr_t)(long)p); |
1515 | break; | 1515 | break; |
1516 | #endif | 1516 | #endif |
1517 | 1517 | ||
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index e695308095ae..37b13368c814 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c | |||
@@ -19,12 +19,6 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
21 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
22 | |||
23 | #ifdef CONFIG_USB_DEBUG | ||
24 | #define DEBUG | ||
25 | #else | ||
26 | #undef DEBUG | ||
27 | #endif | ||
28 | #include <linux/usb.h> | 22 | #include <linux/usb.h> |
29 | 23 | ||
30 | #include "usb.h" | 24 | #include "usb.h" |
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 84d9e69329bb..7feb829362d6 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -17,13 +17,6 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/config.h> | 19 | #include <linux/config.h> |
20 | |||
21 | #ifdef CONFIG_USB_DEBUG | ||
22 | #define DEBUG | ||
23 | #else | ||
24 | #undef DEBUG | ||
25 | #endif | ||
26 | |||
27 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
28 | #include <linux/module.h> | 21 | #include <linux/module.h> |
29 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6c7ca5b08cd6..5e5f65a475ab 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -23,11 +23,6 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/config.h> | 25 | #include <linux/config.h> |
26 | |||
27 | #ifdef CONFIG_USB_DEBUG | ||
28 | #define DEBUG | ||
29 | #endif | ||
30 | |||
31 | #include <linux/module.h> | 26 | #include <linux/module.h> |
32 | #include <linux/version.h> | 27 | #include <linux/version.h> |
33 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 256d9f698715..840727948d84 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -9,11 +9,6 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/config.h> | 11 | #include <linux/config.h> |
12 | #ifdef CONFIG_USB_DEBUG | ||
13 | #define DEBUG | ||
14 | #else | ||
15 | #undef DEBUG | ||
16 | #endif | ||
17 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
18 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
19 | #include <linux/module.h> | 14 | #include <linux/module.h> |
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 12f490fdee8f..c44bbedec817 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
@@ -46,7 +46,6 @@ | |||
46 | 46 | ||
47 | static struct super_operations usbfs_ops; | 47 | static struct super_operations usbfs_ops; |
48 | static struct file_operations default_file_operations; | 48 | static struct file_operations default_file_operations; |
49 | static struct inode_operations usbfs_dir_inode_operations; | ||
50 | static struct vfsmount *usbfs_mount; | 49 | static struct vfsmount *usbfs_mount; |
51 | static int usbfs_mount_count; /* = 0 */ | 50 | static int usbfs_mount_count; /* = 0 */ |
52 | static int ignore_mount = 0; | 51 | static int ignore_mount = 0; |
@@ -262,7 +261,7 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de | |||
262 | inode->i_fop = &default_file_operations; | 261 | inode->i_fop = &default_file_operations; |
263 | break; | 262 | break; |
264 | case S_IFDIR: | 263 | case S_IFDIR: |
265 | inode->i_op = &usbfs_dir_inode_operations; | 264 | inode->i_op = &simple_dir_inode_operations; |
266 | inode->i_fop = &simple_dir_operations; | 265 | inode->i_fop = &simple_dir_operations; |
267 | 266 | ||
268 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | 267 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ |
@@ -417,10 +416,6 @@ static struct file_operations default_file_operations = { | |||
417 | .llseek = default_file_lseek, | 416 | .llseek = default_file_lseek, |
418 | }; | 417 | }; |
419 | 418 | ||
420 | static struct inode_operations usbfs_dir_inode_operations = { | ||
421 | .lookup = simple_lookup, | ||
422 | }; | ||
423 | |||
424 | static struct super_operations usbfs_ops = { | 419 | static struct super_operations usbfs_ops = { |
425 | .statfs = simple_statfs, | 420 | .statfs = simple_statfs, |
426 | .drop_inode = generic_delete_inode, | 421 | .drop_inode = generic_delete_inode, |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 644a3d4f12aa..fe74f99ca5f4 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -3,13 +3,6 @@ | |||
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/config.h> | 5 | #include <linux/config.h> |
6 | |||
7 | #ifdef CONFIG_USB_DEBUG | ||
8 | #define DEBUG | ||
9 | #else | ||
10 | #undef DEBUG | ||
11 | #endif | ||
12 | |||
13 | #include <linux/pci.h> /* for scatterlist macros */ | 6 | #include <linux/pci.h> /* for scatterlist macros */ |
14 | #include <linux/usb.h> | 7 | #include <linux/usb.h> |
15 | #include <linux/module.h> | 8 | #include <linux/module.h> |
@@ -1457,12 +1450,11 @@ free_interfaces: | |||
1457 | */ | 1450 | */ |
1458 | for (i = 0; i < nintf; ++i) { | 1451 | for (i = 0; i < nintf; ++i) { |
1459 | struct usb_interface *intf = cp->interface[i]; | 1452 | struct usb_interface *intf = cp->interface[i]; |
1460 | struct usb_host_interface *alt = intf->cur_altsetting; | ||
1461 | 1453 | ||
1462 | dev_dbg (&dev->dev, | 1454 | dev_dbg (&dev->dev, |
1463 | "adding %s (config #%d, interface %d)\n", | 1455 | "adding %s (config #%d, interface %d)\n", |
1464 | intf->dev.bus_id, configuration, | 1456 | intf->dev.bus_id, configuration, |
1465 | alt->desc.bInterfaceNumber); | 1457 | intf->cur_altsetting->desc.bInterfaceNumber); |
1466 | ret = device_add (&intf->dev); | 1458 | ret = device_add (&intf->dev); |
1467 | if (ret != 0) { | 1459 | if (ret != 0) { |
1468 | dev_err(&dev->dev, | 1460 | dev_err(&dev->dev, |
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index 37da059eced7..fbbebab52fbd 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c | |||
@@ -12,13 +12,7 @@ | |||
12 | #include <linux/config.h> | 12 | #include <linux/config.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/notifier.h> | 14 | #include <linux/notifier.h> |
15 | #ifdef CONFIG_USB_DEBUG | ||
16 | #define DEBUG | ||
17 | #else | ||
18 | #undef DEBUG | ||
19 | #endif | ||
20 | #include <linux/usb.h> | 15 | #include <linux/usb.h> |
21 | |||
22 | #include "usb.h" | 16 | #include "usb.h" |
23 | 17 | ||
24 | 18 | ||
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index edd83e014452..71d881327e88 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -12,14 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/config.h> | 13 | #include <linux/config.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | |||
16 | #ifdef CONFIG_USB_DEBUG | ||
17 | #define DEBUG | ||
18 | #else | ||
19 | #undef DEBUG | ||
20 | #endif | ||
21 | #include <linux/usb.h> | 15 | #include <linux/usb.h> |
22 | |||
23 | #include "usb.h" | 16 | #include "usb.h" |
24 | 17 | ||
25 | /* endpoint stuff */ | 18 | /* endpoint stuff */ |
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index f2a1fed2a802..081796726b95 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
@@ -4,12 +4,6 @@ | |||
4 | #include <linux/bitops.h> | 4 | #include <linux/bitops.h> |
5 | #include <linux/slab.h> | 5 | #include <linux/slab.h> |
6 | #include <linux/init.h> | 6 | #include <linux/init.h> |
7 | |||
8 | #ifdef CONFIG_USB_DEBUG | ||
9 | #define DEBUG | ||
10 | #else | ||
11 | #undef DEBUG | ||
12 | #endif | ||
13 | #include <linux/usb.h> | 7 | #include <linux/usb.h> |
14 | #include "hcd.h" | 8 | #include "hcd.h" |
15 | 9 | ||
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 0eefff7bcb3c..e197ce9353de 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -22,13 +22,6 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/config.h> | 24 | #include <linux/config.h> |
25 | |||
26 | #ifdef CONFIG_USB_DEBUG | ||
27 | #define DEBUG | ||
28 | #else | ||
29 | #undef DEBUG | ||
30 | #endif | ||
31 | |||
32 | #include <linux/module.h> | 25 | #include <linux/module.h> |
33 | #include <linux/string.h> | 26 | #include <linux/string.h> |
34 | #include <linux/bitops.h> | 27 | #include <linux/bitops.h> |
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 1e407745c115..c655d46c8aed 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -944,7 +944,7 @@ static int dummy_udc_suspend (struct platform_device *dev, pm_message_t state) | |||
944 | set_link_state (dum); | 944 | set_link_state (dum); |
945 | spin_unlock_irq (&dum->lock); | 945 | spin_unlock_irq (&dum->lock); |
946 | 946 | ||
947 | dev->power.power_state = state; | 947 | dev->dev.power.power_state = state; |
948 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | 948 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); |
949 | return 0; | 949 | return 0; |
950 | } | 950 | } |
@@ -1904,7 +1904,7 @@ static int dummy_hcd_probe (struct platform_device *dev) | |||
1904 | struct usb_hcd *hcd; | 1904 | struct usb_hcd *hcd; |
1905 | int retval; | 1905 | int retval; |
1906 | 1906 | ||
1907 | dev_info (dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); | 1907 | dev_info(&dev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); |
1908 | 1908 | ||
1909 | hcd = usb_create_hcd (&dummy_hcd, &dev->dev, dev->dev.bus_id); | 1909 | hcd = usb_create_hcd (&dummy_hcd, &dev->dev, dev->dev.bus_id); |
1910 | if (!hcd) | 1910 | if (!hcd) |
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 081ec3f5cff4..3959ccc88332 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c | |||
@@ -219,7 +219,7 @@ static int ohci_hcd_lh7a404_drv_probe(struct platform_device *pdev) | |||
219 | 219 | ||
220 | static int ohci_hcd_lh7a404_drv_remove(struct platform_device *pdev) | 220 | static int ohci_hcd_lh7a404_drv_remove(struct platform_device *pdev) |
221 | { | 221 | { |
222 | struct usb_hcd *hcd = platform_get_drvdata(dev); | 222 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
223 | 223 | ||
224 | usb_hcd_lh7a404_remove(hcd, pdev); | 224 | usb_hcd_lh7a404_remove(hcd, pdev); |
225 | return 0; | 225 | return 0; |
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index 18755766e406..2ec6a78bd65e 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c | |||
@@ -185,7 +185,7 @@ static int ohci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) | |||
185 | 185 | ||
186 | static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev) | 186 | static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev) |
187 | { | 187 | { |
188 | struct usb_hcd *hcd = platform_get_drvdata(dev); | 188 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
189 | 189 | ||
190 | usb_hcd_ppc_soc_remove(hcd, pdev); | 190 | usb_hcd_ppc_soc_remove(hcd, pdev); |
191 | return 0; | 191 | return 0; |
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 61a2604cce4f..950543aa5ac7 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c | |||
@@ -327,6 +327,18 @@ static inline void mts_urb_abort(struct mts_desc* desc) { | |||
327 | usb_kill_urb( desc->urb ); | 327 | usb_kill_urb( desc->urb ); |
328 | } | 328 | } |
329 | 329 | ||
330 | static int mts_slave_alloc (struct scsi_device *s) | ||
331 | { | ||
332 | s->inquiry_len = 0x24; | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int mts_slave_configure (struct scsi_device *s) | ||
337 | { | ||
338 | blk_queue_dma_alignment(s->request_queue, (512 - 1)); | ||
339 | return 0; | ||
340 | } | ||
341 | |||
330 | static int mts_scsi_abort (Scsi_Cmnd *srb) | 342 | static int mts_scsi_abort (Scsi_Cmnd *srb) |
331 | { | 343 | { |
332 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); | 344 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); |
@@ -411,7 +423,7 @@ static void mts_transfer_done( struct urb *transfer, struct pt_regs *regs ) | |||
411 | MTS_INT_INIT(); | 423 | MTS_INT_INIT(); |
412 | 424 | ||
413 | context->srb->result &= MTS_SCSI_ERR_MASK; | 425 | context->srb->result &= MTS_SCSI_ERR_MASK; |
414 | context->srb->result |= (unsigned)context->status<<1; | 426 | context->srb->result |= (unsigned)(*context->scsi_status)<<1; |
415 | 427 | ||
416 | mts_transfer_cleanup(transfer); | 428 | mts_transfer_cleanup(transfer); |
417 | 429 | ||
@@ -427,7 +439,7 @@ static void mts_get_status( struct urb *transfer ) | |||
427 | mts_int_submit_urb(transfer, | 439 | mts_int_submit_urb(transfer, |
428 | usb_rcvbulkpipe(context->instance->usb_dev, | 440 | usb_rcvbulkpipe(context->instance->usb_dev, |
429 | context->instance->ep_response), | 441 | context->instance->ep_response), |
430 | &context->status, | 442 | context->scsi_status, |
431 | 1, | 443 | 1, |
432 | mts_transfer_done ); | 444 | mts_transfer_done ); |
433 | } | 445 | } |
@@ -481,7 +493,7 @@ static void mts_command_done( struct urb *transfer, struct pt_regs *regs ) | |||
481 | context->data_pipe, | 493 | context->data_pipe, |
482 | context->data, | 494 | context->data, |
483 | context->data_length, | 495 | context->data_length, |
484 | context->srb->use_sg ? mts_do_sg : mts_data_done); | 496 | context->srb->use_sg > 1 ? mts_do_sg : mts_data_done); |
485 | } else { | 497 | } else { |
486 | mts_get_status(transfer); | 498 | mts_get_status(transfer); |
487 | } | 499 | } |
@@ -627,7 +639,6 @@ int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ) | |||
627 | callback(srb); | 639 | callback(srb); |
628 | 640 | ||
629 | } | 641 | } |
630 | |||
631 | out: | 642 | out: |
632 | return err; | 643 | return err; |
633 | } | 644 | } |
@@ -645,6 +656,9 @@ static struct scsi_host_template mts_scsi_host_template = { | |||
645 | .cmd_per_lun = 1, | 656 | .cmd_per_lun = 1, |
646 | .use_clustering = 1, | 657 | .use_clustering = 1, |
647 | .emulated = 1, | 658 | .emulated = 1, |
659 | .slave_alloc = mts_slave_alloc, | ||
660 | .slave_configure = mts_slave_configure, | ||
661 | .max_sectors= 256, /* 128 K */ | ||
648 | }; | 662 | }; |
649 | 663 | ||
650 | struct vendor_product | 664 | struct vendor_product |
@@ -771,8 +785,8 @@ static int mts_usb_probe(struct usb_interface *intf, | |||
771 | MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" ); | 785 | MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" ); |
772 | return -ENODEV; | 786 | return -ENODEV; |
773 | } | 787 | } |
774 | 788 | ||
775 | 789 | ||
776 | new_desc = kzalloc(sizeof(struct mts_desc), GFP_KERNEL); | 790 | new_desc = kzalloc(sizeof(struct mts_desc), GFP_KERNEL); |
777 | if (!new_desc) | 791 | if (!new_desc) |
778 | goto out; | 792 | goto out; |
@@ -781,6 +795,10 @@ static int mts_usb_probe(struct usb_interface *intf, | |||
781 | if (!new_desc->urb) | 795 | if (!new_desc->urb) |
782 | goto out_kfree; | 796 | goto out_kfree; |
783 | 797 | ||
798 | new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL); | ||
799 | if (!new_desc->context.scsi_status) | ||
800 | goto out_kfree2; | ||
801 | |||
784 | new_desc->usb_dev = dev; | 802 | new_desc->usb_dev = dev; |
785 | new_desc->usb_intf = intf; | 803 | new_desc->usb_intf = intf; |
786 | init_MUTEX(&new_desc->lock); | 804 | init_MUTEX(&new_desc->lock); |
@@ -817,6 +835,8 @@ static int mts_usb_probe(struct usb_interface *intf, | |||
817 | usb_set_intfdata(intf, new_desc); | 835 | usb_set_intfdata(intf, new_desc); |
818 | return 0; | 836 | return 0; |
819 | 837 | ||
838 | out_kfree2: | ||
839 | kfree(new_desc->context.scsi_status); | ||
820 | out_free_urb: | 840 | out_free_urb: |
821 | usb_free_urb(new_desc->urb); | 841 | usb_free_urb(new_desc->urb); |
822 | out_kfree: | 842 | out_kfree: |
@@ -836,6 +856,7 @@ static void mts_usb_disconnect (struct usb_interface *intf) | |||
836 | 856 | ||
837 | scsi_host_put(desc->host); | 857 | scsi_host_put(desc->host); |
838 | usb_free_urb(desc->urb); | 858 | usb_free_urb(desc->urb); |
859 | kfree(desc->context.scsi_status); | ||
839 | kfree(desc); | 860 | kfree(desc); |
840 | } | 861 | } |
841 | 862 | ||
@@ -856,5 +877,3 @@ module_exit(microtek_drv_exit); | |||
856 | MODULE_AUTHOR( DRIVER_AUTHOR ); | 877 | MODULE_AUTHOR( DRIVER_AUTHOR ); |
857 | MODULE_DESCRIPTION( DRIVER_DESC ); | 878 | MODULE_DESCRIPTION( DRIVER_DESC ); |
858 | MODULE_LICENSE("GPL"); | 879 | MODULE_LICENSE("GPL"); |
859 | |||
860 | |||
diff --git a/drivers/usb/image/microtek.h b/drivers/usb/image/microtek.h index 3271deb8c001..926d4bdc6746 100644 --- a/drivers/usb/image/microtek.h +++ b/drivers/usb/image/microtek.h | |||
@@ -22,7 +22,7 @@ struct mts_transfer_context | |||
22 | int data_pipe; | 22 | int data_pipe; |
23 | int fragment; | 23 | int fragment; |
24 | 24 | ||
25 | u8 status; /* status returned from ep_response after command completion */ | 25 | u8 *scsi_status; /* status returned from ep_response after command completion */ |
26 | }; | 26 | }; |
27 | 27 | ||
28 | 28 | ||
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 5e03b93f29f6..07cb17db42fc 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile | |||
@@ -42,3 +42,7 @@ obj-$(CONFIG_USB_ACECAD) += acecad.o | |||
42 | obj-$(CONFIG_USB_YEALINK) += yealink.o | 42 | obj-$(CONFIG_USB_YEALINK) += yealink.o |
43 | obj-$(CONFIG_USB_XPAD) += xpad.o | 43 | obj-$(CONFIG_USB_XPAD) += xpad.o |
44 | obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o | 44 | obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o |
45 | |||
46 | ifeq ($(CONFIG_USB_DEBUG),y) | ||
47 | EXTRA_CFLAGS += -DDEBUG | ||
48 | endif | ||
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 79ddce4555ab..45f3130fadea 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -1318,6 +1318,7 @@ void hid_init_reports(struct hid_device *hid) | |||
1318 | #define USB_DEVICE_ID_WACOM_PTU 0x0003 | 1318 | #define USB_DEVICE_ID_WACOM_PTU 0x0003 |
1319 | #define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0 | 1319 | #define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0 |
1320 | #define USB_DEVICE_ID_WACOM_CINTIQ 0x003F | 1320 | #define USB_DEVICE_ID_WACOM_CINTIQ 0x003F |
1321 | #define USB_DEVICE_ID_WACOM_DTF 0x00C0 | ||
1321 | 1322 | ||
1322 | #define USB_VENDOR_ID_ACECAD 0x0460 | 1323 | #define USB_VENDOR_ID_ACECAD 0x0460 |
1323 | #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 | 1324 | #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 |
@@ -1524,6 +1525,9 @@ static struct hid_blacklist { | |||
1524 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 3, HID_QUIRK_IGNORE }, | 1525 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 3, HID_QUIRK_IGNORE }, |
1525 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 4, HID_QUIRK_IGNORE }, | 1526 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 4, HID_QUIRK_IGNORE }, |
1526 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 5, HID_QUIRK_IGNORE }, | 1527 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 5, HID_QUIRK_IGNORE }, |
1528 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 7, HID_QUIRK_IGNORE }, | ||
1529 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 8, HID_QUIRK_IGNORE }, | ||
1530 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 9, HID_QUIRK_IGNORE }, | ||
1527 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 1, HID_QUIRK_IGNORE }, | 1531 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 1, HID_QUIRK_IGNORE }, |
1528 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE }, | 1532 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE }, |
1529 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE }, | 1533 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE }, |
@@ -1531,11 +1535,19 @@ static struct hid_blacklist { | |||
1531 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, HID_QUIRK_IGNORE }, | 1535 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, HID_QUIRK_IGNORE }, |
1532 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE }, | 1536 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE }, |
1533 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE }, | 1537 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE }, |
1538 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 1, HID_QUIRK_IGNORE }, | ||
1539 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 2, HID_QUIRK_IGNORE }, | ||
1540 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 3, HID_QUIRK_IGNORE }, | ||
1541 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 4, HID_QUIRK_IGNORE }, | ||
1542 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 5, HID_QUIRK_IGNORE }, | ||
1543 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 6, HID_QUIRK_IGNORE }, | ||
1534 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE }, | 1544 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE }, |
1535 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3, HID_QUIRK_IGNORE }, | 1545 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3, HID_QUIRK_IGNORE }, |
1536 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 1, HID_QUIRK_IGNORE }, | 1546 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 1, HID_QUIRK_IGNORE }, |
1537 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 2, HID_QUIRK_IGNORE }, | 1547 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 2, HID_QUIRK_IGNORE }, |
1548 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 5, HID_QUIRK_IGNORE }, | ||
1538 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_CINTIQ, HID_QUIRK_IGNORE }, | 1549 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_CINTIQ, HID_QUIRK_IGNORE }, |
1550 | { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF, HID_QUIRK_IGNORE }, | ||
1539 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | 1551 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, |
1540 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | 1552 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, |
1541 | 1553 | ||
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c index 3b581853cf10..4a50acb39d29 100644 --- a/drivers/usb/input/itmtouch.c +++ b/drivers/usb/input/itmtouch.c | |||
@@ -40,13 +40,6 @@ | |||
40 | *****************************************************************************/ | 40 | *****************************************************************************/ |
41 | 41 | ||
42 | #include <linux/config.h> | 42 | #include <linux/config.h> |
43 | |||
44 | #ifdef CONFIG_USB_DEBUG | ||
45 | #define DEBUG | ||
46 | #else | ||
47 | #undef DEBUG | ||
48 | #endif | ||
49 | |||
50 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
51 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
52 | #include <linux/input.h> | 45 | #include <linux/input.h> |
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c index 5b8d65f62abf..a32cfe51b77d 100644 --- a/drivers/usb/input/keyspan_remote.c +++ b/drivers/usb/input/keyspan_remote.c | |||
@@ -160,7 +160,8 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) | |||
160 | * though so it's not too big a deal | 160 | * though so it's not too big a deal |
161 | */ | 161 | */ |
162 | if (dev->data.pos >= dev->data.len) { | 162 | if (dev->data.pos >= dev->data.len) { |
163 | dev_dbg(&dev->udev, "%s - Error ran out of data. pos: %d, len: %d\n", | 163 | dev_dbg(&dev->udev->dev, |
164 | "%s - Error ran out of data. pos: %d, len: %d\n", | ||
164 | __FUNCTION__, dev->data.pos, dev->data.len); | 165 | __FUNCTION__, dev->data.pos, dev->data.len); |
165 | return -1; | 166 | return -1; |
166 | } | 167 | } |
@@ -306,7 +307,7 @@ static void keyspan_check_data(struct usb_keyspan *remote, struct pt_regs *regs) | |||
306 | err("Bad message recieved, no stop bit found.\n"); | 307 | err("Bad message recieved, no stop bit found.\n"); |
307 | } | 308 | } |
308 | 309 | ||
309 | dev_dbg(&remote->udev, | 310 | dev_dbg(&remote->udev->dev, |
310 | "%s found valid message: system: %d, button: %d, toggle: %d\n", | 311 | "%s found valid message: system: %d, button: %d, toggle: %d\n", |
311 | __FUNCTION__, message.system, message.button, message.toggle); | 312 | __FUNCTION__, message.system, message.button, message.toggle); |
312 | 313 | ||
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index 7fce526560ca..52cc18cd247d 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c | |||
@@ -40,13 +40,6 @@ | |||
40 | *****************************************************************************/ | 40 | *****************************************************************************/ |
41 | 41 | ||
42 | #include <linux/config.h> | 42 | #include <linux/config.h> |
43 | |||
44 | #ifdef CONFIG_USB_DEBUG | ||
45 | #define DEBUG | ||
46 | #else | ||
47 | #undef DEBUG | ||
48 | #endif | ||
49 | |||
50 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
51 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
52 | #include <linux/input.h> | 45 | #include <linux/input.h> |
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c index dca5ee93a4ef..19e015d171aa 100644 --- a/drivers/usb/input/pid.c +++ b/drivers/usb/input/pid.c | |||
@@ -37,8 +37,6 @@ | |||
37 | #include "hid.h" | 37 | #include "hid.h" |
38 | #include "pid.h" | 38 | #include "pid.h" |
39 | 39 | ||
40 | #define DEBUG | ||
41 | |||
42 | #define CHECK_OWNERSHIP(i, hid_pid) \ | 40 | #define CHECK_OWNERSHIP(i, hid_pid) \ |
43 | ((i) < FF_EFFECTS_MAX && i >= 0 && \ | 41 | ((i) < FF_EFFECTS_MAX && i >= 0 && \ |
44 | test_bit(FF_PID_FLAGS_USED, &hid_pid->effects[(i)].flags) && \ | 42 | test_bit(FF_PID_FLAGS_USED, &hid_pid->effects[(i)].flags) && \ |
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index 0043e6ebcd1f..7420c6b84284 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c | |||
@@ -30,10 +30,6 @@ | |||
30 | #include <linux/input.h> | 30 | #include <linux/input.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | |||
34 | #if !defined(DEBUG) && defined(CONFIG_USB_DEBUG) | ||
35 | #define DEBUG | ||
36 | #endif | ||
37 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
38 | #include <linux/usb_input.h> | 34 | #include <linux/usb_input.h> |
39 | 35 | ||
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index ea0f75773ae1..aea1cfae34cc 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c | |||
@@ -52,8 +52,10 @@ | |||
52 | * v1.30.1 (pi) - Added Graphire3 support | 52 | * v1.30.1 (pi) - Added Graphire3 support |
53 | * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... | 53 | * v1.40 (pc) - Add support for several new devices, fix eraser reporting, ... |
54 | * v1.43 (pc) - Added support for Cintiq 21UX | 54 | * v1.43 (pc) - Added support for Cintiq 21UX |
55 | - Fixed a Graphire bug | 55 | * - Fixed a Graphire bug |
56 | - Merged wacom_intuos3_irq into wacom_intuos_irq | 56 | * - Merged wacom_intuos3_irq into wacom_intuos_irq |
57 | * v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc. | ||
58 | * - Report Device IDs | ||
57 | */ | 59 | */ |
58 | 60 | ||
59 | /* | 61 | /* |
@@ -76,7 +78,7 @@ | |||
76 | /* | 78 | /* |
77 | * Version Information | 79 | * Version Information |
78 | */ | 80 | */ |
79 | #define DRIVER_VERSION "v1.43" | 81 | #define DRIVER_VERSION "v1.44" |
80 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | 82 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" |
81 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | 83 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" |
82 | #define DRIVER_LICENSE "GPL" | 84 | #define DRIVER_LICENSE "GPL" |
@@ -86,10 +88,14 @@ MODULE_DESCRIPTION(DRIVER_DESC); | |||
86 | MODULE_LICENSE(DRIVER_LICENSE); | 88 | MODULE_LICENSE(DRIVER_LICENSE); |
87 | 89 | ||
88 | #define USB_VENDOR_ID_WACOM 0x056a | 90 | #define USB_VENDOR_ID_WACOM 0x056a |
91 | #define STYLUS_DEVICE_ID 0x02 | ||
92 | #define CURSOR_DEVICE_ID 0x06 | ||
93 | #define ERASER_DEVICE_ID 0x0A | ||
89 | 94 | ||
90 | enum { | 95 | enum { |
91 | PENPARTNER = 0, | 96 | PENPARTNER = 0, |
92 | GRAPHIRE, | 97 | GRAPHIRE, |
98 | G4, | ||
93 | PL, | 99 | PL, |
94 | INTUOS, | 100 | INTUOS, |
95 | INTUOS3, | 101 | INTUOS3, |
@@ -116,6 +122,7 @@ struct wacom { | |||
116 | struct urb *irq; | 122 | struct urb *irq; |
117 | struct wacom_features *features; | 123 | struct wacom_features *features; |
118 | int tool[2]; | 124 | int tool[2]; |
125 | int id[2]; | ||
119 | __u32 serial[2]; | 126 | __u32 serial[2]; |
120 | char phys[32]; | 127 | char phys[32]; |
121 | }; | 128 | }; |
@@ -136,7 +143,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
136 | struct wacom *wacom = urb->context; | 143 | struct wacom *wacom = urb->context; |
137 | unsigned char *data = wacom->data; | 144 | unsigned char *data = wacom->data; |
138 | struct input_dev *dev = wacom->dev; | 145 | struct input_dev *dev = wacom->dev; |
139 | int prox, pressure; | 146 | int prox, pressure, id; |
140 | int retval; | 147 | int retval; |
141 | 148 | ||
142 | switch (urb->status) { | 149 | switch (urb->status) { |
@@ -163,6 +170,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
163 | 170 | ||
164 | input_regs(dev, regs); | 171 | input_regs(dev, regs); |
165 | 172 | ||
173 | id = ERASER_DEVICE_ID; | ||
166 | if (prox) { | 174 | if (prox) { |
167 | 175 | ||
168 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | 176 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); |
@@ -177,11 +185,15 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
177 | * an out of proximity for previous tool then a in for new tool. | 185 | * an out of proximity for previous tool then a in for new tool. |
178 | */ | 186 | */ |
179 | if (!wacom->tool[0]) { | 187 | if (!wacom->tool[0]) { |
180 | /* Going into proximity select tool */ | 188 | /* Eraser bit set for DTF */ |
181 | wacom->tool[1] = (data[4] & 0x20)? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 189 | if (data[1] & 0x10) |
190 | wacom->tool[1] = BTN_TOOL_RUBBER; | ||
191 | else | ||
192 | /* Going into proximity select tool */ | ||
193 | wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
182 | } else { | 194 | } else { |
183 | /* was entered with stylus2 pressed */ | 195 | /* was entered with stylus2 pressed */ |
184 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20) ) { | 196 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) { |
185 | /* report out proximity for previous tool */ | 197 | /* report out proximity for previous tool */ |
186 | input_report_key(dev, wacom->tool[1], 0); | 198 | input_report_key(dev, wacom->tool[1], 0); |
187 | input_sync(dev); | 199 | input_sync(dev); |
@@ -192,8 +204,9 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
192 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | 204 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { |
193 | /* Unknown tool selected default to pen tool */ | 205 | /* Unknown tool selected default to pen tool */ |
194 | wacom->tool[1] = BTN_TOOL_PEN; | 206 | wacom->tool[1] = BTN_TOOL_PEN; |
207 | id = STYLUS_DEVICE_ID; | ||
195 | } | 208 | } |
196 | input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */ | 209 | input_report_key(dev, wacom->tool[1], id); /* report in proximity for tool */ |
197 | input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); | 210 | input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); |
198 | input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); | 211 | input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); |
199 | input_report_abs(dev, ABS_PRESSURE, pressure); | 212 | input_report_abs(dev, ABS_PRESSURE, pressure); |
@@ -250,10 +263,10 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs) | |||
250 | 263 | ||
251 | input_regs(dev, regs); | 264 | input_regs(dev, regs); |
252 | if (data[1] & 0x04) { | 265 | if (data[1] & 0x04) { |
253 | input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20); | 266 | input_report_key(dev, BTN_TOOL_RUBBER, (data[1] & 0x20) ? ERASER_DEVICE_ID : 0); |
254 | input_report_key(dev, BTN_TOUCH, data[1] & 0x08); | 267 | input_report_key(dev, BTN_TOUCH, data[1] & 0x08); |
255 | } else { | 268 | } else { |
256 | input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20); | 269 | input_report_key(dev, BTN_TOOL_PEN, (data[1] & 0x20) ? STYLUS_DEVICE_ID : 0); |
257 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | 270 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); |
258 | } | 271 | } |
259 | input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2])); | 272 | input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2])); |
@@ -299,7 +312,7 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs) | |||
299 | } | 312 | } |
300 | 313 | ||
301 | input_regs(dev, regs); | 314 | input_regs(dev, regs); |
302 | input_report_key(dev, BTN_TOOL_PEN, 1); | 315 | input_report_key(dev, BTN_TOOL_PEN, STYLUS_DEVICE_ID); |
303 | input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1])); | 316 | input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1])); |
304 | input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3])); | 317 | input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3])); |
305 | input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127); | 318 | input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127); |
@@ -319,7 +332,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
319 | struct wacom *wacom = urb->context; | 332 | struct wacom *wacom = urb->context; |
320 | unsigned char *data = wacom->data; | 333 | unsigned char *data = wacom->data; |
321 | struct input_dev *dev = wacom->dev; | 334 | struct input_dev *dev = wacom->dev; |
322 | int x, y; | 335 | int x, y, id, rw; |
323 | int retval; | 336 | int retval; |
324 | 337 | ||
325 | switch (urb->status) { | 338 | switch (urb->status) { |
@@ -344,6 +357,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
344 | 357 | ||
345 | input_regs(dev, regs); | 358 | input_regs(dev, regs); |
346 | 359 | ||
360 | id = STYLUS_DEVICE_ID; | ||
347 | if (data[1] & 0x10) { /* in prox */ | 361 | if (data[1] & 0x10) { /* in prox */ |
348 | 362 | ||
349 | switch ((data[1] >> 5) & 3) { | 363 | switch ((data[1] >> 5) & 3) { |
@@ -354,18 +368,27 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
354 | 368 | ||
355 | case 1: /* Rubber */ | 369 | case 1: /* Rubber */ |
356 | wacom->tool[0] = BTN_TOOL_RUBBER; | 370 | wacom->tool[0] = BTN_TOOL_RUBBER; |
371 | id = ERASER_DEVICE_ID; | ||
357 | break; | 372 | break; |
358 | 373 | ||
359 | case 2: /* Mouse with wheel */ | 374 | case 2: /* Mouse with wheel */ |
360 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); | 375 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); |
361 | input_report_rel(dev, REL_WHEEL, (signed char) data[6]); | 376 | if (wacom->features->type == G4) { |
377 | rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); | ||
378 | input_report_rel(dev, REL_WHEEL, rw); | ||
379 | } else | ||
380 | input_report_rel(dev, REL_WHEEL, (signed char) data[6]); | ||
362 | /* fall through */ | 381 | /* fall through */ |
363 | 382 | ||
364 | case 3: /* Mouse without wheel */ | 383 | case 3: /* Mouse without wheel */ |
365 | wacom->tool[0] = BTN_TOOL_MOUSE; | 384 | wacom->tool[0] = BTN_TOOL_MOUSE; |
385 | id = CURSOR_DEVICE_ID; | ||
366 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); | 386 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); |
367 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); | 387 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); |
368 | input_report_abs(dev, ABS_DISTANCE, data[7]); | 388 | if (wacom->features->type == G4) |
389 | input_report_abs(dev, ABS_DISTANCE, data[6]); | ||
390 | else | ||
391 | input_report_abs(dev, ABS_DISTANCE, data[7]); | ||
369 | break; | 392 | break; |
370 | } | 393 | } |
371 | } | 394 | } |
@@ -376,16 +399,50 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
376 | input_report_abs(dev, ABS_X, x); | 399 | input_report_abs(dev, ABS_X, x); |
377 | input_report_abs(dev, ABS_Y, y); | 400 | input_report_abs(dev, ABS_Y, y); |
378 | if (wacom->tool[0] != BTN_TOOL_MOUSE) { | 401 | if (wacom->tool[0] != BTN_TOOL_MOUSE) { |
379 | input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6])); | 402 | input_report_abs(dev, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); |
380 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); | 403 | input_report_key(dev, BTN_TOUCH, data[1] & 0x01); |
381 | input_report_key(dev, BTN_STYLUS, data[1] & 0x02); | 404 | input_report_key(dev, BTN_STYLUS, data[1] & 0x02); |
382 | input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); | 405 | input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); |
383 | } | 406 | } |
384 | } | 407 | } |
385 | 408 | ||
386 | input_report_key(dev, wacom->tool[0], data[1] & 0x10); | 409 | input_report_key(dev, wacom->tool[0], (data[1] & 0x10) ? id : 0); |
387 | input_sync(dev); | 410 | input_sync(dev); |
388 | 411 | ||
412 | /* send pad data */ | ||
413 | if (wacom->features->type == G4) { | ||
414 | /* fist time sending pad data */ | ||
415 | if (wacom->tool[1] != BTN_TOOL_FINGER) { | ||
416 | wacom->id[1] = 0; | ||
417 | wacom->serial[1] = (data[7] & 0x38) >> 2; | ||
418 | } | ||
419 | if (data[7] & 0xf8) { | ||
420 | input_report_key(dev, BTN_0, (data[7] & 0x40)); | ||
421 | input_report_key(dev, BTN_4, (data[7] & 0x80)); | ||
422 | if (((data[7] & 0x38) >> 2) == (wacom->serial[1] & 0x0e)) | ||
423 | /* alter REL_WHEEL value so X apps can get it */ | ||
424 | wacom->serial[1] += (wacom->serial[1] & 0x01) ? -1 : 1; | ||
425 | else | ||
426 | wacom->serial[1] = (data[7] & 0x38 ) >> 2; | ||
427 | |||
428 | /* don't alter the value when there is no wheel event */ | ||
429 | if (wacom->serial[1] == 1) | ||
430 | wacom->serial[1] = 0; | ||
431 | rw = wacom->serial[1]; | ||
432 | rw = (rw & 0x08) ? -(rw & 0x07) : (rw & 0x07); | ||
433 | input_report_rel(dev, REL_WHEEL, rw); | ||
434 | wacom->tool[1] = BTN_TOOL_FINGER; | ||
435 | wacom->id[1] = data[7] & 0xf8; | ||
436 | input_report_key(dev, wacom->tool[1], 0xf0); | ||
437 | input_event(dev, EV_MSC, MSC_SERIAL, 0xf0); | ||
438 | } else if (wacom->id[1]) { | ||
439 | wacom->id[1] = 0; | ||
440 | wacom->serial[1] = 0; | ||
441 | input_report_key(dev, wacom->tool[1], 0); | ||
442 | input_event(dev, EV_MSC, MSC_SERIAL, 0xf0); | ||
443 | } | ||
444 | input_sync(dev); | ||
445 | } | ||
389 | exit: | 446 | exit: |
390 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 447 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
391 | if (retval) | 448 | if (retval) |
@@ -410,7 +467,8 @@ static int wacom_intuos_inout(struct urb *urb) | |||
410 | (data[4] << 20) + (data[5] << 12) + | 467 | (data[4] << 20) + (data[5] << 12) + |
411 | (data[6] << 4) + (data[7] >> 4); | 468 | (data[6] << 4) + (data[7] >> 4); |
412 | 469 | ||
413 | switch ((data[2] << 4) | (data[3] >> 4)) { | 470 | wacom->id[idx] = (data[2] << 4) | (data[3] >> 4); |
471 | switch (wacom->id[idx]) { | ||
414 | case 0x812: /* Inking pen */ | 472 | case 0x812: /* Inking pen */ |
415 | case 0x801: /* Intuos3 Inking pen */ | 473 | case 0x801: /* Intuos3 Inking pen */ |
416 | case 0x012: | 474 | case 0x012: |
@@ -458,7 +516,7 @@ static int wacom_intuos_inout(struct urb *urb) | |||
458 | default: /* Unknown tool */ | 516 | default: /* Unknown tool */ |
459 | wacom->tool[idx] = BTN_TOOL_PEN; | 517 | wacom->tool[idx] = BTN_TOOL_PEN; |
460 | } | 518 | } |
461 | input_report_key(dev, wacom->tool[idx], 1); | 519 | input_report_key(dev, wacom->tool[idx], wacom->id[idx]); |
462 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | 520 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); |
463 | input_sync(dev); | 521 | input_sync(dev); |
464 | return 1; | 522 | return 1; |
@@ -637,7 +695,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) | |||
637 | } | 695 | } |
638 | } | 696 | } |
639 | 697 | ||
640 | input_report_key(dev, wacom->tool[idx], 1); | 698 | input_report_key(dev, wacom->tool[idx], wacom->id[idx]); |
641 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | 699 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); |
642 | input_sync(dev); | 700 | input_sync(dev); |
643 | 701 | ||
@@ -655,6 +713,13 @@ static struct wacom_features wacom_features[] = { | |||
655 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 713 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
656 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 714 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
657 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 715 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
716 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, G4, wacom_graphire_irq }, | ||
717 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, G4, wacom_graphire_irq }, | ||
718 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
719 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, | ||
720 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
721 | { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
722 | { "Wacom PenPartner2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, | ||
658 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, | 723 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, |
659 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, | 724 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, |
660 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, | 725 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, |
@@ -666,16 +731,20 @@ static struct wacom_features wacom_features[] = { | |||
666 | { "Wacom PL600SX", 8, 6260, 5016, 255, 32, PL, wacom_pl_irq }, | 731 | { "Wacom PL600SX", 8, 6260, 5016, 255, 32, PL, wacom_pl_irq }, |
667 | { "Wacom PL550", 8, 6144, 4608, 511, 32, PL, wacom_pl_irq }, | 732 | { "Wacom PL550", 8, 6144, 4608, 511, 32, PL, wacom_pl_irq }, |
668 | { "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_pl_irq }, | 733 | { "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_pl_irq }, |
734 | { "Wacom PL700", 8, 6758, 5406, 511, 32, PL, wacom_pl_irq }, | ||
735 | { "Wacom PL510", 8, 6282, 4762, 511, 32, PL, wacom_pl_irq }, | ||
736 | { "Wacom PL710", 8, 34080, 27660, 511, 32, PL, wacom_pl_irq }, | ||
737 | { "Wacom DTF720", 8, 6858, 5506, 511, 32, PL, wacom_pl_irq }, | ||
738 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PL, wacom_ptu_irq }, | ||
669 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, | 739 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_intuos_irq }, |
670 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, | 740 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, |
671 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, | 741 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_intuos_irq }, |
672 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, | 742 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, |
673 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, | 743 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_intuos_irq }, |
674 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | ||
675 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PL, wacom_ptu_irq }, | ||
676 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_intuos_irq }, | 744 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_intuos_irq }, |
677 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_intuos_irq }, | 745 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_intuos_irq }, |
678 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_intuos_irq }, | 746 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_intuos_irq }, |
747 | { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 15, INTUOS3, wacom_intuos_irq }, | ||
679 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_intuos_irq }, | 748 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_intuos_irq }, |
680 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, | 749 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_intuos_irq }, |
681 | { } | 750 | { } |
@@ -688,6 +757,13 @@ static struct usb_device_id wacom_ids[] = { | |||
688 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) }, | 757 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) }, |
689 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) }, | 758 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) }, |
690 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) }, | 759 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) }, |
760 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) }, | ||
761 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) }, | ||
762 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, | ||
763 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) }, | ||
764 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, | ||
765 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) }, | ||
766 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) }, | ||
691 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, | 767 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, |
692 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, | 768 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, |
693 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, | 769 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, |
@@ -699,16 +775,20 @@ static struct usb_device_id wacom_ids[] = { | |||
699 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) }, | 775 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) }, |
700 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) }, | 776 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) }, |
701 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) }, | 777 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) }, |
778 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, | ||
779 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, | ||
780 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, | ||
781 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, | ||
782 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, | ||
702 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, | 783 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, |
703 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, | 784 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, |
704 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) }, | 785 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) }, |
705 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) }, | 786 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) }, |
706 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) }, | 787 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) }, |
707 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, | ||
708 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, | ||
709 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, | 788 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, |
710 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, | 789 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, |
711 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, | 790 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, |
791 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, | ||
712 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, | 792 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, |
713 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, | 793 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, |
714 | { } | 794 | { } |
@@ -779,6 +859,13 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
779 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); | 859 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); |
780 | 860 | ||
781 | switch (wacom->features->type) { | 861 | switch (wacom->features->type) { |
862 | case G4: | ||
863 | input_dev->evbit[0] |= BIT(EV_MSC); | ||
864 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | ||
865 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | ||
866 | input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); | ||
867 | /* fall through */ | ||
868 | |||
782 | case GRAPHIRE: | 869 | case GRAPHIRE: |
783 | input_dev->evbit[0] |= BIT(EV_REL); | 870 | input_dev->evbit[0] |= BIT(EV_REL); |
784 | input_dev->relbit[0] |= BIT(REL_WHEEL); | 871 | input_dev->relbit[0] |= BIT(REL_WHEEL); |
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 862e40a83689..6c693bc68e2e 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile | |||
@@ -18,4 +18,8 @@ obj-$(CONFIG_USB_RIO500) += rio500.o | |||
18 | obj-$(CONFIG_USB_TEST) += usbtest.o | 18 | obj-$(CONFIG_USB_TEST) += usbtest.o |
19 | obj-$(CONFIG_USB_USS720) += uss720.o | 19 | obj-$(CONFIG_USB_USS720) += uss720.o |
20 | 20 | ||
21 | obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ \ No newline at end of file | 21 | obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ |
22 | |||
23 | ifeq ($(CONFIG_USB_DEBUG),y) | ||
24 | EXTRA_CFLAGS += -DDEBUG | ||
25 | endif | ||
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 5f33f7c64885..2a28ceeaa66a 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/wait.h> | 32 | #include <linux/wait.h> |
33 | #undef DEBUG /* include debug macros until it's done */ | ||
34 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
35 | 34 | ||
36 | /*-------------------------------------------------------------------*/ | 35 | /*-------------------------------------------------------------------*/ |
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c index b84eda631ab5..a30d4a6ee824 100644 --- a/drivers/usb/misc/phidgetservo.c +++ b/drivers/usb/misc/phidgetservo.c | |||
@@ -26,9 +26,6 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/config.h> | 28 | #include <linux/config.h> |
29 | #ifdef CONFIG_USB_DEBUG | ||
30 | #define DEBUG 1 | ||
31 | #endif | ||
32 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
33 | #include <linux/errno.h> | 30 | #include <linux/errno.h> |
34 | #include <linux/init.h> | 31 | #include <linux/init.h> |
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index 7d02d8ec6b1a..9590dbac5d9a 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c | |||
@@ -393,7 +393,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) | |||
393 | ibuf, this_read, &partial, | 393 | ibuf, this_read, &partial, |
394 | 8000); | 394 | 8000); |
395 | 395 | ||
396 | dbg(KERN_DEBUG "read stats: result:%d this_read:%u partial:%u", | 396 | dbg("read stats: result:%d this_read:%u partial:%u", |
397 | result, this_read, partial); | 397 | result, this_read, partial); |
398 | 398 | ||
399 | if (partial) { | 399 | if (partial) { |
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index f6ba4c788dbc..3c93921cb6b3 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c | |||
@@ -10,9 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/config.h> | 12 | #include <linux/config.h> |
13 | #ifdef CONFIG_USB_DEBUG | ||
14 | #define DEBUG 1 | ||
15 | #endif | ||
16 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
17 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
18 | #include <linux/init.h> | 15 | #include <linux/init.h> |
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 2997f558159b..605a2afe34ed 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -1,7 +1,4 @@ | |||
1 | #include <linux/config.h> | 1 | #include <linux/config.h> |
2 | #if !defined (DEBUG) && defined (CONFIG_USB_DEBUG) | ||
3 | # define DEBUG | ||
4 | #endif | ||
5 | #include <linux/kernel.h> | 2 | #include <linux/kernel.h> |
6 | #include <linux/errno.h> | 3 | #include <linux/errno.h> |
7 | #include <linux/init.h> | 4 | #include <linux/init.h> |
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 0592cb5e6c4d..1cabe7ed91f5 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c | |||
@@ -41,8 +41,6 @@ | |||
41 | 41 | ||
42 | /*****************************************************************************/ | 42 | /*****************************************************************************/ |
43 | 43 | ||
44 | #define DEBUG | ||
45 | |||
46 | #include <linux/module.h> | 44 | #include <linux/module.h> |
47 | #include <linux/socket.h> | 45 | #include <linux/socket.h> |
48 | #include <linux/parport.h> | 46 | #include <linux/parport.h> |
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile index 222c0495f791..a21e6eaabaf6 100644 --- a/drivers/usb/net/Makefile +++ b/drivers/usb/net/Makefile | |||
@@ -16,3 +16,7 @@ obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o | |||
16 | obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o | 16 | obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o |
17 | obj-$(CONFIG_USB_USBNET) += usbnet.o | 17 | obj-$(CONFIG_USB_USBNET) += usbnet.o |
18 | obj-$(CONFIG_USB_ZD1201) += zd1201.o | 18 | obj-$(CONFIG_USB_ZD1201) += zd1201.o |
19 | |||
20 | ifeq ($(CONFIG_USB_DEBUG),y) | ||
21 | EXTRA_CFLAGS += -DDEBUG | ||
22 | endif | ||
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 252a34fbb42c..542120ef1fd2 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c | |||
@@ -23,9 +23,6 @@ | |||
23 | // #define VERBOSE // more; success messages | 23 | // #define VERBOSE // more; success messages |
24 | 24 | ||
25 | #include <linux/config.h> | 25 | #include <linux/config.h> |
26 | #ifdef CONFIG_USB_DEBUG | ||
27 | # define DEBUG | ||
28 | #endif | ||
29 | #include <linux/module.h> | 26 | #include <linux/module.h> |
30 | #include <linux/kmod.h> | 27 | #include <linux/kmod.h> |
31 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c index 652b04bbf6af..c008c981862b 100644 --- a/drivers/usb/net/cdc_ether.c +++ b/drivers/usb/net/cdc_ether.c | |||
@@ -21,9 +21,6 @@ | |||
21 | // #define VERBOSE // more; success messages | 21 | // #define VERBOSE // more; success messages |
22 | 22 | ||
23 | #include <linux/config.h> | 23 | #include <linux/config.h> |
24 | #ifdef CONFIG_USB_DEBUG | ||
25 | # define DEBUG | ||
26 | #endif | ||
27 | #include <linux/module.h> | 24 | #include <linux/module.h> |
28 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
29 | #include <linux/init.h> | 26 | #include <linux/init.h> |
diff --git a/drivers/usb/net/cdc_subset.c b/drivers/usb/net/cdc_subset.c index f1730b685fd2..f05cfb83c82d 100644 --- a/drivers/usb/net/cdc_subset.c +++ b/drivers/usb/net/cdc_subset.c | |||
@@ -18,9 +18,6 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/config.h> | 20 | #include <linux/config.h> |
21 | #ifdef CONFIG_USB_DEBUG | ||
22 | # define DEBUG | ||
23 | #endif | ||
24 | #include <linux/module.h> | 21 | #include <linux/module.h> |
25 | #include <linux/kmod.h> | 22 | #include <linux/kmod.h> |
26 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c index c0f263b202a6..2455e9a85674 100644 --- a/drivers/usb/net/gl620a.c +++ b/drivers/usb/net/gl620a.c | |||
@@ -22,9 +22,6 @@ | |||
22 | // #define VERBOSE // more; success messages | 22 | // #define VERBOSE // more; success messages |
23 | 23 | ||
24 | #include <linux/config.h> | 24 | #include <linux/config.h> |
25 | #ifdef CONFIG_USB_DEBUG | ||
26 | # define DEBUG | ||
27 | #endif | ||
28 | #include <linux/module.h> | 25 | #include <linux/module.h> |
29 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
30 | #include <linux/init.h> | 27 | #include <linux/init.h> |
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index 6bef1be6b36c..b5776518020f 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c | |||
@@ -219,7 +219,6 @@ struct kaweth_device | |||
219 | 219 | ||
220 | __u32 status; | 220 | __u32 status; |
221 | int end; | 221 | int end; |
222 | int removed; | ||
223 | int suspend_lowmem_rx; | 222 | int suspend_lowmem_rx; |
224 | int suspend_lowmem_ctrl; | 223 | int suspend_lowmem_ctrl; |
225 | int linkstate; | 224 | int linkstate; |
@@ -699,6 +698,7 @@ static int kaweth_close(struct net_device *net) | |||
699 | 698 | ||
700 | usb_kill_urb(kaweth->irq_urb); | 699 | usb_kill_urb(kaweth->irq_urb); |
701 | usb_kill_urb(kaweth->rx_urb); | 700 | usb_kill_urb(kaweth->rx_urb); |
701 | usb_kill_urb(kaweth->tx_urb); | ||
702 | 702 | ||
703 | flush_scheduled_work(); | 703 | flush_scheduled_work(); |
704 | 704 | ||
@@ -750,13 +750,6 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) | |||
750 | 750 | ||
751 | spin_lock(&kaweth->device_lock); | 751 | spin_lock(&kaweth->device_lock); |
752 | 752 | ||
753 | if (kaweth->removed) { | ||
754 | /* our device is undergoing disconnection - we bail out */ | ||
755 | spin_unlock(&kaweth->device_lock); | ||
756 | dev_kfree_skb_irq(skb); | ||
757 | return 0; | ||
758 | } | ||
759 | |||
760 | kaweth_async_set_rx_mode(kaweth); | 753 | kaweth_async_set_rx_mode(kaweth); |
761 | netif_stop_queue(net); | 754 | netif_stop_queue(net); |
762 | 755 | ||
@@ -1136,10 +1129,6 @@ static void kaweth_disconnect(struct usb_interface *intf) | |||
1136 | return; | 1129 | return; |
1137 | } | 1130 | } |
1138 | netdev = kaweth->net; | 1131 | netdev = kaweth->net; |
1139 | kaweth->removed = 1; | ||
1140 | usb_kill_urb(kaweth->irq_urb); | ||
1141 | usb_kill_urb(kaweth->rx_urb); | ||
1142 | usb_kill_urb(kaweth->tx_urb); | ||
1143 | 1132 | ||
1144 | kaweth_dbg("Unregistering net device"); | 1133 | kaweth_dbg("Unregistering net device"); |
1145 | unregister_netdev(netdev); | 1134 | unregister_netdev(netdev); |
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c index cee55f8cf64f..b3799b1a2b0d 100644 --- a/drivers/usb/net/net1080.c +++ b/drivers/usb/net/net1080.c | |||
@@ -21,9 +21,6 @@ | |||
21 | // #define VERBOSE // more; success messages | 21 | // #define VERBOSE // more; success messages |
22 | 22 | ||
23 | #include <linux/config.h> | 23 | #include <linux/config.h> |
24 | #ifdef CONFIG_USB_DEBUG | ||
25 | # define DEBUG | ||
26 | #endif | ||
27 | #include <linux/module.h> | 24 | #include <linux/module.h> |
28 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
29 | #include <linux/init.h> | 26 | #include <linux/init.h> |
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 537eb181d985..683e3df5d607 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c | |||
@@ -28,8 +28,6 @@ | |||
28 | * is out of the interrupt routine. | 28 | * is out of the interrupt routine. |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #undef DEBUG | ||
32 | |||
33 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
34 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
35 | #include <linux/init.h> | 33 | #include <linux/init.h> |
diff --git a/drivers/usb/net/plusb.c b/drivers/usb/net/plusb.c index 74c2b3581c76..89856aa0e3b8 100644 --- a/drivers/usb/net/plusb.c +++ b/drivers/usb/net/plusb.c | |||
@@ -21,9 +21,6 @@ | |||
21 | // #define VERBOSE // more; success messages | 21 | // #define VERBOSE // more; success messages |
22 | 22 | ||
23 | #include <linux/config.h> | 23 | #include <linux/config.h> |
24 | #ifdef CONFIG_USB_DEBUG | ||
25 | # define DEBUG | ||
26 | #endif | ||
27 | #include <linux/module.h> | 24 | #include <linux/module.h> |
28 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
29 | #include <linux/init.h> | 26 | #include <linux/init.h> |
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c index b5a925dc1beb..c0ecbab6f6ba 100644 --- a/drivers/usb/net/rndis_host.c +++ b/drivers/usb/net/rndis_host.c | |||
@@ -21,9 +21,6 @@ | |||
21 | // #define VERBOSE // more; success messages | 21 | // #define VERBOSE // more; success messages |
22 | 22 | ||
23 | #include <linux/config.h> | 23 | #include <linux/config.h> |
24 | #ifdef CONFIG_USB_DEBUG | ||
25 | # define DEBUG | ||
26 | #endif | ||
27 | #include <linux/module.h> | 24 | #include <linux/module.h> |
28 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
29 | #include <linux/init.h> | 26 | #include <linux/init.h> |
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 74f05c9c84d5..362d6907c9bb 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c | |||
@@ -34,9 +34,6 @@ | |||
34 | // #define VERBOSE // more; success messages | 34 | // #define VERBOSE // more; success messages |
35 | 35 | ||
36 | #include <linux/config.h> | 36 | #include <linux/config.h> |
37 | #ifdef CONFIG_USB_DEBUG | ||
38 | # define DEBUG | ||
39 | #endif | ||
40 | #include <linux/module.h> | 37 | #include <linux/module.h> |
41 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
42 | #include <linux/init.h> | 39 | #include <linux/init.h> |
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c index 5d4b7d55b097..680d13957af4 100644 --- a/drivers/usb/net/zaurus.c +++ b/drivers/usb/net/zaurus.c | |||
@@ -21,9 +21,6 @@ | |||
21 | // #define VERBOSE // more; success messages | 21 | // #define VERBOSE // more; success messages |
22 | 22 | ||
23 | #include <linux/config.h> | 23 | #include <linux/config.h> |
24 | #ifdef CONFIG_USB_DEBUG | ||
25 | # define DEBUG | ||
26 | #endif | ||
27 | #include <linux/module.h> | 24 | #include <linux/module.h> |
28 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
29 | #include <linux/init.h> | 26 | #include <linux/init.h> |
diff --git a/drivers/usb/serial/ChangeLog.old b/drivers/usb/serial/ChangeLog.history index c1b279939bbf..52c4f7bd7a80 100644 --- a/drivers/usb/serial/ChangeLog.old +++ b/drivers/usb/serial/ChangeLog.history | |||
@@ -400,7 +400,7 @@ visor.c Change Log comments: | |||
400 | 400 | ||
401 | (11/11/2001) gkh | 401 | (11/11/2001) gkh |
402 | Added support for the m125 devices, and added check to prevent oopses | 402 | Added support for the m125 devices, and added check to prevent oopses |
403 | for Clié devices that lie about the number of ports they have. | 403 | for Clié devices that lie about the number of ports they have. |
404 | 404 | ||
405 | (08/30/2001) gkh | 405 | (08/30/2001) gkh |
406 | Added support for the Clie devices, both the 3.5 and 4.0 os versions. | 406 | Added support for the Clie devices, both the 3.5 and 4.0 os versions. |
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 7b5e8e4ee2bb..14f55fd26a64 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -62,6 +62,15 @@ config USB_SERIAL_AIRPRIME | |||
62 | To compile this driver as a module, choose M here: the | 62 | To compile this driver as a module, choose M here: the |
63 | module will be called airprime. | 63 | module will be called airprime. |
64 | 64 | ||
65 | config USB_SERIAL_ANYDATA | ||
66 | tristate "USB AnyData CDMA Wireless Driver" | ||
67 | depends on USB_SERIAL | ||
68 | help | ||
69 | Say Y here if you want to use a AnyData CDMA device. | ||
70 | |||
71 | To compile this driver as a module, choose M here: the | ||
72 | module will be called anydata. | ||
73 | |||
65 | config USB_SERIAL_BELKIN | 74 | config USB_SERIAL_BELKIN |
66 | tristate "USB Belkin and Peracom Single Port Serial Driver" | 75 | tristate "USB Belkin and Peracom Single Port Serial Driver" |
67 | depends on USB_SERIAL | 76 | depends on USB_SERIAL |
@@ -394,15 +403,6 @@ config USB_SERIAL_MCT_U232 | |||
394 | To compile this driver as a module, choose M here: the | 403 | To compile this driver as a module, choose M here: the |
395 | module will be called mct_u232. | 404 | module will be called mct_u232. |
396 | 405 | ||
397 | config USB_SERIAL_NOKIA_DKU2 | ||
398 | tristate "USB Nokia DKU2 Driver" | ||
399 | depends on USB_SERIAL | ||
400 | help | ||
401 | Say Y here if you want to use a Nokia DKU2 device. | ||
402 | |||
403 | To compile this driver as a module, choose M here: the | ||
404 | module will be called nokia_dku2. | ||
405 | |||
406 | config USB_SERIAL_PL2303 | 406 | config USB_SERIAL_PL2303 |
407 | tristate "USB Prolific 2303 Single Port Serial Driver" | 407 | tristate "USB Prolific 2303 Single Port Serial Driver" |
408 | depends on USB_SERIAL | 408 | depends on USB_SERIAL |
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 55fd461793b7..f0b04420cea1 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -12,6 +12,7 @@ usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o | |||
12 | usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) | 12 | usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) |
13 | 13 | ||
14 | obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o | 14 | obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o |
15 | obj-$(CONFIG_USB_SERIAL_ANYDATA) += anydata.o | ||
15 | obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o | 16 | obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o |
16 | obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o | 17 | obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o |
17 | obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o | 18 | obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o |
@@ -31,7 +32,6 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o | |||
31 | obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o | 32 | obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o |
32 | obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o | 33 | obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o |
33 | obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o | 34 | obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o |
34 | obj-$(CONFIG_USB_SERIAL_NOKIA_DKU2) += nokia_dku2.o | ||
35 | obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o | 35 | obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o |
36 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o | 36 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o |
37 | obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o | 37 | obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o |
diff --git a/drivers/usb/serial/anydata.c b/drivers/usb/serial/anydata.c new file mode 100644 index 000000000000..18022a74a3dc --- /dev/null +++ b/drivers/usb/serial/anydata.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * AnyData CDMA Serial USB driver | ||
3 | * | ||
4 | * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/tty.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/usb.h> | ||
16 | #include "usb-serial.h" | ||
17 | |||
18 | static struct usb_device_id id_table [] = { | ||
19 | { USB_DEVICE(0x16d5, 0x6501) }, /* AirData CDMA device */ | ||
20 | { }, | ||
21 | }; | ||
22 | MODULE_DEVICE_TABLE(usb, id_table); | ||
23 | |||
24 | /* if overridden by the user, then use their value for the size of the | ||
25 | * read and write urbs */ | ||
26 | static int buffer_size; | ||
27 | static int debug; | ||
28 | |||
29 | static struct usb_driver anydata_driver = { | ||
30 | .owner = THIS_MODULE, | ||
31 | .name = "anydata", | ||
32 | .probe = usb_serial_probe, | ||
33 | .disconnect = usb_serial_disconnect, | ||
34 | .id_table = id_table, | ||
35 | }; | ||
36 | |||
37 | static int anydata_open(struct usb_serial_port *port, struct file *filp) | ||
38 | { | ||
39 | char *buffer; | ||
40 | int result = 0; | ||
41 | |||
42 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
43 | |||
44 | if (buffer_size) { | ||
45 | /* override the default buffer sizes */ | ||
46 | buffer = kmalloc(buffer_size, GFP_KERNEL); | ||
47 | if (!buffer) { | ||
48 | dev_err(&port->dev, "%s - out of memory.\n", | ||
49 | __FUNCTION__); | ||
50 | return -ENOMEM; | ||
51 | } | ||
52 | kfree (port->read_urb->transfer_buffer); | ||
53 | port->read_urb->transfer_buffer = buffer; | ||
54 | port->read_urb->transfer_buffer_length = buffer_size; | ||
55 | |||
56 | buffer = kmalloc(buffer_size, GFP_KERNEL); | ||
57 | if (!buffer) { | ||
58 | dev_err(&port->dev, "%s - out of memory.\n", | ||
59 | __FUNCTION__); | ||
60 | return -ENOMEM; | ||
61 | } | ||
62 | kfree (port->write_urb->transfer_buffer); | ||
63 | port->write_urb->transfer_buffer = buffer; | ||
64 | port->write_urb->transfer_buffer_length = buffer_size; | ||
65 | port->bulk_out_size = buffer_size; | ||
66 | } | ||
67 | |||
68 | /* Start reading from the device */ | ||
69 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | ||
70 | usb_rcvbulkpipe(port->serial->dev, | ||
71 | port->bulk_in_endpointAddress), | ||
72 | port->read_urb->transfer_buffer, | ||
73 | port->read_urb->transfer_buffer_length, | ||
74 | usb_serial_generic_write_bulk_callback, port); | ||
75 | result = usb_submit_urb(port->read_urb, GFP_KERNEL); | ||
76 | if (result) | ||
77 | dev_err(&port->dev, | ||
78 | "%s - failed submitting read urb, error %d\n", | ||
79 | __FUNCTION__, result); | ||
80 | |||
81 | return result; | ||
82 | } | ||
83 | |||
84 | static struct usb_serial_driver anydata_device = { | ||
85 | .driver = { | ||
86 | .owner = THIS_MODULE, | ||
87 | .name = "anydata", | ||
88 | }, | ||
89 | .id_table = id_table, | ||
90 | .num_interrupt_in = NUM_DONT_CARE, | ||
91 | .num_bulk_in = NUM_DONT_CARE, | ||
92 | .num_bulk_out = NUM_DONT_CARE, | ||
93 | .num_ports = 1, | ||
94 | .open = anydata_open, | ||
95 | }; | ||
96 | |||
97 | static int __init anydata_init(void) | ||
98 | { | ||
99 | int retval; | ||
100 | |||
101 | retval = usb_serial_register(&anydata_device); | ||
102 | if (retval) | ||
103 | return retval; | ||
104 | retval = usb_register(&anydata_driver); | ||
105 | if (retval) | ||
106 | usb_serial_deregister(&anydata_device); | ||
107 | return retval; | ||
108 | } | ||
109 | |||
110 | static void __exit anydata_exit(void) | ||
111 | { | ||
112 | usb_deregister(&anydata_driver); | ||
113 | usb_serial_deregister(&anydata_device); | ||
114 | } | ||
115 | |||
116 | module_init(anydata_init); | ||
117 | module_exit(anydata_exit); | ||
118 | MODULE_LICENSE("GPL"); | ||
119 | |||
120 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
121 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
122 | module_param(buffer_size, int, 0); | ||
123 | MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers"); | ||
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index c5334dd89b12..c9787001cf2a 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c | |||
@@ -60,6 +60,7 @@ static struct usb_device_id id_table [] = { | |||
60 | { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ | 60 | { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ |
61 | { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ | 61 | { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ |
62 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ | 62 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ |
63 | { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ | ||
63 | { } /* Terminating Entry */ | 64 | { } /* Terminating Entry */ |
64 | }; | 65 | }; |
65 | 66 | ||
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 8909208f506a..53a47c31cd0e 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -309,6 +309,7 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *re | |||
309 | 309 | ||
310 | schedule_work(&port->work); | 310 | schedule_work(&port->work); |
311 | } | 311 | } |
312 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); | ||
312 | 313 | ||
313 | void usb_serial_generic_shutdown (struct usb_serial *serial) | 314 | void usb_serial_generic_shutdown (struct usb_serial *serial) |
314 | { | 315 | { |
diff --git a/drivers/usb/serial/nokia_dku2.c b/drivers/usb/serial/nokia_dku2.c deleted file mode 100644 index fad01bef3a64..000000000000 --- a/drivers/usb/serial/nokia_dku2.c +++ /dev/null | |||
@@ -1,142 +0,0 @@ | |||
1 | /* | ||
2 | * Nokia DKU2 USB driver | ||
3 | * | ||
4 | * Copyright (C) 2004 | ||
5 | * Author: C Kemp | ||
6 | * | ||
7 | * This program is largely derived from work by the linux-usb group | ||
8 | * and associated source files. Please see the usb/serial files for | ||
9 | * individual credits and copyrights. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * 20.09.2005 - Matthias Blaesing <matthias.blaesing@rwth-aachen.de> | ||
17 | * Added short name to device structure to make driver load into kernel 2.6.13 | ||
18 | * | ||
19 | * 20.09.2005 - Matthias Blaesing <matthias.blaesing@rwth-aachen.de> | ||
20 | * Added usb_deregister to exit code - to allow remove and reinsert of module | ||
21 | */ | ||
22 | |||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/tty.h> | ||
30 | #include <linux/tty_driver.h> | ||
31 | #include <linux/tty_flip.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/usb.h> | ||
34 | #include "usb-serial.h" | ||
35 | |||
36 | |||
37 | #define NOKIA_VENDOR_ID 0x0421 | ||
38 | #define NOKIA7600_PRODUCT_ID 0x0400 | ||
39 | #define NOKIA6230_PRODUCT_ID 0x040f | ||
40 | #define NOKIA6170_PRODUCT_ID 0x0416 | ||
41 | #define NOKIA6670_PRODUCT_ID 0x041d | ||
42 | #define NOKIA6680_PRODUCT_ID 0x041e | ||
43 | #define NOKIA6230i_PRODUCT_ID 0x0428 | ||
44 | |||
45 | #define NOKIA_AT_PORT 0x82 | ||
46 | #define NOKIA_FBUS_PORT 0x86 | ||
47 | |||
48 | /* | ||
49 | * Version Information | ||
50 | */ | ||
51 | #define DRIVER_VERSION "v0.2" | ||
52 | #define DRIVER_AUTHOR "C Kemp" | ||
53 | #define DRIVER_DESC "Nokia DKU2 Driver" | ||
54 | |||
55 | static struct usb_device_id id_table [] = { | ||
56 | { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA7600_PRODUCT_ID) }, | ||
57 | { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6230_PRODUCT_ID) }, | ||
58 | { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6170_PRODUCT_ID) }, | ||
59 | { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6670_PRODUCT_ID) }, | ||
60 | { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6680_PRODUCT_ID) }, | ||
61 | { USB_DEVICE(NOKIA_VENDOR_ID, NOKIA6230i_PRODUCT_ID) }, | ||
62 | { } /* Terminating entry */ | ||
63 | }; | ||
64 | MODULE_DEVICE_TABLE(usb, id_table); | ||
65 | |||
66 | /* The only thing which makes this device different from a generic | ||
67 | * device is that we have to set an alternative configuration to make | ||
68 | * the relevant endpoints available. In 2.6 this is really easy... */ | ||
69 | static int nokia_probe(struct usb_serial *serial, | ||
70 | const struct usb_device_id *id) | ||
71 | { | ||
72 | int retval = -ENODEV; | ||
73 | |||
74 | if (serial->interface->altsetting[0].endpoint[0].desc.bEndpointAddress == NOKIA_AT_PORT) { | ||
75 | /* the AT port */ | ||
76 | dev_info(&serial->dev->dev, "Nokia AT Port:\n"); | ||
77 | retval = 0; | ||
78 | } else if (serial->interface->num_altsetting == 2 && | ||
79 | serial->interface->altsetting[1].endpoint[0].desc.bEndpointAddress == NOKIA_FBUS_PORT) { | ||
80 | /* the FBUS port */ | ||
81 | dev_info(&serial->dev->dev, "Nokia FBUS Port:\n"); | ||
82 | usb_set_interface(serial->dev, 10, 1); | ||
83 | retval = 0; | ||
84 | } | ||
85 | |||
86 | return retval; | ||
87 | } | ||
88 | |||
89 | static struct usb_driver nokia_driver = { | ||
90 | .owner = THIS_MODULE, | ||
91 | .name = "nokia_dku2", | ||
92 | .probe = usb_serial_probe, | ||
93 | .disconnect = usb_serial_disconnect, | ||
94 | .id_table = id_table, | ||
95 | }; | ||
96 | |||
97 | static struct usb_serial_driver nokia_serial_driver = { | ||
98 | .driver = { | ||
99 | .owner = THIS_MODULE, | ||
100 | .name = "nokia_dku2", | ||
101 | }, | ||
102 | .description = "Nokia 7600/6230(i)/6170/66x0 DKU2 driver", | ||
103 | .id_table = id_table, | ||
104 | .num_interrupt_in = 1, | ||
105 | .num_bulk_in = 1, | ||
106 | .num_bulk_out = 1, | ||
107 | .num_ports = 1, | ||
108 | .probe = nokia_probe, | ||
109 | }; | ||
110 | |||
111 | static int __init nokia_init(void) | ||
112 | { | ||
113 | int retval; | ||
114 | |||
115 | retval = usb_serial_register(&nokia_serial_driver); | ||
116 | if (retval) | ||
117 | return retval; | ||
118 | |||
119 | retval = usb_register(&nokia_driver); | ||
120 | if (retval) { | ||
121 | usb_serial_deregister(&nokia_serial_driver); | ||
122 | return retval; | ||
123 | } | ||
124 | |||
125 | info(DRIVER_VERSION " " DRIVER_AUTHOR); | ||
126 | info(DRIVER_DESC); | ||
127 | |||
128 | return retval; | ||
129 | } | ||
130 | |||
131 | static void __exit nokia_exit(void) | ||
132 | { | ||
133 | usb_deregister(&nokia_driver); | ||
134 | usb_serial_deregister(&nokia_serial_driver); | ||
135 | } | ||
136 | |||
137 | module_init(nokia_init); | ||
138 | module_exit(nokia_exit); | ||
139 | |||
140 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
141 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
142 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 165c119bf10e..41a45a5025b2 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -71,7 +71,9 @@ static struct usb_device_id id_table [] = { | |||
71 | { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, | 71 | { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, |
72 | { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, | 72 | { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, |
73 | { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, | 73 | { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, |
74 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) }, | ||
74 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, | 75 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) }, |
76 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) }, | ||
75 | { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, | 77 | { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, |
76 | { USB_DEVICE( NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) }, | 78 | { USB_DEVICE( NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID ) }, |
77 | { } /* Terminating entry */ | 79 | { } /* Terminating entry */ |
@@ -811,7 +813,9 @@ static void pl2303_update_line_status(struct usb_serial_port *port, | |||
811 | u8 length = UART_STATE; | 813 | u8 length = UART_STATE; |
812 | 814 | ||
813 | if ((le16_to_cpu(port->serial->dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) && | 815 | if ((le16_to_cpu(port->serial->dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) && |
814 | (le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X65)) { | 816 | (le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X65 || |
817 | le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_SX1 || | ||
818 | le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X75)) { | ||
815 | length = 1; | 819 | length = 1; |
816 | status_idx = 0; | 820 | status_idx = 0; |
817 | } | 821 | } |
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 7be9644f5a03..21d434d81813 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h | |||
@@ -54,7 +54,9 @@ | |||
54 | #define SAMSUNG_PRODUCT_ID 0x8001 | 54 | #define SAMSUNG_PRODUCT_ID 0x8001 |
55 | 55 | ||
56 | #define SIEMENS_VENDOR_ID 0x11f5 | 56 | #define SIEMENS_VENDOR_ID 0x11f5 |
57 | #define SIEMENS_PRODUCT_ID_SX1 0x0001 | ||
57 | #define SIEMENS_PRODUCT_ID_X65 0x0003 | 58 | #define SIEMENS_PRODUCT_ID_X65 0x0003 |
59 | #define SIEMENS_PRODUCT_ID_X75 0x0004 | ||
58 | 60 | ||
59 | #define SYNTECH_VENDOR_ID 0x0745 | 61 | #define SYNTECH_VENDOR_ID 0x0745 |
60 | #define SYNTECH_PRODUCT_ID 0x0001 | 62 | #define SYNTECH_PRODUCT_ID 0x0001 |
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 1a9679f76f5a..c41d64dbb0f0 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig | |||
@@ -115,7 +115,7 @@ config USB_STORAGE_JUMPSHOT | |||
115 | 115 | ||
116 | config USB_STORAGE_ONETOUCH | 116 | config USB_STORAGE_ONETOUCH |
117 | bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)" | 117 | bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)" |
118 | depends on USB_STORAGE && INPUT_EVDEV && EXPERIMENTAL | 118 | depends on USB_STORAGE && INPUT_EVDEV && EXPERIMENTAL && !PM |
119 | help | 119 | help |
120 | Say Y here to include additional code to support the Maxtor OneTouch | 120 | Say Y here to include additional code to support the Maxtor OneTouch |
121 | USB hard drive's onetouch button. | 121 | USB hard drive's onetouch button. |
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index 33c55a6261bb..fea176d7e79a 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c | |||
@@ -853,7 +853,7 @@ static int usbat_identify_device(struct us_data *us, | |||
853 | rc = usbat_device_reset(us); | 853 | rc = usbat_device_reset(us); |
854 | if (rc != USB_STOR_TRANSPORT_GOOD) | 854 | if (rc != USB_STOR_TRANSPORT_GOOD) |
855 | return rc; | 855 | return rc; |
856 | msleep(25); | 856 | msleep(500); |
857 | 857 | ||
858 | /* | 858 | /* |
859 | * In attempt to distinguish between HP CDRW's and Flash readers, we now | 859 | * In attempt to distinguish between HP CDRW's and Flash readers, we now |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 9e926a8f2116..0a9858f69a9b 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -710,11 +710,6 @@ UNUSUAL_DEV( 0x0686, 0x4017, 0x0001, 0x0001, | |||
710 | "DIMAGE E223", | 710 | "DIMAGE E223", |
711 | US_SC_SCSI, US_PR_DEVICE, NULL, 0 ), | 711 | US_SC_SCSI, US_PR_DEVICE, NULL, 0 ), |
712 | 712 | ||
713 | UNUSUAL_DEV( 0x0693, 0x0002, 0x0100, 0x0100, | ||
714 | "Hagiwara", | ||
715 | "FlashGate SmartMedia", | ||
716 | US_SC_SCSI, US_PR_BULK, NULL, 0 ), | ||
717 | |||
718 | UNUSUAL_DEV( 0x0693, 0x0005, 0x0100, 0x0100, | 713 | UNUSUAL_DEV( 0x0693, 0x0005, 0x0100, 0x0100, |
719 | "Hagiwara", | 714 | "Hagiwara", |
720 | "Flashgate", | 715 | "Flashgate", |
@@ -1008,6 +1003,11 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, | |||
1008 | * | 1003 | * |
1009 | */ | 1004 | */ |
1010 | #ifdef CONFIG_USB_STORAGE_ONETOUCH | 1005 | #ifdef CONFIG_USB_STORAGE_ONETOUCH |
1006 | UNUSUAL_DEV( 0x0d49, 0x7000, 0x0000, 0x9999, | ||
1007 | "Maxtor", | ||
1008 | "OneTouch External Harddrive", | ||
1009 | US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, | ||
1010 | 0), | ||
1011 | UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999, | 1011 | UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999, |
1012 | "Maxtor", | 1012 | "Maxtor", |
1013 | "OneTouch External Harddrive", | 1013 | "OneTouch External Harddrive", |
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index f53bf3ba1278..d3728f60961e 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c | |||
@@ -51,6 +51,9 @@ static struct fb_ops bw2_ops = { | |||
51 | .fb_imageblit = cfb_imageblit, | 51 | .fb_imageblit = cfb_imageblit, |
52 | .fb_mmap = bw2_mmap, | 52 | .fb_mmap = bw2_mmap, |
53 | .fb_ioctl = bw2_ioctl, | 53 | .fb_ioctl = bw2_ioctl, |
54 | #ifdef CONFIG_COMPAT | ||
55 | .fb_compat_ioctl = sbusfb_compat_ioctl, | ||
56 | #endif | ||
54 | }; | 57 | }; |
55 | 58 | ||
56 | /* OBio addresses for the bwtwo registers */ | 59 | /* OBio addresses for the bwtwo registers */ |
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index 030d4b13b1c2..1bed50f2a276 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c | |||
@@ -49,6 +49,9 @@ static struct fb_ops cg14_ops = { | |||
49 | .fb_imageblit = cfb_imageblit, | 49 | .fb_imageblit = cfb_imageblit, |
50 | .fb_mmap = cg14_mmap, | 50 | .fb_mmap = cg14_mmap, |
51 | .fb_ioctl = cg14_ioctl, | 51 | .fb_ioctl = cg14_ioctl, |
52 | #ifdef CONFIG_COMPAT | ||
53 | .fb_compat_ioctl = sbusfb_compat_ioctl, | ||
54 | #endif | ||
52 | }; | 55 | }; |
53 | 56 | ||
54 | #define CG14_MCR_INTENABLE_SHIFT 7 | 57 | #define CG14_MCR_INTENABLE_SHIFT 7 |
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index b94eee8c42d5..a1354e7e0513 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c | |||
@@ -50,6 +50,9 @@ static struct fb_ops cg3_ops = { | |||
50 | .fb_imageblit = cfb_imageblit, | 50 | .fb_imageblit = cfb_imageblit, |
51 | .fb_mmap = cg3_mmap, | 51 | .fb_mmap = cg3_mmap, |
52 | .fb_ioctl = cg3_ioctl, | 52 | .fb_ioctl = cg3_ioctl, |
53 | #ifdef CONFIG_COMPAT | ||
54 | .fb_compat_ioctl = sbusfb_compat_ioctl, | ||
55 | #endif | ||
53 | }; | 56 | }; |
54 | 57 | ||
55 | 58 | ||
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 414c4409e924..9debe642fd2f 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c | |||
@@ -54,6 +54,9 @@ static struct fb_ops cg6_ops = { | |||
54 | .fb_sync = cg6_sync, | 54 | .fb_sync = cg6_sync, |
55 | .fb_mmap = cg6_mmap, | 55 | .fb_mmap = cg6_mmap, |
56 | .fb_ioctl = cg6_ioctl, | 56 | .fb_ioctl = cg6_ioctl, |
57 | #ifdef CONFIG_COMPAT | ||
58 | .fb_compat_ioctl = sbusfb_compat_ioctl, | ||
59 | #endif | ||
57 | }; | 60 | }; |
58 | 61 | ||
59 | /* Offset of interesting structures in the OBIO space */ | 62 | /* Offset of interesting structures in the OBIO space */ |
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 94c5f1392cce..5f74df993406 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig | |||
@@ -215,12 +215,5 @@ config FONT_10x18 | |||
215 | big letters. It fits between the sun 12x22 and the normal 8x16 font. | 215 | big letters. It fits between the sun 12x22 and the normal 8x16 font. |
216 | If other fonts are too big or too small for you, say Y, otherwise say N. | 216 | If other fonts are too big or too small for you, say Y, otherwise say N. |
217 | 217 | ||
218 | config FONT_RL | ||
219 | bool "console Roman Large 8x16 font" if FONTS | ||
220 | depends on FRAMEBUFFER_CONSOLE | ||
221 | help | ||
222 | This is the visually-appealing "RL" console font that is | ||
223 | included with the kbd package. | ||
224 | |||
225 | endmenu | 218 | endmenu |
226 | 219 | ||
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index fed600c9ca55..9b26dda18a38 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile | |||
@@ -15,7 +15,6 @@ font-objs-$(CONFIG_FONT_10x18) += font_10x18.o | |||
15 | font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o | 15 | font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o |
16 | font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o | 16 | font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o |
17 | font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o | 17 | font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o |
18 | font-objs-$(CONFIG_FONT_RL) += font_rl.o | ||
19 | 18 | ||
20 | font-objs += $(font-objs-y) | 19 | font-objs += $(font-objs-y) |
21 | 20 | ||
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index e7802ffe549a..bcea87c3cc06 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -106,8 +106,7 @@ enum { | |||
106 | FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ | 106 | FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ |
107 | }; | 107 | }; |
108 | 108 | ||
109 | struct display fb_display[MAX_NR_CONSOLES]; | 109 | static struct display fb_display[MAX_NR_CONSOLES]; |
110 | EXPORT_SYMBOL(fb_display); | ||
111 | 110 | ||
112 | static signed char con2fb_map[MAX_NR_CONSOLES]; | 111 | static signed char con2fb_map[MAX_NR_CONSOLES]; |
113 | static signed char con2fb_map_boot[MAX_NR_CONSOLES]; | 112 | static signed char con2fb_map_boot[MAX_NR_CONSOLES]; |
@@ -653,13 +652,12 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info, | |||
653 | { | 652 | { |
654 | struct fbcon_ops *ops = info->fbcon_par; | 653 | struct fbcon_ops *ops = info->fbcon_par; |
655 | 654 | ||
655 | ops->p = (p) ? p : &fb_display[vc->vc_num]; | ||
656 | |||
656 | if ((info->flags & FBINFO_MISC_TILEBLITTING)) | 657 | if ((info->flags & FBINFO_MISC_TILEBLITTING)) |
657 | fbcon_set_tileops(vc, info, p, ops); | 658 | fbcon_set_tileops(vc, info, p, ops); |
658 | else { | 659 | else { |
659 | struct display *disp; | 660 | fbcon_set_rotation(info, ops->p); |
660 | |||
661 | disp = (p) ? p : &fb_display[vc->vc_num]; | ||
662 | fbcon_set_rotation(info, disp); | ||
663 | fbcon_set_bitops(ops); | 661 | fbcon_set_bitops(ops); |
664 | } | 662 | } |
665 | } | 663 | } |
@@ -668,11 +666,10 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info, | |||
668 | struct display *p) | 666 | struct display *p) |
669 | { | 667 | { |
670 | struct fbcon_ops *ops = info->fbcon_par; | 668 | struct fbcon_ops *ops = info->fbcon_par; |
671 | struct display *disp; | ||
672 | 669 | ||
673 | info->flags &= ~FBINFO_MISC_TILEBLITTING; | 670 | info->flags &= ~FBINFO_MISC_TILEBLITTING; |
674 | disp = (p) ? p : &fb_display[vc->vc_num]; | 671 | ops->p = (p) ? p : &fb_display[vc->vc_num]; |
675 | fbcon_set_rotation(info, disp); | 672 | fbcon_set_rotation(info, ops->p); |
676 | fbcon_set_bitops(ops); | 673 | fbcon_set_bitops(ops); |
677 | } | 674 | } |
678 | #endif /* CONFIG_MISC_TILEBLITTING */ | 675 | #endif /* CONFIG_MISC_TILEBLITTING */ |
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index accfd7bd8e93..6892e7ff34de 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h | |||
@@ -52,8 +52,6 @@ struct display { | |||
52 | struct fb_videomode *mode; | 52 | struct fb_videomode *mode; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | extern struct display fb_display[]; | ||
56 | |||
57 | struct fbcon_ops { | 55 | struct fbcon_ops { |
58 | void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, | 56 | void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, |
59 | int sx, int dy, int dx, int height, int width); | 57 | int sx, int dy, int dx, int height, int width); |
@@ -73,6 +71,7 @@ struct fbcon_ops { | |||
73 | struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ | 71 | struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ |
74 | struct timer_list cursor_timer; /* Cursor timer */ | 72 | struct timer_list cursor_timer; /* Cursor timer */ |
75 | struct fb_cursor cursor_state; | 73 | struct fb_cursor cursor_state; |
74 | struct display *p; | ||
76 | int currcon; /* Current VC. */ | 75 | int currcon; /* Current VC. */ |
77 | int cursor_flash; | 76 | int cursor_flash; |
78 | int cursor_reset; | 77 | int cursor_reset; |
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c index 680aabab73c5..3afd1eeb1ade 100644 --- a/drivers/video/console/fbcon_ccw.c +++ b/drivers/video/console/fbcon_ccw.c | |||
@@ -63,9 +63,9 @@ static inline void ccw_update_attr(u8 *dst, u8 *src, int attribute, | |||
63 | static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | 63 | static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, |
64 | int sx, int dy, int dx, int height, int width) | 64 | int sx, int dy, int dx, int height, int width) |
65 | { | 65 | { |
66 | struct display *p = &fb_display[vc->vc_num]; | 66 | struct fbcon_ops *ops = info->fbcon_par; |
67 | struct fb_copyarea area; | 67 | struct fb_copyarea area; |
68 | u32 vyres = GETVYRES(p->scrollmode, info); | 68 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
69 | 69 | ||
70 | area.sx = sy * vc->vc_font.height; | 70 | area.sx = sy * vc->vc_font.height; |
71 | area.sy = vyres - ((sx + width) * vc->vc_font.width); | 71 | area.sy = vyres - ((sx + width) * vc->vc_font.width); |
@@ -80,10 +80,10 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |||
80 | static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, | 80 | static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, |
81 | int sx, int height, int width) | 81 | int sx, int height, int width) |
82 | { | 82 | { |
83 | struct display *p = &fb_display[vc->vc_num]; | 83 | struct fbcon_ops *ops = info->fbcon_par; |
84 | struct fb_fillrect region; | 84 | struct fb_fillrect region; |
85 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 85 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
86 | u32 vyres = GETVYRES(p->scrollmode, info); | 86 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
87 | 87 | ||
88 | region.color = attr_bgcol_ec(bgshift,vc); | 88 | region.color = attr_bgcol_ec(bgshift,vc); |
89 | region.dx = sy * vc->vc_font.height; | 89 | region.dx = sy * vc->vc_font.height; |
@@ -131,7 +131,6 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info, | |||
131 | int fg, int bg) | 131 | int fg, int bg) |
132 | { | 132 | { |
133 | struct fb_image image; | 133 | struct fb_image image; |
134 | struct display *p = &fb_display[vc->vc_num]; | ||
135 | struct fbcon_ops *ops = info->fbcon_par; | 134 | struct fbcon_ops *ops = info->fbcon_par; |
136 | u32 width = (vc->vc_font.height + 7)/8; | 135 | u32 width = (vc->vc_font.height + 7)/8; |
137 | u32 cellsize = width * vc->vc_font.width; | 136 | u32 cellsize = width * vc->vc_font.width; |
@@ -141,7 +140,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info, | |||
141 | u32 cnt, pitch, size; | 140 | u32 cnt, pitch, size; |
142 | u32 attribute = get_attribute(info, scr_readw(s)); | 141 | u32 attribute = get_attribute(info, scr_readw(s)); |
143 | u8 *dst, *buf = NULL; | 142 | u8 *dst, *buf = NULL; |
144 | u32 vyres = GETVYRES(p->scrollmode, info); | 143 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
145 | 144 | ||
146 | if (!ops->fontbuffer) | 145 | if (!ops->fontbuffer) |
147 | return; | 146 | return; |
@@ -397,9 +396,8 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, | |||
397 | int ccw_update_start(struct fb_info *info) | 396 | int ccw_update_start(struct fb_info *info) |
398 | { | 397 | { |
399 | struct fbcon_ops *ops = info->fbcon_par; | 398 | struct fbcon_ops *ops = info->fbcon_par; |
400 | struct display *p = &fb_display[ops->currcon]; | ||
401 | u32 yoffset; | 399 | u32 yoffset; |
402 | u32 vyres = GETVYRES(p->scrollmode, info); | 400 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
403 | int err; | 401 | int err; |
404 | 402 | ||
405 | yoffset = (vyres - info->var.yres) - ops->var.xoffset; | 403 | yoffset = (vyres - info->var.yres) - ops->var.xoffset; |
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c index 6c6f3b6dd175..6d92b8456206 100644 --- a/drivers/video/console/fbcon_cw.c +++ b/drivers/video/console/fbcon_cw.c | |||
@@ -49,9 +49,9 @@ static inline void cw_update_attr(u8 *dst, u8 *src, int attribute, | |||
49 | static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | 49 | static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, |
50 | int sx, int dy, int dx, int height, int width) | 50 | int sx, int dy, int dx, int height, int width) |
51 | { | 51 | { |
52 | struct display *p = &fb_display[vc->vc_num]; | 52 | struct fbcon_ops *ops = info->fbcon_par; |
53 | struct fb_copyarea area; | 53 | struct fb_copyarea area; |
54 | u32 vxres = GETVXRES(p->scrollmode, info); | 54 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
55 | 55 | ||
56 | area.sx = vxres - ((sy + height) * vc->vc_font.height); | 56 | area.sx = vxres - ((sy + height) * vc->vc_font.height); |
57 | area.sy = sx * vc->vc_font.width; | 57 | area.sy = sx * vc->vc_font.width; |
@@ -66,10 +66,10 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |||
66 | static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, | 66 | static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, |
67 | int sx, int height, int width) | 67 | int sx, int height, int width) |
68 | { | 68 | { |
69 | struct display *p = &fb_display[vc->vc_num]; | 69 | struct fbcon_ops *ops = info->fbcon_par; |
70 | struct fb_fillrect region; | 70 | struct fb_fillrect region; |
71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
72 | u32 vxres = GETVXRES(p->scrollmode, info); | 72 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
73 | 73 | ||
74 | region.color = attr_bgcol_ec(bgshift,vc); | 74 | region.color = attr_bgcol_ec(bgshift,vc); |
75 | region.dx = vxres - ((sy + height) * vc->vc_font.height); | 75 | region.dx = vxres - ((sy + height) * vc->vc_font.height); |
@@ -117,7 +117,6 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info, | |||
117 | int fg, int bg) | 117 | int fg, int bg) |
118 | { | 118 | { |
119 | struct fb_image image; | 119 | struct fb_image image; |
120 | struct display *p = &fb_display[vc->vc_num]; | ||
121 | struct fbcon_ops *ops = info->fbcon_par; | 120 | struct fbcon_ops *ops = info->fbcon_par; |
122 | u32 width = (vc->vc_font.height + 7)/8; | 121 | u32 width = (vc->vc_font.height + 7)/8; |
123 | u32 cellsize = width * vc->vc_font.width; | 122 | u32 cellsize = width * vc->vc_font.width; |
@@ -127,7 +126,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info, | |||
127 | u32 cnt, pitch, size; | 126 | u32 cnt, pitch, size; |
128 | u32 attribute = get_attribute(info, scr_readw(s)); | 127 | u32 attribute = get_attribute(info, scr_readw(s)); |
129 | u8 *dst, *buf = NULL; | 128 | u8 *dst, *buf = NULL; |
130 | u32 vxres = GETVXRES(p->scrollmode, info); | 129 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
131 | 130 | ||
132 | if (!ops->fontbuffer) | 131 | if (!ops->fontbuffer) |
133 | return; | 132 | return; |
@@ -381,8 +380,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, | |||
381 | int cw_update_start(struct fb_info *info) | 380 | int cw_update_start(struct fb_info *info) |
382 | { | 381 | { |
383 | struct fbcon_ops *ops = info->fbcon_par; | 382 | struct fbcon_ops *ops = info->fbcon_par; |
384 | struct display *p = &fb_display[ops->currcon]; | 383 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
385 | u32 vxres = GETVXRES(p->scrollmode, info); | ||
386 | u32 xoffset; | 384 | u32 xoffset; |
387 | int err; | 385 | int err; |
388 | 386 | ||
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c index 2e1d9d4249cd..c4d7c89212b4 100644 --- a/drivers/video/console/fbcon_ud.c +++ b/drivers/video/console/fbcon_ud.c | |||
@@ -48,10 +48,10 @@ static inline void ud_update_attr(u8 *dst, u8 *src, int attribute, | |||
48 | static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, | 48 | static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, |
49 | int sx, int dy, int dx, int height, int width) | 49 | int sx, int dy, int dx, int height, int width) |
50 | { | 50 | { |
51 | struct display *p = &fb_display[vc->vc_num]; | 51 | struct fbcon_ops *ops = info->fbcon_par; |
52 | struct fb_copyarea area; | 52 | struct fb_copyarea area; |
53 | u32 vyres = GETVYRES(p->scrollmode, info); | 53 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
54 | u32 vxres = GETVXRES(p->scrollmode, info); | 54 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
55 | 55 | ||
56 | area.sy = vyres - ((sy + height) * vc->vc_font.height); | 56 | area.sy = vyres - ((sy + height) * vc->vc_font.height); |
57 | area.sx = vxres - ((sx + width) * vc->vc_font.width); | 57 | area.sx = vxres - ((sx + width) * vc->vc_font.width); |
@@ -66,11 +66,11 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, | |||
66 | static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, | 66 | static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, |
67 | int sx, int height, int width) | 67 | int sx, int height, int width) |
68 | { | 68 | { |
69 | struct display *p = &fb_display[vc->vc_num]; | 69 | struct fbcon_ops *ops = info->fbcon_par; |
70 | struct fb_fillrect region; | 70 | struct fb_fillrect region; |
71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 71 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
72 | u32 vyres = GETVYRES(p->scrollmode, info); | 72 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
73 | u32 vxres = GETVXRES(p->scrollmode, info); | 73 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
74 | 74 | ||
75 | region.color = attr_bgcol_ec(bgshift,vc); | 75 | region.color = attr_bgcol_ec(bgshift,vc); |
76 | region.dy = vyres - ((sy + height) * vc->vc_font.height); | 76 | region.dy = vyres - ((sy + height) * vc->vc_font.height); |
@@ -153,7 +153,6 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info, | |||
153 | int fg, int bg) | 153 | int fg, int bg) |
154 | { | 154 | { |
155 | struct fb_image image; | 155 | struct fb_image image; |
156 | struct display *p = &fb_display[vc->vc_num]; | ||
157 | struct fbcon_ops *ops = info->fbcon_par; | 156 | struct fbcon_ops *ops = info->fbcon_par; |
158 | u32 width = (vc->vc_font.width + 7)/8; | 157 | u32 width = (vc->vc_font.width + 7)/8; |
159 | u32 cellsize = width * vc->vc_font.height; | 158 | u32 cellsize = width * vc->vc_font.height; |
@@ -163,8 +162,8 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info, | |||
163 | u32 mod = vc->vc_font.width % 8, cnt, pitch, size; | 162 | u32 mod = vc->vc_font.width % 8, cnt, pitch, size; |
164 | u32 attribute = get_attribute(info, scr_readw(s)); | 163 | u32 attribute = get_attribute(info, scr_readw(s)); |
165 | u8 *dst, *buf = NULL; | 164 | u8 *dst, *buf = NULL; |
166 | u32 vyres = GETVYRES(p->scrollmode, info); | 165 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
167 | u32 vxres = GETVXRES(p->scrollmode, info); | 166 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
168 | 167 | ||
169 | if (!ops->fontbuffer) | 168 | if (!ops->fontbuffer) |
170 | return; | 169 | return; |
@@ -421,10 +420,9 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, | |||
421 | int ud_update_start(struct fb_info *info) | 420 | int ud_update_start(struct fb_info *info) |
422 | { | 421 | { |
423 | struct fbcon_ops *ops = info->fbcon_par; | 422 | struct fbcon_ops *ops = info->fbcon_par; |
424 | struct display *p = &fb_display[ops->currcon]; | ||
425 | u32 xoffset, yoffset; | 423 | u32 xoffset, yoffset; |
426 | u32 vyres = GETVYRES(p->scrollmode, info); | 424 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
427 | u32 vxres = GETVXRES(p->scrollmode, info); | 425 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
428 | int err; | 426 | int err; |
429 | 427 | ||
430 | xoffset = (vxres - info->var.xres) - ops->var.xoffset; | 428 | xoffset = (vxres - info->var.xres) - ops->var.xoffset; |
diff --git a/drivers/video/console/font_rl.c b/drivers/video/console/font_rl.c deleted file mode 100644 index dfecc27d8ded..000000000000 --- a/drivers/video/console/font_rl.c +++ /dev/null | |||
@@ -1,4374 +0,0 @@ | |||
1 | |||
2 | /* This font is simply the "rl.fnt" console font from the kbd utility. | ||
3 | * Converted by Zack T Smith, fbui@comcast.net. | ||
4 | * The original binary file is covered under the GNU Public License. | ||
5 | */ | ||
6 | |||
7 | #include <linux/font.h> | ||
8 | |||
9 | #define FONTDATAMAX 4096 | ||
10 | |||
11 | static unsigned char patterns[4096] = { | ||
12 | 0x00, | ||
13 | 0x00, | ||
14 | 0x00, | ||
15 | 0x00, | ||
16 | 0x00, | ||
17 | 0x00, | ||
18 | 0x00, | ||
19 | 0x00, | ||
20 | 0x00, | ||
21 | 0x00, | ||
22 | 0x00, | ||
23 | 0x00, | ||
24 | 0x00, | ||
25 | 0x00, | ||
26 | 0x00, | ||
27 | 0x00, | ||
28 | |||
29 | 0x00, | ||
30 | 0x00, | ||
31 | 0x3c, | ||
32 | 0x42, | ||
33 | 0x81, | ||
34 | 0xe7, | ||
35 | 0xa5, | ||
36 | 0x99, | ||
37 | 0x81, | ||
38 | 0x81, | ||
39 | 0x99, | ||
40 | 0x42, | ||
41 | 0x3c, | ||
42 | 0x00, | ||
43 | 0x00, | ||
44 | 0x00, | ||
45 | |||
46 | 0x00, | ||
47 | 0x00, | ||
48 | 0x3c, | ||
49 | 0x7e, | ||
50 | 0xff, | ||
51 | 0x99, | ||
52 | 0xdb, | ||
53 | 0xe7, | ||
54 | 0xff, | ||
55 | 0xff, | ||
56 | 0xe7, | ||
57 | 0x7e, | ||
58 | 0x3c, | ||
59 | 0x00, | ||
60 | 0x00, | ||
61 | 0x00, | ||
62 | |||
63 | 0x00, | ||
64 | 0x00, | ||
65 | 0x00, | ||
66 | 0x6c, | ||
67 | 0xfe, | ||
68 | 0xfe, | ||
69 | 0xfe, | ||
70 | 0xfe, | ||
71 | 0xfe, | ||
72 | 0x7c, | ||
73 | 0x38, | ||
74 | 0x10, | ||
75 | 0x00, | ||
76 | 0x00, | ||
77 | 0x00, | ||
78 | 0x00, | ||
79 | |||
80 | 0x00, | ||
81 | 0x00, | ||
82 | 0x00, | ||
83 | 0x00, | ||
84 | 0x10, | ||
85 | 0x38, | ||
86 | 0x7c, | ||
87 | 0xfe, | ||
88 | 0x7c, | ||
89 | 0x38, | ||
90 | 0x10, | ||
91 | 0x00, | ||
92 | 0x00, | ||
93 | 0x00, | ||
94 | 0x00, | ||
95 | 0x00, | ||
96 | |||
97 | 0x00, | ||
98 | 0x00, | ||
99 | 0x38, | ||
100 | 0x38, | ||
101 | 0x10, | ||
102 | 0xd6, | ||
103 | 0xfe, | ||
104 | 0xd6, | ||
105 | 0x10, | ||
106 | 0x10, | ||
107 | 0x38, | ||
108 | 0x7c, | ||
109 | 0x00, | ||
110 | 0x00, | ||
111 | 0x00, | ||
112 | 0x00, | ||
113 | |||
114 | 0x00, | ||
115 | 0x00, | ||
116 | 0x10, | ||
117 | 0x38, | ||
118 | 0x7c, | ||
119 | 0xfe, | ||
120 | 0xfe, | ||
121 | 0x54, | ||
122 | 0x10, | ||
123 | 0x10, | ||
124 | 0x38, | ||
125 | 0x7c, | ||
126 | 0x00, | ||
127 | 0x00, | ||
128 | 0x00, | ||
129 | 0x00, | ||
130 | |||
131 | 0x00, | ||
132 | 0x00, | ||
133 | 0x00, | ||
134 | 0x00, | ||
135 | 0x00, | ||
136 | 0x00, | ||
137 | 0x18, | ||
138 | 0x3c, | ||
139 | 0x3c, | ||
140 | 0x18, | ||
141 | 0x00, | ||
142 | 0x00, | ||
143 | 0x00, | ||
144 | 0x00, | ||
145 | 0x00, | ||
146 | 0x00, | ||
147 | |||
148 | 0xff, | ||
149 | 0xff, | ||
150 | 0xff, | ||
151 | 0xff, | ||
152 | 0xff, | ||
153 | 0xff, | ||
154 | 0xe7, | ||
155 | 0xc3, | ||
156 | 0xc3, | ||
157 | 0xe7, | ||
158 | 0xff, | ||
159 | 0xff, | ||
160 | 0xff, | ||
161 | 0xff, | ||
162 | 0xff, | ||
163 | 0xff, | ||
164 | |||
165 | 0x00, | ||
166 | 0x00, | ||
167 | 0x00, | ||
168 | 0x00, | ||
169 | 0x00, | ||
170 | 0x3c, | ||
171 | 0x66, | ||
172 | 0x42, | ||
173 | 0x42, | ||
174 | 0x66, | ||
175 | 0x3c, | ||
176 | 0x00, | ||
177 | 0x00, | ||
178 | 0x00, | ||
179 | 0x00, | ||
180 | 0x00, | ||
181 | |||
182 | 0xff, | ||
183 | 0xff, | ||
184 | 0xff, | ||
185 | 0xff, | ||
186 | 0xff, | ||
187 | 0xc3, | ||
188 | 0x99, | ||
189 | 0xbd, | ||
190 | 0xbd, | ||
191 | 0x99, | ||
192 | 0xc3, | ||
193 | 0xff, | ||
194 | 0xff, | ||
195 | 0xff, | ||
196 | 0xff, | ||
197 | 0xff, | ||
198 | |||
199 | 0x00, | ||
200 | 0x00, | ||
201 | 0x0f, | ||
202 | 0x07, | ||
203 | 0x0d, | ||
204 | 0x18, | ||
205 | 0x78, | ||
206 | 0xcc, | ||
207 | 0xcc, | ||
208 | 0xcc, | ||
209 | 0xcc, | ||
210 | 0x78, | ||
211 | 0x00, | ||
212 | 0x00, | ||
213 | 0x00, | ||
214 | 0x00, | ||
215 | |||
216 | 0x00, | ||
217 | 0x00, | ||
218 | 0x3c, | ||
219 | 0x66, | ||
220 | 0x66, | ||
221 | 0x66, | ||
222 | 0x3c, | ||
223 | 0x18, | ||
224 | 0x7e, | ||
225 | 0x18, | ||
226 | 0x18, | ||
227 | 0x18, | ||
228 | 0x00, | ||
229 | 0x00, | ||
230 | 0x00, | ||
231 | 0x00, | ||
232 | |||
233 | 0x00, | ||
234 | 0x08, | ||
235 | 0x0c, | ||
236 | 0x0a, | ||
237 | 0x0a, | ||
238 | 0x0a, | ||
239 | 0x08, | ||
240 | 0x08, | ||
241 | 0x08, | ||
242 | 0x38, | ||
243 | 0x78, | ||
244 | 0x30, | ||
245 | 0x00, | ||
246 | 0x00, | ||
247 | 0x00, | ||
248 | 0x00, | ||
249 | |||
250 | 0x00, | ||
251 | 0x10, | ||
252 | 0x18, | ||
253 | 0x1c, | ||
254 | 0x1e, | ||
255 | 0x1e, | ||
256 | 0x16, | ||
257 | 0x12, | ||
258 | 0x72, | ||
259 | 0xf2, | ||
260 | 0x62, | ||
261 | 0x0e, | ||
262 | 0x1e, | ||
263 | 0x0c, | ||
264 | 0x00, | ||
265 | 0x00, | ||
266 | |||
267 | 0x00, | ||
268 | 0x00, | ||
269 | 0x00, | ||
270 | 0x10, | ||
271 | 0x92, | ||
272 | 0x54, | ||
273 | 0x38, | ||
274 | 0xfe, | ||
275 | 0x38, | ||
276 | 0x54, | ||
277 | 0x92, | ||
278 | 0x10, | ||
279 | 0x00, | ||
280 | 0x00, | ||
281 | 0x00, | ||
282 | 0x00, | ||
283 | |||
284 | 0x00, | ||
285 | 0x00, | ||
286 | 0x00, | ||
287 | 0x80, | ||
288 | 0xc0, | ||
289 | 0xe0, | ||
290 | 0xb8, | ||
291 | 0x8e, | ||
292 | 0xb8, | ||
293 | 0xe0, | ||
294 | 0xc0, | ||
295 | 0x80, | ||
296 | 0x00, | ||
297 | 0x00, | ||
298 | 0x00, | ||
299 | 0x00, | ||
300 | |||
301 | 0x00, | ||
302 | 0x00, | ||
303 | 0x00, | ||
304 | 0x02, | ||
305 | 0x06, | ||
306 | 0x0e, | ||
307 | 0x3a, | ||
308 | 0xe2, | ||
309 | 0x3a, | ||
310 | 0x0e, | ||
311 | 0x06, | ||
312 | 0x02, | ||
313 | 0x00, | ||
314 | 0x00, | ||
315 | 0x00, | ||
316 | 0x00, | ||
317 | |||
318 | 0x00, | ||
319 | 0x00, | ||
320 | 0x10, | ||
321 | 0x38, | ||
322 | 0x7c, | ||
323 | 0xd6, | ||
324 | 0x10, | ||
325 | 0x10, | ||
326 | 0x10, | ||
327 | 0x10, | ||
328 | 0xd6, | ||
329 | 0x7c, | ||
330 | 0x38, | ||
331 | 0x10, | ||
332 | 0x00, | ||
333 | 0x00, | ||
334 | |||
335 | 0x00, | ||
336 | 0x42, | ||
337 | 0xe7, | ||
338 | 0xe7, | ||
339 | 0xe7, | ||
340 | 0xe7, | ||
341 | 0x42, | ||
342 | 0x42, | ||
343 | 0x42, | ||
344 | 0x00, | ||
345 | 0x66, | ||
346 | 0x66, | ||
347 | 0x66, | ||
348 | 0x00, | ||
349 | 0x00, | ||
350 | 0x00, | ||
351 | |||
352 | 0x00, | ||
353 | 0x7f, | ||
354 | 0xca, | ||
355 | 0xca, | ||
356 | 0xca, | ||
357 | 0xca, | ||
358 | 0x7a, | ||
359 | 0x0a, | ||
360 | 0x0a, | ||
361 | 0x0a, | ||
362 | 0x0a, | ||
363 | 0x0a, | ||
364 | 0x1b, | ||
365 | 0x00, | ||
366 | 0x00, | ||
367 | 0x00, | ||
368 | |||
369 | 0x00, | ||
370 | 0x1e, | ||
371 | 0x31, | ||
372 | 0x78, | ||
373 | 0xcc, | ||
374 | 0xc6, | ||
375 | 0xc3, | ||
376 | 0x63, | ||
377 | 0x33, | ||
378 | 0x1e, | ||
379 | 0x8c, | ||
380 | 0x78, | ||
381 | 0x00, | ||
382 | 0x00, | ||
383 | 0x00, | ||
384 | 0x00, | ||
385 | |||
386 | 0x00, | ||
387 | 0x00, | ||
388 | 0x00, | ||
389 | 0x00, | ||
390 | 0x00, | ||
391 | 0x00, | ||
392 | 0x00, | ||
393 | 0x00, | ||
394 | 0xfe, | ||
395 | 0xfe, | ||
396 | 0xfe, | ||
397 | 0xfe, | ||
398 | 0x00, | ||
399 | 0x00, | ||
400 | 0x00, | ||
401 | 0x00, | ||
402 | |||
403 | 0x00, | ||
404 | 0x00, | ||
405 | 0x10, | ||
406 | 0x38, | ||
407 | 0x7c, | ||
408 | 0xd6, | ||
409 | 0x10, | ||
410 | 0x10, | ||
411 | 0x10, | ||
412 | 0x10, | ||
413 | 0xd6, | ||
414 | 0x7c, | ||
415 | 0x38, | ||
416 | 0x10, | ||
417 | 0xfe, | ||
418 | 0x00, | ||
419 | |||
420 | 0x00, | ||
421 | 0x00, | ||
422 | 0x10, | ||
423 | 0x38, | ||
424 | 0x7c, | ||
425 | 0xd6, | ||
426 | 0x10, | ||
427 | 0x10, | ||
428 | 0x10, | ||
429 | 0x10, | ||
430 | 0x10, | ||
431 | 0x10, | ||
432 | 0x10, | ||
433 | 0x10, | ||
434 | 0x00, | ||
435 | 0x00, | ||
436 | |||
437 | 0x00, | ||
438 | 0x00, | ||
439 | 0x10, | ||
440 | 0x10, | ||
441 | 0x10, | ||
442 | 0x10, | ||
443 | 0x10, | ||
444 | 0x10, | ||
445 | 0x10, | ||
446 | 0x10, | ||
447 | 0xd6, | ||
448 | 0x7c, | ||
449 | 0x38, | ||
450 | 0x10, | ||
451 | 0x00, | ||
452 | 0x00, | ||
453 | |||
454 | 0x00, | ||
455 | 0x00, | ||
456 | 0x00, | ||
457 | 0x00, | ||
458 | 0x00, | ||
459 | 0x08, | ||
460 | 0x0c, | ||
461 | 0x06, | ||
462 | 0xff, | ||
463 | 0x06, | ||
464 | 0x0c, | ||
465 | 0x08, | ||
466 | 0x00, | ||
467 | 0x00, | ||
468 | 0x00, | ||
469 | 0x00, | ||
470 | |||
471 | 0x00, | ||
472 | 0x00, | ||
473 | 0x00, | ||
474 | 0x00, | ||
475 | 0x00, | ||
476 | 0x10, | ||
477 | 0x30, | ||
478 | 0x60, | ||
479 | 0xff, | ||
480 | 0x60, | ||
481 | 0x30, | ||
482 | 0x10, | ||
483 | 0x00, | ||
484 | 0x00, | ||
485 | 0x00, | ||
486 | 0x00, | ||
487 | |||
488 | 0x22, | ||
489 | 0x44, | ||
490 | 0x88, | ||
491 | 0xcc, | ||
492 | 0xee, | ||
493 | 0x44, | ||
494 | 0x00, | ||
495 | 0x00, | ||
496 | 0x00, | ||
497 | 0x00, | ||
498 | 0x00, | ||
499 | 0x00, | ||
500 | 0x00, | ||
501 | 0x00, | ||
502 | 0x00, | ||
503 | 0x00, | ||
504 | |||
505 | 0x00, | ||
506 | 0x00, | ||
507 | 0x00, | ||
508 | 0x00, | ||
509 | 0x00, | ||
510 | 0x24, | ||
511 | 0x42, | ||
512 | 0xff, | ||
513 | 0x42, | ||
514 | 0x24, | ||
515 | 0x00, | ||
516 | 0x00, | ||
517 | 0x00, | ||
518 | 0x00, | ||
519 | 0x00, | ||
520 | 0x00, | ||
521 | |||
522 | 0x00, | ||
523 | 0x00, | ||
524 | 0x00, | ||
525 | 0x10, | ||
526 | 0x38, | ||
527 | 0x38, | ||
528 | 0x6c, | ||
529 | 0x6c, | ||
530 | 0xc6, | ||
531 | 0xfe, | ||
532 | 0x00, | ||
533 | 0x00, | ||
534 | 0x00, | ||
535 | 0x00, | ||
536 | 0x00, | ||
537 | 0x00, | ||
538 | |||
539 | 0x00, | ||
540 | 0x00, | ||
541 | 0x00, | ||
542 | 0xfe, | ||
543 | 0xc6, | ||
544 | 0x6c, | ||
545 | 0x6c, | ||
546 | 0x38, | ||
547 | 0x38, | ||
548 | 0x10, | ||
549 | 0x00, | ||
550 | 0x00, | ||
551 | 0x00, | ||
552 | 0x00, | ||
553 | 0x00, | ||
554 | 0x00, | ||
555 | |||
556 | 0x00, | ||
557 | 0x00, | ||
558 | 0x00, | ||
559 | 0x00, | ||
560 | 0x00, | ||
561 | 0x00, | ||
562 | 0x00, | ||
563 | 0x00, | ||
564 | 0x00, | ||
565 | 0x00, | ||
566 | 0x00, | ||
567 | 0x00, | ||
568 | 0x00, | ||
569 | 0x00, | ||
570 | 0x00, | ||
571 | 0x00, | ||
572 | |||
573 | 0x00, | ||
574 | 0x18, | ||
575 | 0x3c, | ||
576 | 0x3c, | ||
577 | 0x3c, | ||
578 | 0x3c, | ||
579 | 0x18, | ||
580 | 0x18, | ||
581 | 0x18, | ||
582 | 0x10, | ||
583 | 0x00, | ||
584 | 0x18, | ||
585 | 0x18, | ||
586 | 0x00, | ||
587 | 0x00, | ||
588 | 0x00, | ||
589 | |||
590 | 0x22, | ||
591 | 0x77, | ||
592 | 0x33, | ||
593 | 0x11, | ||
594 | 0x22, | ||
595 | 0x44, | ||
596 | 0x00, | ||
597 | 0x00, | ||
598 | 0x00, | ||
599 | 0x00, | ||
600 | 0x00, | ||
601 | 0x00, | ||
602 | 0x00, | ||
603 | 0x00, | ||
604 | 0x00, | ||
605 | 0x00, | ||
606 | |||
607 | 0x00, | ||
608 | 0x00, | ||
609 | 0x12, | ||
610 | 0x12, | ||
611 | 0x12, | ||
612 | 0x7f, | ||
613 | 0x24, | ||
614 | 0x24, | ||
615 | 0x24, | ||
616 | 0xfe, | ||
617 | 0x48, | ||
618 | 0x48, | ||
619 | 0x48, | ||
620 | 0x00, | ||
621 | 0x00, | ||
622 | 0x00, | ||
623 | |||
624 | 0x10, | ||
625 | 0x10, | ||
626 | 0x7c, | ||
627 | 0xd2, | ||
628 | 0xd0, | ||
629 | 0xd0, | ||
630 | 0xd0, | ||
631 | 0x7c, | ||
632 | 0x16, | ||
633 | 0x16, | ||
634 | 0x16, | ||
635 | 0x96, | ||
636 | 0x7c, | ||
637 | 0x10, | ||
638 | 0x10, | ||
639 | 0x00, | ||
640 | |||
641 | 0x00, | ||
642 | 0x42, | ||
643 | 0xbe, | ||
644 | 0x44, | ||
645 | 0x0c, | ||
646 | 0x08, | ||
647 | 0x18, | ||
648 | 0x10, | ||
649 | 0x30, | ||
650 | 0x20, | ||
651 | 0x64, | ||
652 | 0x4a, | ||
653 | 0xc4, | ||
654 | 0x00, | ||
655 | 0x00, | ||
656 | 0x00, | ||
657 | |||
658 | 0x00, | ||
659 | 0x38, | ||
660 | 0x6c, | ||
661 | 0x6c, | ||
662 | 0x6c, | ||
663 | 0x38, | ||
664 | 0x37, | ||
665 | 0x72, | ||
666 | 0xdc, | ||
667 | 0xcc, | ||
668 | 0xcc, | ||
669 | 0xcc, | ||
670 | 0x77, | ||
671 | 0x00, | ||
672 | 0x00, | ||
673 | 0x00, | ||
674 | |||
675 | 0x10, | ||
676 | 0x38, | ||
677 | 0x18, | ||
678 | 0x08, | ||
679 | 0x10, | ||
680 | 0x20, | ||
681 | 0x00, | ||
682 | 0x00, | ||
683 | 0x00, | ||
684 | 0x00, | ||
685 | 0x00, | ||
686 | 0x00, | ||
687 | 0x00, | ||
688 | 0x00, | ||
689 | 0x00, | ||
690 | 0x00, | ||
691 | |||
692 | 0x00, | ||
693 | 0x04, | ||
694 | 0x08, | ||
695 | 0x10, | ||
696 | 0x10, | ||
697 | 0x30, | ||
698 | 0x30, | ||
699 | 0x30, | ||
700 | 0x30, | ||
701 | 0x30, | ||
702 | 0x10, | ||
703 | 0x10, | ||
704 | 0x08, | ||
705 | 0x04, | ||
706 | 0x00, | ||
707 | 0x00, | ||
708 | |||
709 | 0x00, | ||
710 | 0x20, | ||
711 | 0x10, | ||
712 | 0x08, | ||
713 | 0x08, | ||
714 | 0x0c, | ||
715 | 0x0c, | ||
716 | 0x0c, | ||
717 | 0x0c, | ||
718 | 0x0c, | ||
719 | 0x08, | ||
720 | 0x08, | ||
721 | 0x10, | ||
722 | 0x20, | ||
723 | 0x00, | ||
724 | 0x00, | ||
725 | |||
726 | 0x00, | ||
727 | 0x00, | ||
728 | 0x00, | ||
729 | 0x00, | ||
730 | 0x44, | ||
731 | 0x28, | ||
732 | 0x38, | ||
733 | 0xfe, | ||
734 | 0x38, | ||
735 | 0x28, | ||
736 | 0x44, | ||
737 | 0x00, | ||
738 | 0x00, | ||
739 | 0x00, | ||
740 | 0x00, | ||
741 | 0x00, | ||
742 | |||
743 | 0x00, | ||
744 | 0x00, | ||
745 | 0x00, | ||
746 | 0x00, | ||
747 | 0x00, | ||
748 | 0x18, | ||
749 | 0x18, | ||
750 | 0x7e, | ||
751 | 0x18, | ||
752 | 0x18, | ||
753 | 0x00, | ||
754 | 0x00, | ||
755 | 0x00, | ||
756 | 0x00, | ||
757 | 0x00, | ||
758 | 0x00, | ||
759 | |||
760 | 0x00, | ||
761 | 0x00, | ||
762 | 0x00, | ||
763 | 0x00, | ||
764 | 0x00, | ||
765 | 0x00, | ||
766 | 0x00, | ||
767 | 0x00, | ||
768 | 0x00, | ||
769 | 0x00, | ||
770 | 0x10, | ||
771 | 0x38, | ||
772 | 0x18, | ||
773 | 0x08, | ||
774 | 0x10, | ||
775 | 0x20, | ||
776 | |||
777 | 0x00, | ||
778 | 0x00, | ||
779 | 0x00, | ||
780 | 0x00, | ||
781 | 0x00, | ||
782 | 0x00, | ||
783 | 0x00, | ||
784 | 0x7e, | ||
785 | 0x00, | ||
786 | 0x00, | ||
787 | 0x00, | ||
788 | 0x00, | ||
789 | 0x00, | ||
790 | 0x00, | ||
791 | 0x00, | ||
792 | 0x00, | ||
793 | |||
794 | 0x00, | ||
795 | 0x00, | ||
796 | 0x00, | ||
797 | 0x00, | ||
798 | 0x00, | ||
799 | 0x00, | ||
800 | 0x00, | ||
801 | 0x00, | ||
802 | 0x00, | ||
803 | 0x00, | ||
804 | 0x10, | ||
805 | 0x38, | ||
806 | 0x10, | ||
807 | 0x00, | ||
808 | 0x00, | ||
809 | 0x00, | ||
810 | |||
811 | 0x00, | ||
812 | 0x06, | ||
813 | 0x06, | ||
814 | 0x0c, | ||
815 | 0x0c, | ||
816 | 0x18, | ||
817 | 0x18, | ||
818 | 0x30, | ||
819 | 0x30, | ||
820 | 0x60, | ||
821 | 0x60, | ||
822 | 0xc0, | ||
823 | 0xc0, | ||
824 | 0x00, | ||
825 | 0x00, | ||
826 | 0x00, | ||
827 | |||
828 | 0x00, | ||
829 | 0x00, | ||
830 | 0x00, | ||
831 | 0x00, | ||
832 | 0x3c, | ||
833 | 0x46, | ||
834 | 0xc6, | ||
835 | 0xc6, | ||
836 | 0xc6, | ||
837 | 0xc6, | ||
838 | 0xc6, | ||
839 | 0xc4, | ||
840 | 0x78, | ||
841 | 0x00, | ||
842 | 0x00, | ||
843 | 0x00, | ||
844 | |||
845 | 0x00, | ||
846 | 0x00, | ||
847 | 0x00, | ||
848 | 0x00, | ||
849 | 0x08, | ||
850 | 0x18, | ||
851 | 0x78, | ||
852 | 0x18, | ||
853 | 0x18, | ||
854 | 0x18, | ||
855 | 0x18, | ||
856 | 0x18, | ||
857 | 0x7e, | ||
858 | 0x00, | ||
859 | 0x00, | ||
860 | 0x00, | ||
861 | |||
862 | 0x00, | ||
863 | 0x00, | ||
864 | 0x00, | ||
865 | 0x00, | ||
866 | 0x7c, | ||
867 | 0x86, | ||
868 | 0x06, | ||
869 | 0x0c, | ||
870 | 0x18, | ||
871 | 0x20, | ||
872 | 0x40, | ||
873 | 0xc1, | ||
874 | 0xfe, | ||
875 | 0x00, | ||
876 | 0x00, | ||
877 | 0x00, | ||
878 | |||
879 | 0x00, | ||
880 | 0x00, | ||
881 | 0x00, | ||
882 | 0x00, | ||
883 | 0x3c, | ||
884 | 0x46, | ||
885 | 0x04, | ||
886 | 0x08, | ||
887 | 0x1c, | ||
888 | 0x06, | ||
889 | 0x06, | ||
890 | 0x06, | ||
891 | 0x06, | ||
892 | 0x0c, | ||
893 | 0x70, | ||
894 | 0x00, | ||
895 | |||
896 | 0x00, | ||
897 | 0x00, | ||
898 | 0x00, | ||
899 | 0x00, | ||
900 | 0x04, | ||
901 | 0x08, | ||
902 | 0x10, | ||
903 | 0x2c, | ||
904 | 0x4c, | ||
905 | 0x8c, | ||
906 | 0x8c, | ||
907 | 0xfe, | ||
908 | 0x0c, | ||
909 | 0x0c, | ||
910 | 0x0c, | ||
911 | 0x00, | ||
912 | |||
913 | 0x00, | ||
914 | 0x00, | ||
915 | 0x00, | ||
916 | 0x02, | ||
917 | 0x3c, | ||
918 | 0x20, | ||
919 | 0x20, | ||
920 | 0x70, | ||
921 | 0x0c, | ||
922 | 0x06, | ||
923 | 0x06, | ||
924 | 0x06, | ||
925 | 0x06, | ||
926 | 0x0c, | ||
927 | 0x70, | ||
928 | 0x00, | ||
929 | |||
930 | 0x00, | ||
931 | 0x00, | ||
932 | 0x18, | ||
933 | 0x20, | ||
934 | 0x40, | ||
935 | 0xc0, | ||
936 | 0xdc, | ||
937 | 0xc6, | ||
938 | 0xc6, | ||
939 | 0xc6, | ||
940 | 0xc6, | ||
941 | 0x44, | ||
942 | 0x38, | ||
943 | 0x00, | ||
944 | 0x00, | ||
945 | 0x00, | ||
946 | |||
947 | 0x00, | ||
948 | 0x00, | ||
949 | 0x00, | ||
950 | 0x40, | ||
951 | 0x7e, | ||
952 | 0x82, | ||
953 | 0x06, | ||
954 | 0x04, | ||
955 | 0x0c, | ||
956 | 0x18, | ||
957 | 0x18, | ||
958 | 0x30, | ||
959 | 0x30, | ||
960 | 0x30, | ||
961 | 0x30, | ||
962 | 0x00, | ||
963 | |||
964 | 0x00, | ||
965 | 0x00, | ||
966 | 0x7c, | ||
967 | 0xc6, | ||
968 | 0xc6, | ||
969 | 0x64, | ||
970 | 0x38, | ||
971 | 0x4c, | ||
972 | 0xc6, | ||
973 | 0xc6, | ||
974 | 0xc6, | ||
975 | 0xc6, | ||
976 | 0x7c, | ||
977 | 0x00, | ||
978 | 0x00, | ||
979 | 0x00, | ||
980 | |||
981 | 0x00, | ||
982 | 0x00, | ||
983 | 0x00, | ||
984 | 0x00, | ||
985 | 0x38, | ||
986 | 0x44, | ||
987 | 0xc6, | ||
988 | 0xc6, | ||
989 | 0x76, | ||
990 | 0x06, | ||
991 | 0x06, | ||
992 | 0x06, | ||
993 | 0x04, | ||
994 | 0x08, | ||
995 | 0x30, | ||
996 | 0x00, | ||
997 | |||
998 | 0x00, | ||
999 | 0x00, | ||
1000 | 0x00, | ||
1001 | 0x00, | ||
1002 | 0x10, | ||
1003 | 0x38, | ||
1004 | 0x10, | ||
1005 | 0x00, | ||
1006 | 0x00, | ||
1007 | 0x00, | ||
1008 | 0x10, | ||
1009 | 0x38, | ||
1010 | 0x10, | ||
1011 | 0x00, | ||
1012 | 0x00, | ||
1013 | 0x00, | ||
1014 | |||
1015 | 0x00, | ||
1016 | 0x00, | ||
1017 | 0x00, | ||
1018 | 0x00, | ||
1019 | 0x10, | ||
1020 | 0x38, | ||
1021 | 0x10, | ||
1022 | 0x00, | ||
1023 | 0x00, | ||
1024 | 0x00, | ||
1025 | 0x10, | ||
1026 | 0x38, | ||
1027 | 0x18, | ||
1028 | 0x08, | ||
1029 | 0x10, | ||
1030 | 0x20, | ||
1031 | |||
1032 | 0x00, | ||
1033 | 0x06, | ||
1034 | 0x0c, | ||
1035 | 0x18, | ||
1036 | 0x30, | ||
1037 | 0x60, | ||
1038 | 0xa0, | ||
1039 | 0xa0, | ||
1040 | 0x60, | ||
1041 | 0x30, | ||
1042 | 0x18, | ||
1043 | 0x0c, | ||
1044 | 0x06, | ||
1045 | 0x00, | ||
1046 | 0x00, | ||
1047 | 0x00, | ||
1048 | |||
1049 | 0x00, | ||
1050 | 0x00, | ||
1051 | 0x00, | ||
1052 | 0x00, | ||
1053 | 0x00, | ||
1054 | 0x7e, | ||
1055 | 0x00, | ||
1056 | 0x00, | ||
1057 | 0x7e, | ||
1058 | 0x00, | ||
1059 | 0x00, | ||
1060 | 0x00, | ||
1061 | 0x00, | ||
1062 | 0x00, | ||
1063 | 0x00, | ||
1064 | 0x00, | ||
1065 | |||
1066 | 0x00, | ||
1067 | 0x60, | ||
1068 | 0x30, | ||
1069 | 0x18, | ||
1070 | 0x0c, | ||
1071 | 0x06, | ||
1072 | 0x05, | ||
1073 | 0x05, | ||
1074 | 0x06, | ||
1075 | 0x0c, | ||
1076 | 0x18, | ||
1077 | 0x30, | ||
1078 | 0x60, | ||
1079 | 0x00, | ||
1080 | 0x00, | ||
1081 | 0x00, | ||
1082 | |||
1083 | 0x00, | ||
1084 | 0x7c, | ||
1085 | 0x86, | ||
1086 | 0xc6, | ||
1087 | 0x06, | ||
1088 | 0x04, | ||
1089 | 0x08, | ||
1090 | 0x10, | ||
1091 | 0x10, | ||
1092 | 0x18, | ||
1093 | 0x00, | ||
1094 | 0x18, | ||
1095 | 0x18, | ||
1096 | 0x00, | ||
1097 | 0x00, | ||
1098 | 0x00, | ||
1099 | |||
1100 | 0x00, | ||
1101 | 0x00, | ||
1102 | 0x3c, | ||
1103 | 0x46, | ||
1104 | 0xc6, | ||
1105 | 0xce, | ||
1106 | 0xd6, | ||
1107 | 0xd6, | ||
1108 | 0xd6, | ||
1109 | 0xdc, | ||
1110 | 0xc0, | ||
1111 | 0xc4, | ||
1112 | 0x78, | ||
1113 | 0x00, | ||
1114 | 0x00, | ||
1115 | 0x00, | ||
1116 | |||
1117 | 0x00, | ||
1118 | 0x18, | ||
1119 | 0x18, | ||
1120 | 0x18, | ||
1121 | 0x3c, | ||
1122 | 0x2c, | ||
1123 | 0x2c, | ||
1124 | 0x2c, | ||
1125 | 0x7e, | ||
1126 | 0x46, | ||
1127 | 0x46, | ||
1128 | 0x46, | ||
1129 | 0xef, | ||
1130 | 0x00, | ||
1131 | 0x00, | ||
1132 | 0x00, | ||
1133 | |||
1134 | 0x00, | ||
1135 | 0xfc, | ||
1136 | 0x66, | ||
1137 | 0x66, | ||
1138 | 0x66, | ||
1139 | 0x66, | ||
1140 | 0x7c, | ||
1141 | 0x66, | ||
1142 | 0x66, | ||
1143 | 0x66, | ||
1144 | 0x66, | ||
1145 | 0x66, | ||
1146 | 0xfc, | ||
1147 | 0x00, | ||
1148 | 0x00, | ||
1149 | 0x00, | ||
1150 | |||
1151 | 0x00, | ||
1152 | 0x3a, | ||
1153 | 0x66, | ||
1154 | 0xc2, | ||
1155 | 0xc0, | ||
1156 | 0xc0, | ||
1157 | 0xc0, | ||
1158 | 0xc0, | ||
1159 | 0xc0, | ||
1160 | 0xc0, | ||
1161 | 0xc0, | ||
1162 | 0x62, | ||
1163 | 0x3c, | ||
1164 | 0x00, | ||
1165 | 0x00, | ||
1166 | 0x00, | ||
1167 | |||
1168 | 0x00, | ||
1169 | 0xfc, | ||
1170 | 0x66, | ||
1171 | 0x63, | ||
1172 | 0x63, | ||
1173 | 0x63, | ||
1174 | 0x63, | ||
1175 | 0x63, | ||
1176 | 0x63, | ||
1177 | 0x63, | ||
1178 | 0x63, | ||
1179 | 0x66, | ||
1180 | 0xfc, | ||
1181 | 0x00, | ||
1182 | 0x00, | ||
1183 | 0x00, | ||
1184 | |||
1185 | 0x00, | ||
1186 | 0xff, | ||
1187 | 0x61, | ||
1188 | 0x60, | ||
1189 | 0x60, | ||
1190 | 0x64, | ||
1191 | 0x7c, | ||
1192 | 0x64, | ||
1193 | 0x60, | ||
1194 | 0x60, | ||
1195 | 0x60, | ||
1196 | 0x61, | ||
1197 | 0xfe, | ||
1198 | 0x00, | ||
1199 | 0x00, | ||
1200 | 0x00, | ||
1201 | |||
1202 | 0x00, | ||
1203 | 0xff, | ||
1204 | 0x61, | ||
1205 | 0x61, | ||
1206 | 0x60, | ||
1207 | 0x64, | ||
1208 | 0x7c, | ||
1209 | 0x64, | ||
1210 | 0x60, | ||
1211 | 0x60, | ||
1212 | 0x60, | ||
1213 | 0x60, | ||
1214 | 0xf0, | ||
1215 | 0x00, | ||
1216 | 0x00, | ||
1217 | 0x00, | ||
1218 | |||
1219 | 0x00, | ||
1220 | 0x3a, | ||
1221 | 0x66, | ||
1222 | 0xc2, | ||
1223 | 0xc0, | ||
1224 | 0xc0, | ||
1225 | 0xc0, | ||
1226 | 0xcf, | ||
1227 | 0xc6, | ||
1228 | 0xc6, | ||
1229 | 0xc6, | ||
1230 | 0x66, | ||
1231 | 0x38, | ||
1232 | 0x00, | ||
1233 | 0x00, | ||
1234 | 0x00, | ||
1235 | |||
1236 | 0x00, | ||
1237 | 0xf7, | ||
1238 | 0x62, | ||
1239 | 0x62, | ||
1240 | 0x62, | ||
1241 | 0x62, | ||
1242 | 0x7e, | ||
1243 | 0x62, | ||
1244 | 0x62, | ||
1245 | 0x62, | ||
1246 | 0x62, | ||
1247 | 0x62, | ||
1248 | 0xf7, | ||
1249 | 0x00, | ||
1250 | 0x00, | ||
1251 | 0x00, | ||
1252 | |||
1253 | 0x00, | ||
1254 | 0x3c, | ||
1255 | 0x18, | ||
1256 | 0x18, | ||
1257 | 0x18, | ||
1258 | 0x18, | ||
1259 | 0x18, | ||
1260 | 0x18, | ||
1261 | 0x18, | ||
1262 | 0x18, | ||
1263 | 0x18, | ||
1264 | 0x18, | ||
1265 | 0x3c, | ||
1266 | 0x00, | ||
1267 | 0x00, | ||
1268 | 0x00, | ||
1269 | |||
1270 | 0x00, | ||
1271 | 0x1e, | ||
1272 | 0x0c, | ||
1273 | 0x0c, | ||
1274 | 0x0c, | ||
1275 | 0x0c, | ||
1276 | 0x0c, | ||
1277 | 0x0c, | ||
1278 | 0x0c, | ||
1279 | 0x0c, | ||
1280 | 0x0c, | ||
1281 | 0x0c, | ||
1282 | 0x0c, | ||
1283 | 0x0c, | ||
1284 | 0x08, | ||
1285 | 0xf0, | ||
1286 | |||
1287 | 0x00, | ||
1288 | 0xf7, | ||
1289 | 0x64, | ||
1290 | 0x6c, | ||
1291 | 0x68, | ||
1292 | 0x68, | ||
1293 | 0x78, | ||
1294 | 0x6c, | ||
1295 | 0x6c, | ||
1296 | 0x6c, | ||
1297 | 0x66, | ||
1298 | 0x66, | ||
1299 | 0xf7, | ||
1300 | 0x00, | ||
1301 | 0x00, | ||
1302 | 0x00, | ||
1303 | |||
1304 | 0x00, | ||
1305 | 0xf8, | ||
1306 | 0x60, | ||
1307 | 0x60, | ||
1308 | 0x60, | ||
1309 | 0x60, | ||
1310 | 0x60, | ||
1311 | 0x60, | ||
1312 | 0x60, | ||
1313 | 0x60, | ||
1314 | 0x60, | ||
1315 | 0x61, | ||
1316 | 0xfe, | ||
1317 | 0x00, | ||
1318 | 0x00, | ||
1319 | 0x00, | ||
1320 | |||
1321 | 0x00, | ||
1322 | 0xc3, | ||
1323 | 0x66, | ||
1324 | 0x76, | ||
1325 | 0x7e, | ||
1326 | 0x56, | ||
1327 | 0x56, | ||
1328 | 0x46, | ||
1329 | 0x46, | ||
1330 | 0x46, | ||
1331 | 0x46, | ||
1332 | 0x46, | ||
1333 | 0xef, | ||
1334 | 0x00, | ||
1335 | 0x00, | ||
1336 | 0x00, | ||
1337 | |||
1338 | 0x00, | ||
1339 | 0xe7, | ||
1340 | 0x62, | ||
1341 | 0x62, | ||
1342 | 0x72, | ||
1343 | 0x52, | ||
1344 | 0x5a, | ||
1345 | 0x4a, | ||
1346 | 0x4e, | ||
1347 | 0x46, | ||
1348 | 0x46, | ||
1349 | 0x42, | ||
1350 | 0xe2, | ||
1351 | 0x00, | ||
1352 | 0x00, | ||
1353 | 0x00, | ||
1354 | |||
1355 | 0x00, | ||
1356 | 0x3c, | ||
1357 | 0x66, | ||
1358 | 0xc3, | ||
1359 | 0xc3, | ||
1360 | 0xc3, | ||
1361 | 0xc3, | ||
1362 | 0xc3, | ||
1363 | 0xc3, | ||
1364 | 0xc3, | ||
1365 | 0xc3, | ||
1366 | 0x66, | ||
1367 | 0x3c, | ||
1368 | 0x00, | ||
1369 | 0x00, | ||
1370 | 0x00, | ||
1371 | |||
1372 | 0x00, | ||
1373 | 0xfc, | ||
1374 | 0x66, | ||
1375 | 0x66, | ||
1376 | 0x66, | ||
1377 | 0x66, | ||
1378 | 0x6c, | ||
1379 | 0x60, | ||
1380 | 0x60, | ||
1381 | 0x60, | ||
1382 | 0x60, | ||
1383 | 0x60, | ||
1384 | 0xf0, | ||
1385 | 0x00, | ||
1386 | 0x00, | ||
1387 | 0x00, | ||
1388 | |||
1389 | 0x00, | ||
1390 | 0x3c, | ||
1391 | 0x66, | ||
1392 | 0xc3, | ||
1393 | 0xc3, | ||
1394 | 0xc3, | ||
1395 | 0xc3, | ||
1396 | 0xc3, | ||
1397 | 0xc3, | ||
1398 | 0xc3, | ||
1399 | 0xc3, | ||
1400 | 0x66, | ||
1401 | 0x3c, | ||
1402 | 0x10, | ||
1403 | 0x39, | ||
1404 | 0x0e, | ||
1405 | |||
1406 | 0x00, | ||
1407 | 0xfc, | ||
1408 | 0x66, | ||
1409 | 0x66, | ||
1410 | 0x66, | ||
1411 | 0x66, | ||
1412 | 0x7c, | ||
1413 | 0x6c, | ||
1414 | 0x66, | ||
1415 | 0x66, | ||
1416 | 0x66, | ||
1417 | 0x66, | ||
1418 | 0xf3, | ||
1419 | 0x00, | ||
1420 | 0x00, | ||
1421 | 0x00, | ||
1422 | |||
1423 | 0x00, | ||
1424 | 0x7a, | ||
1425 | 0xc6, | ||
1426 | 0xc2, | ||
1427 | 0xc0, | ||
1428 | 0x70, | ||
1429 | 0x3c, | ||
1430 | 0x0e, | ||
1431 | 0x06, | ||
1432 | 0x06, | ||
1433 | 0x86, | ||
1434 | 0xc6, | ||
1435 | 0xbc, | ||
1436 | 0x00, | ||
1437 | 0x00, | ||
1438 | 0x00, | ||
1439 | |||
1440 | 0x00, | ||
1441 | 0xff, | ||
1442 | 0x99, | ||
1443 | 0x18, | ||
1444 | 0x18, | ||
1445 | 0x18, | ||
1446 | 0x18, | ||
1447 | 0x18, | ||
1448 | 0x18, | ||
1449 | 0x18, | ||
1450 | 0x18, | ||
1451 | 0x18, | ||
1452 | 0x3c, | ||
1453 | 0x00, | ||
1454 | 0x00, | ||
1455 | 0x00, | ||
1456 | |||
1457 | 0x00, | ||
1458 | 0xf7, | ||
1459 | 0x62, | ||
1460 | 0x62, | ||
1461 | 0x62, | ||
1462 | 0x62, | ||
1463 | 0x62, | ||
1464 | 0x62, | ||
1465 | 0x62, | ||
1466 | 0x62, | ||
1467 | 0x62, | ||
1468 | 0x62, | ||
1469 | 0x3c, | ||
1470 | 0x00, | ||
1471 | 0x00, | ||
1472 | 0x00, | ||
1473 | |||
1474 | 0x00, | ||
1475 | 0xf7, | ||
1476 | 0x62, | ||
1477 | 0x62, | ||
1478 | 0x62, | ||
1479 | 0x76, | ||
1480 | 0x34, | ||
1481 | 0x34, | ||
1482 | 0x34, | ||
1483 | 0x3c, | ||
1484 | 0x18, | ||
1485 | 0x18, | ||
1486 | 0x18, | ||
1487 | 0x00, | ||
1488 | 0x00, | ||
1489 | 0x00, | ||
1490 | |||
1491 | 0x00, | ||
1492 | 0xf7, | ||
1493 | 0x62, | ||
1494 | 0x62, | ||
1495 | 0x62, | ||
1496 | 0x62, | ||
1497 | 0x6a, | ||
1498 | 0x6a, | ||
1499 | 0x6a, | ||
1500 | 0x6a, | ||
1501 | 0x7e, | ||
1502 | 0x7e, | ||
1503 | 0x34, | ||
1504 | 0x00, | ||
1505 | 0x00, | ||
1506 | 0x00, | ||
1507 | |||
1508 | 0x00, | ||
1509 | 0xf7, | ||
1510 | 0x62, | ||
1511 | 0x62, | ||
1512 | 0x34, | ||
1513 | 0x34, | ||
1514 | 0x18, | ||
1515 | 0x18, | ||
1516 | 0x2c, | ||
1517 | 0x2c, | ||
1518 | 0x46, | ||
1519 | 0x46, | ||
1520 | 0xef, | ||
1521 | 0x00, | ||
1522 | 0x00, | ||
1523 | 0x00, | ||
1524 | |||
1525 | 0x00, | ||
1526 | 0xf7, | ||
1527 | 0x62, | ||
1528 | 0x62, | ||
1529 | 0x62, | ||
1530 | 0x34, | ||
1531 | 0x34, | ||
1532 | 0x18, | ||
1533 | 0x18, | ||
1534 | 0x18, | ||
1535 | 0x18, | ||
1536 | 0x18, | ||
1537 | 0x3c, | ||
1538 | 0x00, | ||
1539 | 0x00, | ||
1540 | 0x00, | ||
1541 | |||
1542 | 0x00, | ||
1543 | 0x7f, | ||
1544 | 0x46, | ||
1545 | 0x86, | ||
1546 | 0x0c, | ||
1547 | 0x0c, | ||
1548 | 0x18, | ||
1549 | 0x18, | ||
1550 | 0x30, | ||
1551 | 0x30, | ||
1552 | 0x61, | ||
1553 | 0x62, | ||
1554 | 0xfe, | ||
1555 | 0x00, | ||
1556 | 0x00, | ||
1557 | 0x00, | ||
1558 | |||
1559 | 0x00, | ||
1560 | 0x3c, | ||
1561 | 0x30, | ||
1562 | 0x30, | ||
1563 | 0x30, | ||
1564 | 0x30, | ||
1565 | 0x30, | ||
1566 | 0x30, | ||
1567 | 0x30, | ||
1568 | 0x30, | ||
1569 | 0x30, | ||
1570 | 0x30, | ||
1571 | 0x3c, | ||
1572 | 0x00, | ||
1573 | 0x00, | ||
1574 | 0x00, | ||
1575 | |||
1576 | 0x00, | ||
1577 | 0xc0, | ||
1578 | 0xc0, | ||
1579 | 0x60, | ||
1580 | 0x60, | ||
1581 | 0x30, | ||
1582 | 0x30, | ||
1583 | 0x18, | ||
1584 | 0x18, | ||
1585 | 0x0c, | ||
1586 | 0x0c, | ||
1587 | 0x06, | ||
1588 | 0x06, | ||
1589 | 0x00, | ||
1590 | 0x00, | ||
1591 | 0x00, | ||
1592 | |||
1593 | 0x00, | ||
1594 | 0x3c, | ||
1595 | 0x0c, | ||
1596 | 0x0c, | ||
1597 | 0x0c, | ||
1598 | 0x0c, | ||
1599 | 0x0c, | ||
1600 | 0x0c, | ||
1601 | 0x0c, | ||
1602 | 0x0c, | ||
1603 | 0x0c, | ||
1604 | 0x0c, | ||
1605 | 0x3c, | ||
1606 | 0x00, | ||
1607 | 0x00, | ||
1608 | 0x00, | ||
1609 | |||
1610 | 0x00, | ||
1611 | 0x10, | ||
1612 | 0x38, | ||
1613 | 0x4c, | ||
1614 | 0x86, | ||
1615 | 0x00, | ||
1616 | 0x00, | ||
1617 | 0x00, | ||
1618 | 0x00, | ||
1619 | 0x00, | ||
1620 | 0x00, | ||
1621 | 0x00, | ||
1622 | 0x00, | ||
1623 | 0x00, | ||
1624 | 0x00, | ||
1625 | 0x00, | ||
1626 | |||
1627 | 0x00, | ||
1628 | 0x00, | ||
1629 | 0x00, | ||
1630 | 0x00, | ||
1631 | 0x00, | ||
1632 | 0x00, | ||
1633 | 0x00, | ||
1634 | 0x00, | ||
1635 | 0x00, | ||
1636 | 0x00, | ||
1637 | 0x00, | ||
1638 | 0x00, | ||
1639 | 0x00, | ||
1640 | 0xff, | ||
1641 | 0x00, | ||
1642 | 0x00, | ||
1643 | |||
1644 | 0x00, | ||
1645 | 0x18, | ||
1646 | 0x20, | ||
1647 | 0x30, | ||
1648 | 0x38, | ||
1649 | 0x10, | ||
1650 | 0x00, | ||
1651 | 0x00, | ||
1652 | 0x00, | ||
1653 | 0x00, | ||
1654 | 0x00, | ||
1655 | 0x00, | ||
1656 | 0x00, | ||
1657 | 0x00, | ||
1658 | 0x00, | ||
1659 | 0x00, | ||
1660 | |||
1661 | 0x00, | ||
1662 | 0x00, | ||
1663 | 0x00, | ||
1664 | 0x00, | ||
1665 | 0x00, | ||
1666 | 0x78, | ||
1667 | 0x8c, | ||
1668 | 0x0c, | ||
1669 | 0x3c, | ||
1670 | 0xcc, | ||
1671 | 0xcc, | ||
1672 | 0xcd, | ||
1673 | 0x76, | ||
1674 | 0x00, | ||
1675 | 0x00, | ||
1676 | 0x00, | ||
1677 | |||
1678 | 0x00, | ||
1679 | 0x20, | ||
1680 | 0xe0, | ||
1681 | 0x60, | ||
1682 | 0x60, | ||
1683 | 0x6c, | ||
1684 | 0x76, | ||
1685 | 0x66, | ||
1686 | 0x66, | ||
1687 | 0x66, | ||
1688 | 0x66, | ||
1689 | 0x76, | ||
1690 | 0x6c, | ||
1691 | 0x00, | ||
1692 | 0x00, | ||
1693 | 0x00, | ||
1694 | |||
1695 | 0x00, | ||
1696 | 0x00, | ||
1697 | 0x00, | ||
1698 | 0x00, | ||
1699 | 0x00, | ||
1700 | 0x3c, | ||
1701 | 0x66, | ||
1702 | 0x60, | ||
1703 | 0x60, | ||
1704 | 0x60, | ||
1705 | 0x60, | ||
1706 | 0x62, | ||
1707 | 0x3c, | ||
1708 | 0x00, | ||
1709 | 0x00, | ||
1710 | 0x00, | ||
1711 | |||
1712 | 0x00, | ||
1713 | 0x04, | ||
1714 | 0x1c, | ||
1715 | 0x0c, | ||
1716 | 0x0c, | ||
1717 | 0x6c, | ||
1718 | 0xdc, | ||
1719 | 0xcc, | ||
1720 | 0xcc, | ||
1721 | 0xcc, | ||
1722 | 0xcc, | ||
1723 | 0xdc, | ||
1724 | 0x66, | ||
1725 | 0x00, | ||
1726 | 0x00, | ||
1727 | 0x00, | ||
1728 | |||
1729 | 0x00, | ||
1730 | 0x00, | ||
1731 | 0x00, | ||
1732 | 0x00, | ||
1733 | 0x00, | ||
1734 | 0x3c, | ||
1735 | 0x66, | ||
1736 | 0x7e, | ||
1737 | 0x60, | ||
1738 | 0x60, | ||
1739 | 0x60, | ||
1740 | 0x62, | ||
1741 | 0x3c, | ||
1742 | 0x00, | ||
1743 | 0x00, | ||
1744 | 0x00, | ||
1745 | |||
1746 | 0x00, | ||
1747 | 0x1e, | ||
1748 | 0x31, | ||
1749 | 0x33, | ||
1750 | 0x30, | ||
1751 | 0x30, | ||
1752 | 0x78, | ||
1753 | 0x30, | ||
1754 | 0x30, | ||
1755 | 0x30, | ||
1756 | 0x30, | ||
1757 | 0x30, | ||
1758 | 0x78, | ||
1759 | 0x00, | ||
1760 | 0x00, | ||
1761 | 0x00, | ||
1762 | |||
1763 | 0x00, | ||
1764 | 0x00, | ||
1765 | 0x00, | ||
1766 | 0x00, | ||
1767 | 0x00, | ||
1768 | 0x7b, | ||
1769 | 0xce, | ||
1770 | 0xcc, | ||
1771 | 0xcc, | ||
1772 | 0xcc, | ||
1773 | 0x78, | ||
1774 | 0x60, | ||
1775 | 0x7c, | ||
1776 | 0x86, | ||
1777 | 0xc6, | ||
1778 | 0x7c, | ||
1779 | |||
1780 | 0x00, | ||
1781 | 0x20, | ||
1782 | 0xe0, | ||
1783 | 0x60, | ||
1784 | 0x60, | ||
1785 | 0x6c, | ||
1786 | 0x76, | ||
1787 | 0x66, | ||
1788 | 0x66, | ||
1789 | 0x66, | ||
1790 | 0x66, | ||
1791 | 0x66, | ||
1792 | 0xf7, | ||
1793 | 0x00, | ||
1794 | 0x00, | ||
1795 | 0x00, | ||
1796 | |||
1797 | 0x00, | ||
1798 | 0x10, | ||
1799 | 0x38, | ||
1800 | 0x10, | ||
1801 | 0x00, | ||
1802 | 0x18, | ||
1803 | 0x38, | ||
1804 | 0x18, | ||
1805 | 0x18, | ||
1806 | 0x18, | ||
1807 | 0x18, | ||
1808 | 0x18, | ||
1809 | 0x3c, | ||
1810 | 0x00, | ||
1811 | 0x00, | ||
1812 | 0x00, | ||
1813 | |||
1814 | 0x00, | ||
1815 | 0x08, | ||
1816 | 0x1c, | ||
1817 | 0x08, | ||
1818 | 0x00, | ||
1819 | 0x0c, | ||
1820 | 0x1c, | ||
1821 | 0x0c, | ||
1822 | 0x0c, | ||
1823 | 0x0c, | ||
1824 | 0x0c, | ||
1825 | 0x0c, | ||
1826 | 0x6c, | ||
1827 | 0x4c, | ||
1828 | 0x38, | ||
1829 | 0x00, | ||
1830 | |||
1831 | 0x00, | ||
1832 | 0x20, | ||
1833 | 0xe0, | ||
1834 | 0x60, | ||
1835 | 0x60, | ||
1836 | 0x67, | ||
1837 | 0x66, | ||
1838 | 0x6c, | ||
1839 | 0x78, | ||
1840 | 0x6c, | ||
1841 | 0x6c, | ||
1842 | 0x66, | ||
1843 | 0xe7, | ||
1844 | 0x00, | ||
1845 | 0x00, | ||
1846 | 0x00, | ||
1847 | |||
1848 | 0x00, | ||
1849 | 0x08, | ||
1850 | 0x38, | ||
1851 | 0x18, | ||
1852 | 0x18, | ||
1853 | 0x18, | ||
1854 | 0x18, | ||
1855 | 0x18, | ||
1856 | 0x18, | ||
1857 | 0x18, | ||
1858 | 0x18, | ||
1859 | 0x18, | ||
1860 | 0x3c, | ||
1861 | 0x00, | ||
1862 | 0x00, | ||
1863 | 0x00, | ||
1864 | |||
1865 | 0x00, | ||
1866 | 0x00, | ||
1867 | 0x00, | ||
1868 | 0x00, | ||
1869 | 0x00, | ||
1870 | 0x6a, | ||
1871 | 0xfe, | ||
1872 | 0x6a, | ||
1873 | 0x6a, | ||
1874 | 0x6a, | ||
1875 | 0x62, | ||
1876 | 0x62, | ||
1877 | 0xf7, | ||
1878 | 0x00, | ||
1879 | 0x00, | ||
1880 | 0x00, | ||
1881 | |||
1882 | 0x00, | ||
1883 | 0x00, | ||
1884 | 0x00, | ||
1885 | 0x00, | ||
1886 | 0x00, | ||
1887 | 0x5c, | ||
1888 | 0xf6, | ||
1889 | 0x66, | ||
1890 | 0x66, | ||
1891 | 0x66, | ||
1892 | 0x66, | ||
1893 | 0x66, | ||
1894 | 0xf7, | ||
1895 | 0x00, | ||
1896 | 0x00, | ||
1897 | 0x00, | ||
1898 | |||
1899 | 0x00, | ||
1900 | 0x00, | ||
1901 | 0x00, | ||
1902 | 0x00, | ||
1903 | 0x00, | ||
1904 | 0x3c, | ||
1905 | 0x66, | ||
1906 | 0x66, | ||
1907 | 0x66, | ||
1908 | 0x66, | ||
1909 | 0x66, | ||
1910 | 0x66, | ||
1911 | 0x3c, | ||
1912 | 0x00, | ||
1913 | 0x00, | ||
1914 | 0x00, | ||
1915 | |||
1916 | 0x00, | ||
1917 | 0x00, | ||
1918 | 0x00, | ||
1919 | 0x00, | ||
1920 | 0x00, | ||
1921 | 0x5c, | ||
1922 | 0xe6, | ||
1923 | 0x66, | ||
1924 | 0x66, | ||
1925 | 0x66, | ||
1926 | 0x66, | ||
1927 | 0x66, | ||
1928 | 0x7c, | ||
1929 | 0x60, | ||
1930 | 0x60, | ||
1931 | 0xf0, | ||
1932 | |||
1933 | 0x00, | ||
1934 | 0x00, | ||
1935 | 0x00, | ||
1936 | 0x00, | ||
1937 | 0x00, | ||
1938 | 0x76, | ||
1939 | 0xcc, | ||
1940 | 0xcc, | ||
1941 | 0xcc, | ||
1942 | 0xcc, | ||
1943 | 0xcc, | ||
1944 | 0xcc, | ||
1945 | 0x7c, | ||
1946 | 0x0c, | ||
1947 | 0x0c, | ||
1948 | 0x1e, | ||
1949 | |||
1950 | 0x00, | ||
1951 | 0x00, | ||
1952 | 0x00, | ||
1953 | 0x00, | ||
1954 | 0x00, | ||
1955 | 0x5e, | ||
1956 | 0xf6, | ||
1957 | 0x60, | ||
1958 | 0x60, | ||
1959 | 0x60, | ||
1960 | 0x60, | ||
1961 | 0x60, | ||
1962 | 0xf0, | ||
1963 | 0x00, | ||
1964 | 0x00, | ||
1965 | 0x00, | ||
1966 | |||
1967 | 0x00, | ||
1968 | 0x00, | ||
1969 | 0x00, | ||
1970 | 0x00, | ||
1971 | 0x00, | ||
1972 | 0x7a, | ||
1973 | 0xc6, | ||
1974 | 0x72, | ||
1975 | 0x1c, | ||
1976 | 0x06, | ||
1977 | 0x86, | ||
1978 | 0xc6, | ||
1979 | 0xbc, | ||
1980 | 0x00, | ||
1981 | 0x00, | ||
1982 | 0x00, | ||
1983 | |||
1984 | 0x00, | ||
1985 | 0x00, | ||
1986 | 0x00, | ||
1987 | 0x10, | ||
1988 | 0x30, | ||
1989 | 0x7c, | ||
1990 | 0x30, | ||
1991 | 0x30, | ||
1992 | 0x30, | ||
1993 | 0x30, | ||
1994 | 0x30, | ||
1995 | 0x34, | ||
1996 | 0x18, | ||
1997 | 0x00, | ||
1998 | 0x00, | ||
1999 | 0x00, | ||
2000 | |||
2001 | 0x00, | ||
2002 | 0x00, | ||
2003 | 0x00, | ||
2004 | 0x00, | ||
2005 | 0x00, | ||
2006 | 0xee, | ||
2007 | 0x66, | ||
2008 | 0x66, | ||
2009 | 0x66, | ||
2010 | 0x66, | ||
2011 | 0x66, | ||
2012 | 0x67, | ||
2013 | 0x3a, | ||
2014 | 0x00, | ||
2015 | 0x00, | ||
2016 | 0x00, | ||
2017 | |||
2018 | 0x00, | ||
2019 | 0x00, | ||
2020 | 0x00, | ||
2021 | 0x00, | ||
2022 | 0x00, | ||
2023 | 0xf7, | ||
2024 | 0x62, | ||
2025 | 0x76, | ||
2026 | 0x34, | ||
2027 | 0x34, | ||
2028 | 0x3c, | ||
2029 | 0x18, | ||
2030 | 0x18, | ||
2031 | 0x00, | ||
2032 | 0x00, | ||
2033 | 0x00, | ||
2034 | |||
2035 | 0x00, | ||
2036 | 0x00, | ||
2037 | 0x00, | ||
2038 | 0x00, | ||
2039 | 0x00, | ||
2040 | 0xf7, | ||
2041 | 0x62, | ||
2042 | 0x6a, | ||
2043 | 0x6a, | ||
2044 | 0x6a, | ||
2045 | 0x6a, | ||
2046 | 0x7e, | ||
2047 | 0x24, | ||
2048 | 0x00, | ||
2049 | 0x00, | ||
2050 | 0x00, | ||
2051 | |||
2052 | 0x00, | ||
2053 | 0x00, | ||
2054 | 0x00, | ||
2055 | 0x00, | ||
2056 | 0x00, | ||
2057 | 0xf7, | ||
2058 | 0x62, | ||
2059 | 0x34, | ||
2060 | 0x18, | ||
2061 | 0x2c, | ||
2062 | 0x46, | ||
2063 | 0x46, | ||
2064 | 0xef, | ||
2065 | 0x00, | ||
2066 | 0x00, | ||
2067 | 0x00, | ||
2068 | |||
2069 | 0x00, | ||
2070 | 0x00, | ||
2071 | 0x00, | ||
2072 | 0x00, | ||
2073 | 0x00, | ||
2074 | 0xf7, | ||
2075 | 0x62, | ||
2076 | 0x62, | ||
2077 | 0x34, | ||
2078 | 0x34, | ||
2079 | 0x18, | ||
2080 | 0x18, | ||
2081 | 0x18, | ||
2082 | 0x10, | ||
2083 | 0xb0, | ||
2084 | 0xe0, | ||
2085 | |||
2086 | 0x00, | ||
2087 | 0x00, | ||
2088 | 0x00, | ||
2089 | 0x00, | ||
2090 | 0x00, | ||
2091 | 0xfe, | ||
2092 | 0x8c, | ||
2093 | 0x18, | ||
2094 | 0x30, | ||
2095 | 0x30, | ||
2096 | 0x60, | ||
2097 | 0xc2, | ||
2098 | 0xfe, | ||
2099 | 0x00, | ||
2100 | 0x00, | ||
2101 | 0x00, | ||
2102 | |||
2103 | 0x00, | ||
2104 | 0x0e, | ||
2105 | 0x18, | ||
2106 | 0x10, | ||
2107 | 0x10, | ||
2108 | 0x08, | ||
2109 | 0x70, | ||
2110 | 0x70, | ||
2111 | 0x08, | ||
2112 | 0x10, | ||
2113 | 0x10, | ||
2114 | 0x18, | ||
2115 | 0x0e, | ||
2116 | 0x00, | ||
2117 | 0x00, | ||
2118 | 0x00, | ||
2119 | |||
2120 | 0x18, | ||
2121 | 0x18, | ||
2122 | 0x18, | ||
2123 | 0x18, | ||
2124 | 0x18, | ||
2125 | 0x18, | ||
2126 | 0x18, | ||
2127 | 0x18, | ||
2128 | 0x18, | ||
2129 | 0x18, | ||
2130 | 0x18, | ||
2131 | 0x18, | ||
2132 | 0x18, | ||
2133 | 0x18, | ||
2134 | 0x00, | ||
2135 | 0x00, | ||
2136 | |||
2137 | 0x00, | ||
2138 | 0x70, | ||
2139 | 0x18, | ||
2140 | 0x08, | ||
2141 | 0x08, | ||
2142 | 0x10, | ||
2143 | 0x0e, | ||
2144 | 0x0e, | ||
2145 | 0x10, | ||
2146 | 0x08, | ||
2147 | 0x08, | ||
2148 | 0x18, | ||
2149 | 0x70, | ||
2150 | 0x00, | ||
2151 | 0x00, | ||
2152 | 0x00, | ||
2153 | |||
2154 | 0x00, | ||
2155 | 0x00, | ||
2156 | 0x00, | ||
2157 | 0x00, | ||
2158 | 0x00, | ||
2159 | 0x00, | ||
2160 | 0x76, | ||
2161 | 0xdc, | ||
2162 | 0x00, | ||
2163 | 0x00, | ||
2164 | 0x00, | ||
2165 | 0x00, | ||
2166 | 0x00, | ||
2167 | 0x00, | ||
2168 | 0x00, | ||
2169 | 0x00, | ||
2170 | |||
2171 | 0x00, | ||
2172 | 0x00, | ||
2173 | 0x00, | ||
2174 | 0x00, | ||
2175 | 0x10, | ||
2176 | 0x38, | ||
2177 | 0x6c, | ||
2178 | 0xc6, | ||
2179 | 0xc6, | ||
2180 | 0xc6, | ||
2181 | 0xfe, | ||
2182 | 0x00, | ||
2183 | 0x00, | ||
2184 | 0x00, | ||
2185 | 0x00, | ||
2186 | 0x00, | ||
2187 | |||
2188 | 0x00, | ||
2189 | 0x00, | ||
2190 | 0x3a, | ||
2191 | 0x66, | ||
2192 | 0xc2, | ||
2193 | 0xc0, | ||
2194 | 0xc0, | ||
2195 | 0xc0, | ||
2196 | 0xc0, | ||
2197 | 0xc0, | ||
2198 | 0x62, | ||
2199 | 0x3c, | ||
2200 | 0x18, | ||
2201 | 0x0c, | ||
2202 | 0x24, | ||
2203 | 0x18, | ||
2204 | |||
2205 | 0x00, | ||
2206 | 0x00, | ||
2207 | 0x66, | ||
2208 | 0x00, | ||
2209 | 0x00, | ||
2210 | 0xee, | ||
2211 | 0x66, | ||
2212 | 0x66, | ||
2213 | 0x66, | ||
2214 | 0x66, | ||
2215 | 0x66, | ||
2216 | 0x66, | ||
2217 | 0x3b, | ||
2218 | 0x00, | ||
2219 | 0x00, | ||
2220 | 0x00, | ||
2221 | |||
2222 | 0x00, | ||
2223 | 0x0c, | ||
2224 | 0x18, | ||
2225 | 0x20, | ||
2226 | 0x00, | ||
2227 | 0x3c, | ||
2228 | 0x66, | ||
2229 | 0x7e, | ||
2230 | 0x60, | ||
2231 | 0x60, | ||
2232 | 0x60, | ||
2233 | 0x62, | ||
2234 | 0x3c, | ||
2235 | 0x00, | ||
2236 | 0x00, | ||
2237 | 0x00, | ||
2238 | |||
2239 | 0x00, | ||
2240 | 0x30, | ||
2241 | 0x58, | ||
2242 | 0x8c, | ||
2243 | 0x00, | ||
2244 | 0x78, | ||
2245 | 0x8c, | ||
2246 | 0x0c, | ||
2247 | 0x3c, | ||
2248 | 0xcc, | ||
2249 | 0xcc, | ||
2250 | 0xcd, | ||
2251 | 0x76, | ||
2252 | 0x00, | ||
2253 | 0x00, | ||
2254 | 0x00, | ||
2255 | |||
2256 | 0x00, | ||
2257 | 0x00, | ||
2258 | 0x66, | ||
2259 | 0x00, | ||
2260 | 0x00, | ||
2261 | 0x78, | ||
2262 | 0x8c, | ||
2263 | 0x0c, | ||
2264 | 0x3c, | ||
2265 | 0xcc, | ||
2266 | 0xcc, | ||
2267 | 0xcd, | ||
2268 | 0x76, | ||
2269 | 0x00, | ||
2270 | 0x00, | ||
2271 | 0x00, | ||
2272 | |||
2273 | 0x00, | ||
2274 | 0x30, | ||
2275 | 0x18, | ||
2276 | 0x04, | ||
2277 | 0x00, | ||
2278 | 0x78, | ||
2279 | 0x8c, | ||
2280 | 0x0c, | ||
2281 | 0x3c, | ||
2282 | 0xcc, | ||
2283 | 0xcc, | ||
2284 | 0xcd, | ||
2285 | 0x76, | ||
2286 | 0x00, | ||
2287 | 0x00, | ||
2288 | 0x00, | ||
2289 | |||
2290 | 0x38, | ||
2291 | 0x44, | ||
2292 | 0x44, | ||
2293 | 0x38, | ||
2294 | 0x00, | ||
2295 | 0x78, | ||
2296 | 0x8c, | ||
2297 | 0x0c, | ||
2298 | 0x3c, | ||
2299 | 0xcc, | ||
2300 | 0xcc, | ||
2301 | 0xcd, | ||
2302 | 0x76, | ||
2303 | 0x00, | ||
2304 | 0x00, | ||
2305 | 0x00, | ||
2306 | |||
2307 | 0x00, | ||
2308 | 0x00, | ||
2309 | 0x00, | ||
2310 | 0x00, | ||
2311 | 0x00, | ||
2312 | 0x3c, | ||
2313 | 0x66, | ||
2314 | 0x60, | ||
2315 | 0x60, | ||
2316 | 0x60, | ||
2317 | 0x60, | ||
2318 | 0x62, | ||
2319 | 0x3c, | ||
2320 | 0x08, | ||
2321 | 0x24, | ||
2322 | 0x18, | ||
2323 | |||
2324 | 0x00, | ||
2325 | 0x18, | ||
2326 | 0x2c, | ||
2327 | 0x46, | ||
2328 | 0x00, | ||
2329 | 0x3c, | ||
2330 | 0x66, | ||
2331 | 0x7e, | ||
2332 | 0x60, | ||
2333 | 0x60, | ||
2334 | 0x60, | ||
2335 | 0x62, | ||
2336 | 0x3c, | ||
2337 | 0x00, | ||
2338 | 0x00, | ||
2339 | 0x00, | ||
2340 | |||
2341 | 0x00, | ||
2342 | 0x00, | ||
2343 | 0x66, | ||
2344 | 0x00, | ||
2345 | 0x00, | ||
2346 | 0x3c, | ||
2347 | 0x66, | ||
2348 | 0x7e, | ||
2349 | 0x60, | ||
2350 | 0x60, | ||
2351 | 0x60, | ||
2352 | 0x62, | ||
2353 | 0x3c, | ||
2354 | 0x00, | ||
2355 | 0x00, | ||
2356 | 0x00, | ||
2357 | |||
2358 | 0x00, | ||
2359 | 0x30, | ||
2360 | 0x18, | ||
2361 | 0x04, | ||
2362 | 0x00, | ||
2363 | 0x3c, | ||
2364 | 0x66, | ||
2365 | 0x7e, | ||
2366 | 0x60, | ||
2367 | 0x60, | ||
2368 | 0x60, | ||
2369 | 0x62, | ||
2370 | 0x3c, | ||
2371 | 0x00, | ||
2372 | 0x00, | ||
2373 | 0x00, | ||
2374 | |||
2375 | 0x00, | ||
2376 | 0x00, | ||
2377 | 0x66, | ||
2378 | 0x00, | ||
2379 | 0x00, | ||
2380 | 0x38, | ||
2381 | 0x18, | ||
2382 | 0x18, | ||
2383 | 0x18, | ||
2384 | 0x18, | ||
2385 | 0x18, | ||
2386 | 0x18, | ||
2387 | 0x3c, | ||
2388 | 0x00, | ||
2389 | 0x00, | ||
2390 | 0x00, | ||
2391 | |||
2392 | 0x00, | ||
2393 | 0x18, | ||
2394 | 0x2c, | ||
2395 | 0x46, | ||
2396 | 0x00, | ||
2397 | 0x38, | ||
2398 | 0x18, | ||
2399 | 0x18, | ||
2400 | 0x18, | ||
2401 | 0x18, | ||
2402 | 0x18, | ||
2403 | 0x18, | ||
2404 | 0x3c, | ||
2405 | 0x00, | ||
2406 | 0x00, | ||
2407 | 0x00, | ||
2408 | |||
2409 | 0x00, | ||
2410 | 0x60, | ||
2411 | 0x30, | ||
2412 | 0x08, | ||
2413 | 0x00, | ||
2414 | 0x38, | ||
2415 | 0x18, | ||
2416 | 0x18, | ||
2417 | 0x18, | ||
2418 | 0x18, | ||
2419 | 0x18, | ||
2420 | 0x18, | ||
2421 | 0x3c, | ||
2422 | 0x00, | ||
2423 | 0x00, | ||
2424 | 0x00, | ||
2425 | |||
2426 | 0x66, | ||
2427 | 0x18, | ||
2428 | 0x18, | ||
2429 | 0x18, | ||
2430 | 0x3c, | ||
2431 | 0x2c, | ||
2432 | 0x2c, | ||
2433 | 0x2c, | ||
2434 | 0x7e, | ||
2435 | 0x46, | ||
2436 | 0x46, | ||
2437 | 0x46, | ||
2438 | 0xef, | ||
2439 | 0x00, | ||
2440 | 0x00, | ||
2441 | 0x00, | ||
2442 | |||
2443 | 0x18, | ||
2444 | 0x24, | ||
2445 | 0x18, | ||
2446 | 0x18, | ||
2447 | 0x3c, | ||
2448 | 0x2c, | ||
2449 | 0x2c, | ||
2450 | 0x2c, | ||
2451 | 0x7e, | ||
2452 | 0x46, | ||
2453 | 0x46, | ||
2454 | 0x46, | ||
2455 | 0xef, | ||
2456 | 0x00, | ||
2457 | 0x00, | ||
2458 | 0x00, | ||
2459 | |||
2460 | 0x0c, | ||
2461 | 0x18, | ||
2462 | 0xff, | ||
2463 | 0x61, | ||
2464 | 0x60, | ||
2465 | 0x60, | ||
2466 | 0x64, | ||
2467 | 0x7c, | ||
2468 | 0x64, | ||
2469 | 0x60, | ||
2470 | 0x60, | ||
2471 | 0x61, | ||
2472 | 0xfe, | ||
2473 | 0x00, | ||
2474 | 0x00, | ||
2475 | 0x00, | ||
2476 | |||
2477 | 0x00, | ||
2478 | 0x00, | ||
2479 | 0x00, | ||
2480 | 0x00, | ||
2481 | 0x00, | ||
2482 | 0x76, | ||
2483 | 0x9b, | ||
2484 | 0x1b, | ||
2485 | 0x3f, | ||
2486 | 0xd8, | ||
2487 | 0xd8, | ||
2488 | 0xd9, | ||
2489 | 0x6e, | ||
2490 | 0x00, | ||
2491 | 0x00, | ||
2492 | 0x00, | ||
2493 | |||
2494 | 0x00, | ||
2495 | 0x1f, | ||
2496 | 0x1d, | ||
2497 | 0x1d, | ||
2498 | 0x3c, | ||
2499 | 0x2c, | ||
2500 | 0x2e, | ||
2501 | 0x2c, | ||
2502 | 0x7c, | ||
2503 | 0x4c, | ||
2504 | 0x4c, | ||
2505 | 0x4d, | ||
2506 | 0xef, | ||
2507 | 0x00, | ||
2508 | 0x00, | ||
2509 | 0x00, | ||
2510 | |||
2511 | 0x00, | ||
2512 | 0x18, | ||
2513 | 0x2c, | ||
2514 | 0x46, | ||
2515 | 0x00, | ||
2516 | 0x3c, | ||
2517 | 0x66, | ||
2518 | 0x66, | ||
2519 | 0x66, | ||
2520 | 0x66, | ||
2521 | 0x66, | ||
2522 | 0x66, | ||
2523 | 0x3c, | ||
2524 | 0x00, | ||
2525 | 0x00, | ||
2526 | 0x00, | ||
2527 | |||
2528 | 0x00, | ||
2529 | 0x00, | ||
2530 | 0x66, | ||
2531 | 0x00, | ||
2532 | 0x00, | ||
2533 | 0x3c, | ||
2534 | 0x66, | ||
2535 | 0x66, | ||
2536 | 0x66, | ||
2537 | 0x66, | ||
2538 | 0x66, | ||
2539 | 0x66, | ||
2540 | 0x3c, | ||
2541 | 0x00, | ||
2542 | 0x00, | ||
2543 | 0x00, | ||
2544 | |||
2545 | 0x00, | ||
2546 | 0x30, | ||
2547 | 0x18, | ||
2548 | 0x04, | ||
2549 | 0x00, | ||
2550 | 0x3c, | ||
2551 | 0x66, | ||
2552 | 0x66, | ||
2553 | 0x66, | ||
2554 | 0x66, | ||
2555 | 0x66, | ||
2556 | 0x66, | ||
2557 | 0x3c, | ||
2558 | 0x00, | ||
2559 | 0x00, | ||
2560 | 0x00, | ||
2561 | |||
2562 | 0x00, | ||
2563 | 0x18, | ||
2564 | 0x2c, | ||
2565 | 0x46, | ||
2566 | 0x00, | ||
2567 | 0xee, | ||
2568 | 0x66, | ||
2569 | 0x66, | ||
2570 | 0x66, | ||
2571 | 0x66, | ||
2572 | 0x66, | ||
2573 | 0x67, | ||
2574 | 0x3a, | ||
2575 | 0x00, | ||
2576 | 0x00, | ||
2577 | 0x00, | ||
2578 | |||
2579 | 0x00, | ||
2580 | 0x30, | ||
2581 | 0x18, | ||
2582 | 0x04, | ||
2583 | 0x00, | ||
2584 | 0xee, | ||
2585 | 0x66, | ||
2586 | 0x66, | ||
2587 | 0x66, | ||
2588 | 0x66, | ||
2589 | 0x66, | ||
2590 | 0x67, | ||
2591 | 0x3a, | ||
2592 | 0x00, | ||
2593 | 0x00, | ||
2594 | 0x00, | ||
2595 | |||
2596 | 0x00, | ||
2597 | 0x00, | ||
2598 | 0x66, | ||
2599 | 0x00, | ||
2600 | 0x00, | ||
2601 | 0xf7, | ||
2602 | 0x62, | ||
2603 | 0x62, | ||
2604 | 0x34, | ||
2605 | 0x34, | ||
2606 | 0x18, | ||
2607 | 0x18, | ||
2608 | 0x18, | ||
2609 | 0x10, | ||
2610 | 0xb0, | ||
2611 | 0xe0, | ||
2612 | |||
2613 | 0x66, | ||
2614 | 0x00, | ||
2615 | 0x3c, | ||
2616 | 0x66, | ||
2617 | 0xc3, | ||
2618 | 0xc3, | ||
2619 | 0xc3, | ||
2620 | 0xc3, | ||
2621 | 0xc3, | ||
2622 | 0xc3, | ||
2623 | 0xc3, | ||
2624 | 0x66, | ||
2625 | 0x3c, | ||
2626 | 0x00, | ||
2627 | 0x00, | ||
2628 | 0x00, | ||
2629 | |||
2630 | 0x66, | ||
2631 | 0x00, | ||
2632 | 0xf7, | ||
2633 | 0x62, | ||
2634 | 0x62, | ||
2635 | 0x62, | ||
2636 | 0x62, | ||
2637 | 0x62, | ||
2638 | 0x62, | ||
2639 | 0x62, | ||
2640 | 0x62, | ||
2641 | 0x62, | ||
2642 | 0x3c, | ||
2643 | 0x00, | ||
2644 | 0x00, | ||
2645 | 0x00, | ||
2646 | |||
2647 | 0x00, | ||
2648 | 0x00, | ||
2649 | 0x10, | ||
2650 | 0x10, | ||
2651 | 0x10, | ||
2652 | 0x7c, | ||
2653 | 0xc6, | ||
2654 | 0xc0, | ||
2655 | 0xc0, | ||
2656 | 0xc0, | ||
2657 | 0xc0, | ||
2658 | 0xc2, | ||
2659 | 0x7c, | ||
2660 | 0x10, | ||
2661 | 0x10, | ||
2662 | 0x00, | ||
2663 | |||
2664 | 0x00, | ||
2665 | 0x38, | ||
2666 | 0x64, | ||
2667 | 0x6c, | ||
2668 | 0x60, | ||
2669 | 0x60, | ||
2670 | 0xf0, | ||
2671 | 0x60, | ||
2672 | 0x60, | ||
2673 | 0x60, | ||
2674 | 0x60, | ||
2675 | 0x66, | ||
2676 | 0xfc, | ||
2677 | 0x00, | ||
2678 | 0x00, | ||
2679 | 0x00, | ||
2680 | |||
2681 | 0x00, | ||
2682 | 0x81, | ||
2683 | 0xc3, | ||
2684 | 0x66, | ||
2685 | 0x3c, | ||
2686 | 0x18, | ||
2687 | 0xff, | ||
2688 | 0x18, | ||
2689 | 0x18, | ||
2690 | 0xff, | ||
2691 | 0x18, | ||
2692 | 0x18, | ||
2693 | 0x18, | ||
2694 | 0x00, | ||
2695 | 0x00, | ||
2696 | 0x00, | ||
2697 | |||
2698 | 0x00, | ||
2699 | 0xfe, | ||
2700 | 0x63, | ||
2701 | 0x63, | ||
2702 | 0x63, | ||
2703 | 0x63, | ||
2704 | 0x6e, | ||
2705 | 0x60, | ||
2706 | 0x64, | ||
2707 | 0x6e, | ||
2708 | 0x64, | ||
2709 | 0x64, | ||
2710 | 0xf5, | ||
2711 | 0x06, | ||
2712 | 0x00, | ||
2713 | 0x00, | ||
2714 | |||
2715 | 0x00, | ||
2716 | 0x0e, | ||
2717 | 0x19, | ||
2718 | 0x1b, | ||
2719 | 0x18, | ||
2720 | 0x18, | ||
2721 | 0x3c, | ||
2722 | 0x18, | ||
2723 | 0x18, | ||
2724 | 0x18, | ||
2725 | 0x18, | ||
2726 | 0xd8, | ||
2727 | 0x98, | ||
2728 | 0x70, | ||
2729 | 0x00, | ||
2730 | 0x00, | ||
2731 | |||
2732 | 0x00, | ||
2733 | 0x0c, | ||
2734 | 0x18, | ||
2735 | 0x20, | ||
2736 | 0x00, | ||
2737 | 0x78, | ||
2738 | 0x8c, | ||
2739 | 0x0c, | ||
2740 | 0x3c, | ||
2741 | 0xcc, | ||
2742 | 0xcc, | ||
2743 | 0xcd, | ||
2744 | 0x76, | ||
2745 | 0x00, | ||
2746 | 0x00, | ||
2747 | 0x00, | ||
2748 | |||
2749 | 0x00, | ||
2750 | 0x06, | ||
2751 | 0x0c, | ||
2752 | 0x10, | ||
2753 | 0x00, | ||
2754 | 0x38, | ||
2755 | 0x18, | ||
2756 | 0x18, | ||
2757 | 0x18, | ||
2758 | 0x18, | ||
2759 | 0x18, | ||
2760 | 0x18, | ||
2761 | 0x3c, | ||
2762 | 0x00, | ||
2763 | 0x00, | ||
2764 | 0x00, | ||
2765 | |||
2766 | 0x00, | ||
2767 | 0x0c, | ||
2768 | 0x18, | ||
2769 | 0x20, | ||
2770 | 0x00, | ||
2771 | 0x3c, | ||
2772 | 0x66, | ||
2773 | 0x66, | ||
2774 | 0x66, | ||
2775 | 0x66, | ||
2776 | 0x66, | ||
2777 | 0x66, | ||
2778 | 0x3c, | ||
2779 | 0x00, | ||
2780 | 0x00, | ||
2781 | 0x00, | ||
2782 | |||
2783 | 0x00, | ||
2784 | 0x0c, | ||
2785 | 0x18, | ||
2786 | 0x20, | ||
2787 | 0x00, | ||
2788 | 0xee, | ||
2789 | 0x66, | ||
2790 | 0x66, | ||
2791 | 0x66, | ||
2792 | 0x66, | ||
2793 | 0x66, | ||
2794 | 0x67, | ||
2795 | 0x3a, | ||
2796 | 0x00, | ||
2797 | 0x00, | ||
2798 | 0x00, | ||
2799 | |||
2800 | 0x00, | ||
2801 | 0x00, | ||
2802 | 0x32, | ||
2803 | 0x4c, | ||
2804 | 0x00, | ||
2805 | 0x5c, | ||
2806 | 0xf6, | ||
2807 | 0x66, | ||
2808 | 0x66, | ||
2809 | 0x66, | ||
2810 | 0x66, | ||
2811 | 0x66, | ||
2812 | 0xf7, | ||
2813 | 0x00, | ||
2814 | 0x00, | ||
2815 | 0x00, | ||
2816 | |||
2817 | 0x32, | ||
2818 | 0x4c, | ||
2819 | 0x00, | ||
2820 | 0xe7, | ||
2821 | 0x72, | ||
2822 | 0x52, | ||
2823 | 0x5a, | ||
2824 | 0x4a, | ||
2825 | 0x4e, | ||
2826 | 0x46, | ||
2827 | 0x46, | ||
2828 | 0x42, | ||
2829 | 0xe2, | ||
2830 | 0x00, | ||
2831 | 0x00, | ||
2832 | 0x00, | ||
2833 | |||
2834 | 0x00, | ||
2835 | 0x78, | ||
2836 | 0x8c, | ||
2837 | 0x0c, | ||
2838 | 0x3c, | ||
2839 | 0xcc, | ||
2840 | 0xcc, | ||
2841 | 0xcd, | ||
2842 | 0x76, | ||
2843 | 0x00, | ||
2844 | 0xfe, | ||
2845 | 0x00, | ||
2846 | 0x00, | ||
2847 | 0x00, | ||
2848 | 0x00, | ||
2849 | 0x00, | ||
2850 | |||
2851 | 0x00, | ||
2852 | 0x3c, | ||
2853 | 0x66, | ||
2854 | 0x66, | ||
2855 | 0x66, | ||
2856 | 0x66, | ||
2857 | 0x66, | ||
2858 | 0x66, | ||
2859 | 0x3c, | ||
2860 | 0x00, | ||
2861 | 0x7e, | ||
2862 | 0x00, | ||
2863 | 0x00, | ||
2864 | 0x00, | ||
2865 | 0x00, | ||
2866 | 0x00, | ||
2867 | |||
2868 | 0x00, | ||
2869 | 0x30, | ||
2870 | 0x30, | ||
2871 | 0x00, | ||
2872 | 0x30, | ||
2873 | 0x10, | ||
2874 | 0x10, | ||
2875 | 0x20, | ||
2876 | 0x40, | ||
2877 | 0xc0, | ||
2878 | 0xc6, | ||
2879 | 0xc2, | ||
2880 | 0x7c, | ||
2881 | 0x00, | ||
2882 | 0x00, | ||
2883 | 0x00, | ||
2884 | |||
2885 | 0x00, | ||
2886 | 0x00, | ||
2887 | 0x00, | ||
2888 | 0x00, | ||
2889 | 0x00, | ||
2890 | 0x00, | ||
2891 | 0xfe, | ||
2892 | 0xc0, | ||
2893 | 0xc0, | ||
2894 | 0xc0, | ||
2895 | 0xc0, | ||
2896 | 0x00, | ||
2897 | 0x00, | ||
2898 | 0x00, | ||
2899 | 0x00, | ||
2900 | 0x00, | ||
2901 | |||
2902 | 0x00, | ||
2903 | 0x00, | ||
2904 | 0x00, | ||
2905 | 0x00, | ||
2906 | 0x00, | ||
2907 | 0x00, | ||
2908 | 0xfe, | ||
2909 | 0x06, | ||
2910 | 0x06, | ||
2911 | 0x06, | ||
2912 | 0x06, | ||
2913 | 0x00, | ||
2914 | 0x00, | ||
2915 | 0x00, | ||
2916 | 0x00, | ||
2917 | 0x00, | ||
2918 | |||
2919 | 0x00, | ||
2920 | 0x20, | ||
2921 | 0xe0, | ||
2922 | 0x63, | ||
2923 | 0x66, | ||
2924 | 0xfc, | ||
2925 | 0x18, | ||
2926 | 0x30, | ||
2927 | 0x60, | ||
2928 | 0xce, | ||
2929 | 0x93, | ||
2930 | 0x06, | ||
2931 | 0x0c, | ||
2932 | 0x1f, | ||
2933 | 0x00, | ||
2934 | 0x00, | ||
2935 | |||
2936 | 0x00, | ||
2937 | 0x20, | ||
2938 | 0xe0, | ||
2939 | 0x63, | ||
2940 | 0x66, | ||
2941 | 0xfc, | ||
2942 | 0x18, | ||
2943 | 0x30, | ||
2944 | 0x64, | ||
2945 | 0xc8, | ||
2946 | 0x96, | ||
2947 | 0x3f, | ||
2948 | 0x06, | ||
2949 | 0x06, | ||
2950 | 0x00, | ||
2951 | 0x00, | ||
2952 | |||
2953 | 0x00, | ||
2954 | 0x18, | ||
2955 | 0x18, | ||
2956 | 0x00, | ||
2957 | 0x08, | ||
2958 | 0x18, | ||
2959 | 0x18, | ||
2960 | 0x18, | ||
2961 | 0x3c, | ||
2962 | 0x3c, | ||
2963 | 0x3c, | ||
2964 | 0x3c, | ||
2965 | 0x18, | ||
2966 | 0x00, | ||
2967 | 0x00, | ||
2968 | 0x00, | ||
2969 | |||
2970 | 0x00, | ||
2971 | 0x00, | ||
2972 | 0x00, | ||
2973 | 0x00, | ||
2974 | 0x00, | ||
2975 | 0x36, | ||
2976 | 0x6c, | ||
2977 | 0xd8, | ||
2978 | 0xd8, | ||
2979 | 0x6c, | ||
2980 | 0x36, | ||
2981 | 0x00, | ||
2982 | 0x00, | ||
2983 | 0x00, | ||
2984 | 0x00, | ||
2985 | 0x00, | ||
2986 | |||
2987 | 0x00, | ||
2988 | 0x00, | ||
2989 | 0x00, | ||
2990 | 0x00, | ||
2991 | 0x00, | ||
2992 | 0xd8, | ||
2993 | 0x6c, | ||
2994 | 0x36, | ||
2995 | 0x36, | ||
2996 | 0x6c, | ||
2997 | 0xd8, | ||
2998 | 0x00, | ||
2999 | 0x00, | ||
3000 | 0x00, | ||
3001 | 0x00, | ||
3002 | 0x00, | ||
3003 | |||
3004 | 0x82, | ||
3005 | 0x10, | ||
3006 | 0x82, | ||
3007 | 0x10, | ||
3008 | 0x82, | ||
3009 | 0x10, | ||
3010 | 0x82, | ||
3011 | 0x10, | ||
3012 | 0x82, | ||
3013 | 0x10, | ||
3014 | 0x82, | ||
3015 | 0x10, | ||
3016 | 0x82, | ||
3017 | 0x10, | ||
3018 | 0x82, | ||
3019 | 0x10, | ||
3020 | |||
3021 | 0x00, | ||
3022 | 0x95, | ||
3023 | 0x00, | ||
3024 | 0xa9, | ||
3025 | 0x00, | ||
3026 | 0x95, | ||
3027 | 0x00, | ||
3028 | 0xa9, | ||
3029 | 0x00, | ||
3030 | 0x95, | ||
3031 | 0x00, | ||
3032 | 0xa9, | ||
3033 | 0x00, | ||
3034 | 0x95, | ||
3035 | 0x00, | ||
3036 | 0xa9, | ||
3037 | |||
3038 | 0x92, | ||
3039 | 0x49, | ||
3040 | 0x92, | ||
3041 | 0x49, | ||
3042 | 0x92, | ||
3043 | 0x49, | ||
3044 | 0x92, | ||
3045 | 0x49, | ||
3046 | 0x92, | ||
3047 | 0x49, | ||
3048 | 0x92, | ||
3049 | 0x49, | ||
3050 | 0x92, | ||
3051 | 0x49, | ||
3052 | 0x92, | ||
3053 | 0x49, | ||
3054 | |||
3055 | 0x18, | ||
3056 | 0x18, | ||
3057 | 0x18, | ||
3058 | 0x18, | ||
3059 | 0x18, | ||
3060 | 0x18, | ||
3061 | 0x18, | ||
3062 | 0x18, | ||
3063 | 0x18, | ||
3064 | 0x18, | ||
3065 | 0x18, | ||
3066 | 0x18, | ||
3067 | 0x18, | ||
3068 | 0x18, | ||
3069 | 0x18, | ||
3070 | 0x18, | ||
3071 | |||
3072 | 0x18, | ||
3073 | 0x18, | ||
3074 | 0x18, | ||
3075 | 0x18, | ||
3076 | 0x18, | ||
3077 | 0x18, | ||
3078 | 0x18, | ||
3079 | 0xf8, | ||
3080 | 0x18, | ||
3081 | 0x18, | ||
3082 | 0x18, | ||
3083 | 0x18, | ||
3084 | 0x18, | ||
3085 | 0x18, | ||
3086 | 0x18, | ||
3087 | 0x18, | ||
3088 | |||
3089 | 0x18, | ||
3090 | 0x18, | ||
3091 | 0x18, | ||
3092 | 0x18, | ||
3093 | 0x18, | ||
3094 | 0x18, | ||
3095 | 0xf8, | ||
3096 | 0x18, | ||
3097 | 0x18, | ||
3098 | 0xf8, | ||
3099 | 0x18, | ||
3100 | 0x18, | ||
3101 | 0x18, | ||
3102 | 0x18, | ||
3103 | 0x18, | ||
3104 | 0x18, | ||
3105 | |||
3106 | 0x66, | ||
3107 | 0x66, | ||
3108 | 0x66, | ||
3109 | 0x66, | ||
3110 | 0x66, | ||
3111 | 0x66, | ||
3112 | 0x66, | ||
3113 | 0xe6, | ||
3114 | 0x66, | ||
3115 | 0x66, | ||
3116 | 0x66, | ||
3117 | 0x66, | ||
3118 | 0x66, | ||
3119 | 0x66, | ||
3120 | 0x66, | ||
3121 | 0x66, | ||
3122 | |||
3123 | 0x00, | ||
3124 | 0x00, | ||
3125 | 0x00, | ||
3126 | 0x00, | ||
3127 | 0x00, | ||
3128 | 0x00, | ||
3129 | 0x00, | ||
3130 | 0xfe, | ||
3131 | 0x66, | ||
3132 | 0x66, | ||
3133 | 0x66, | ||
3134 | 0x66, | ||
3135 | 0x66, | ||
3136 | 0x66, | ||
3137 | 0x66, | ||
3138 | 0x66, | ||
3139 | |||
3140 | 0x00, | ||
3141 | 0x00, | ||
3142 | 0x00, | ||
3143 | 0x00, | ||
3144 | 0x00, | ||
3145 | 0x00, | ||
3146 | 0xf8, | ||
3147 | 0x18, | ||
3148 | 0x18, | ||
3149 | 0xf8, | ||
3150 | 0x18, | ||
3151 | 0x18, | ||
3152 | 0x18, | ||
3153 | 0x18, | ||
3154 | 0x18, | ||
3155 | 0x18, | ||
3156 | |||
3157 | 0x66, | ||
3158 | 0x66, | ||
3159 | 0x66, | ||
3160 | 0x66, | ||
3161 | 0x66, | ||
3162 | 0x66, | ||
3163 | 0xe6, | ||
3164 | 0x06, | ||
3165 | 0x06, | ||
3166 | 0xe6, | ||
3167 | 0x66, | ||
3168 | 0x66, | ||
3169 | 0x66, | ||
3170 | 0x66, | ||
3171 | 0x66, | ||
3172 | 0x66, | ||
3173 | |||
3174 | 0x66, | ||
3175 | 0x66, | ||
3176 | 0x66, | ||
3177 | 0x66, | ||
3178 | 0x66, | ||
3179 | 0x66, | ||
3180 | 0x66, | ||
3181 | 0x66, | ||
3182 | 0x66, | ||
3183 | 0x66, | ||
3184 | 0x66, | ||
3185 | 0x66, | ||
3186 | 0x66, | ||
3187 | 0x66, | ||
3188 | 0x66, | ||
3189 | 0x66, | ||
3190 | |||
3191 | 0x00, | ||
3192 | 0x00, | ||
3193 | 0x00, | ||
3194 | 0x00, | ||
3195 | 0x00, | ||
3196 | 0x00, | ||
3197 | 0xfe, | ||
3198 | 0x06, | ||
3199 | 0x06, | ||
3200 | 0xe6, | ||
3201 | 0x66, | ||
3202 | 0x66, | ||
3203 | 0x66, | ||
3204 | 0x66, | ||
3205 | 0x66, | ||
3206 | 0x66, | ||
3207 | |||
3208 | 0x66, | ||
3209 | 0x66, | ||
3210 | 0x66, | ||
3211 | 0x66, | ||
3212 | 0x66, | ||
3213 | 0x66, | ||
3214 | 0xe6, | ||
3215 | 0x06, | ||
3216 | 0x06, | ||
3217 | 0xfe, | ||
3218 | 0x00, | ||
3219 | 0x00, | ||
3220 | 0x00, | ||
3221 | 0x00, | ||
3222 | 0x00, | ||
3223 | 0x00, | ||
3224 | |||
3225 | 0x66, | ||
3226 | 0x66, | ||
3227 | 0x66, | ||
3228 | 0x66, | ||
3229 | 0x66, | ||
3230 | 0x66, | ||
3231 | 0x66, | ||
3232 | 0xfe, | ||
3233 | 0x00, | ||
3234 | 0x00, | ||
3235 | 0x00, | ||
3236 | 0x00, | ||
3237 | 0x00, | ||
3238 | 0x00, | ||
3239 | 0x00, | ||
3240 | 0x00, | ||
3241 | |||
3242 | 0x18, | ||
3243 | 0x18, | ||
3244 | 0x18, | ||
3245 | 0x18, | ||
3246 | 0x18, | ||
3247 | 0x18, | ||
3248 | 0xf8, | ||
3249 | 0x18, | ||
3250 | 0x18, | ||
3251 | 0xf8, | ||
3252 | 0x00, | ||
3253 | 0x00, | ||
3254 | 0x00, | ||
3255 | 0x00, | ||
3256 | 0x00, | ||
3257 | 0x00, | ||
3258 | |||
3259 | 0x00, | ||
3260 | 0x00, | ||
3261 | 0x00, | ||
3262 | 0x00, | ||
3263 | 0x00, | ||
3264 | 0x00, | ||
3265 | 0x00, | ||
3266 | 0xf8, | ||
3267 | 0x18, | ||
3268 | 0x18, | ||
3269 | 0x18, | ||
3270 | 0x18, | ||
3271 | 0x18, | ||
3272 | 0x18, | ||
3273 | 0x18, | ||
3274 | 0x18, | ||
3275 | |||
3276 | 0x18, | ||
3277 | 0x18, | ||
3278 | 0x18, | ||
3279 | 0x18, | ||
3280 | 0x18, | ||
3281 | 0x18, | ||
3282 | 0x18, | ||
3283 | 0x1f, | ||
3284 | 0x00, | ||
3285 | 0x00, | ||
3286 | 0x00, | ||
3287 | 0x00, | ||
3288 | 0x00, | ||
3289 | 0x00, | ||
3290 | 0x00, | ||
3291 | 0x00, | ||
3292 | |||
3293 | 0x18, | ||
3294 | 0x18, | ||
3295 | 0x18, | ||
3296 | 0x18, | ||
3297 | 0x18, | ||
3298 | 0x18, | ||
3299 | 0x18, | ||
3300 | 0xff, | ||
3301 | 0x00, | ||
3302 | 0x00, | ||
3303 | 0x00, | ||
3304 | 0x00, | ||
3305 | 0x00, | ||
3306 | 0x00, | ||
3307 | 0x00, | ||
3308 | 0x00, | ||
3309 | |||
3310 | 0x00, | ||
3311 | 0x00, | ||
3312 | 0x00, | ||
3313 | 0x00, | ||
3314 | 0x00, | ||
3315 | 0x00, | ||
3316 | 0x00, | ||
3317 | 0xff, | ||
3318 | 0x18, | ||
3319 | 0x18, | ||
3320 | 0x18, | ||
3321 | 0x18, | ||
3322 | 0x18, | ||
3323 | 0x18, | ||
3324 | 0x18, | ||
3325 | 0x18, | ||
3326 | |||
3327 | 0x18, | ||
3328 | 0x18, | ||
3329 | 0x18, | ||
3330 | 0x18, | ||
3331 | 0x18, | ||
3332 | 0x18, | ||
3333 | 0x18, | ||
3334 | 0x1f, | ||
3335 | 0x18, | ||
3336 | 0x18, | ||
3337 | 0x18, | ||
3338 | 0x18, | ||
3339 | 0x18, | ||
3340 | 0x18, | ||
3341 | 0x18, | ||
3342 | 0x18, | ||
3343 | |||
3344 | 0x00, | ||
3345 | 0x00, | ||
3346 | 0x00, | ||
3347 | 0x00, | ||
3348 | 0x00, | ||
3349 | 0x00, | ||
3350 | 0x00, | ||
3351 | 0xff, | ||
3352 | 0x00, | ||
3353 | 0x00, | ||
3354 | 0x00, | ||
3355 | 0x00, | ||
3356 | 0x00, | ||
3357 | 0x00, | ||
3358 | 0x00, | ||
3359 | 0x00, | ||
3360 | |||
3361 | 0x18, | ||
3362 | 0x18, | ||
3363 | 0x18, | ||
3364 | 0x18, | ||
3365 | 0x18, | ||
3366 | 0x18, | ||
3367 | 0x18, | ||
3368 | 0xff, | ||
3369 | 0x18, | ||
3370 | 0x18, | ||
3371 | 0x18, | ||
3372 | 0x18, | ||
3373 | 0x18, | ||
3374 | 0x18, | ||
3375 | 0x18, | ||
3376 | 0x18, | ||
3377 | |||
3378 | 0x18, | ||
3379 | 0x18, | ||
3380 | 0x18, | ||
3381 | 0x18, | ||
3382 | 0x18, | ||
3383 | 0x18, | ||
3384 | 0x1f, | ||
3385 | 0x18, | ||
3386 | 0x18, | ||
3387 | 0x1f, | ||
3388 | 0x18, | ||
3389 | 0x18, | ||
3390 | 0x18, | ||
3391 | 0x18, | ||
3392 | 0x18, | ||
3393 | 0x18, | ||
3394 | |||
3395 | 0x66, | ||
3396 | 0x66, | ||
3397 | 0x66, | ||
3398 | 0x66, | ||
3399 | 0x66, | ||
3400 | 0x66, | ||
3401 | 0x66, | ||
3402 | 0x67, | ||
3403 | 0x66, | ||
3404 | 0x66, | ||
3405 | 0x66, | ||
3406 | 0x66, | ||
3407 | 0x66, | ||
3408 | 0x66, | ||
3409 | 0x66, | ||
3410 | 0x66, | ||
3411 | |||
3412 | 0x66, | ||
3413 | 0x66, | ||
3414 | 0x66, | ||
3415 | 0x66, | ||
3416 | 0x66, | ||
3417 | 0x66, | ||
3418 | 0x67, | ||
3419 | 0x60, | ||
3420 | 0x60, | ||
3421 | 0x7f, | ||
3422 | 0x00, | ||
3423 | 0x00, | ||
3424 | 0x00, | ||
3425 | 0x00, | ||
3426 | 0x00, | ||
3427 | 0x00, | ||
3428 | |||
3429 | 0x00, | ||
3430 | 0x00, | ||
3431 | 0x00, | ||
3432 | 0x00, | ||
3433 | 0x00, | ||
3434 | 0x00, | ||
3435 | 0x7f, | ||
3436 | 0x60, | ||
3437 | 0x60, | ||
3438 | 0x67, | ||
3439 | 0x66, | ||
3440 | 0x66, | ||
3441 | 0x66, | ||
3442 | 0x66, | ||
3443 | 0x66, | ||
3444 | 0x66, | ||
3445 | |||
3446 | 0x66, | ||
3447 | 0x66, | ||
3448 | 0x66, | ||
3449 | 0x66, | ||
3450 | 0x66, | ||
3451 | 0x66, | ||
3452 | 0xe7, | ||
3453 | 0x00, | ||
3454 | 0x00, | ||
3455 | 0xff, | ||
3456 | 0x00, | ||
3457 | 0x00, | ||
3458 | 0x00, | ||
3459 | 0x00, | ||
3460 | 0x00, | ||
3461 | 0x00, | ||
3462 | |||
3463 | 0x00, | ||
3464 | 0x00, | ||
3465 | 0x00, | ||
3466 | 0x00, | ||
3467 | 0x00, | ||
3468 | 0x00, | ||
3469 | 0xff, | ||
3470 | 0x00, | ||
3471 | 0x00, | ||
3472 | 0xe7, | ||
3473 | 0x66, | ||
3474 | 0x66, | ||
3475 | 0x66, | ||
3476 | 0x66, | ||
3477 | 0x66, | ||
3478 | 0x66, | ||
3479 | |||
3480 | 0x66, | ||
3481 | 0x66, | ||
3482 | 0x66, | ||
3483 | 0x66, | ||
3484 | 0x66, | ||
3485 | 0x66, | ||
3486 | 0x67, | ||
3487 | 0x60, | ||
3488 | 0x60, | ||
3489 | 0x67, | ||
3490 | 0x66, | ||
3491 | 0x66, | ||
3492 | 0x66, | ||
3493 | 0x66, | ||
3494 | 0x66, | ||
3495 | 0x66, | ||
3496 | |||
3497 | 0x00, | ||
3498 | 0x00, | ||
3499 | 0x00, | ||
3500 | 0x00, | ||
3501 | 0x00, | ||
3502 | 0x00, | ||
3503 | 0xff, | ||
3504 | 0x00, | ||
3505 | 0x00, | ||
3506 | 0xff, | ||
3507 | 0x00, | ||
3508 | 0x00, | ||
3509 | 0x00, | ||
3510 | 0x00, | ||
3511 | 0x00, | ||
3512 | 0x00, | ||
3513 | |||
3514 | 0x66, | ||
3515 | 0x66, | ||
3516 | 0x66, | ||
3517 | 0x66, | ||
3518 | 0x66, | ||
3519 | 0x66, | ||
3520 | 0xe7, | ||
3521 | 0x00, | ||
3522 | 0x00, | ||
3523 | 0xe7, | ||
3524 | 0x66, | ||
3525 | 0x66, | ||
3526 | 0x66, | ||
3527 | 0x66, | ||
3528 | 0x66, | ||
3529 | 0x66, | ||
3530 | |||
3531 | 0x18, | ||
3532 | 0x18, | ||
3533 | 0x18, | ||
3534 | 0x18, | ||
3535 | 0x18, | ||
3536 | 0x18, | ||
3537 | 0xff, | ||
3538 | 0x00, | ||
3539 | 0x00, | ||
3540 | 0xff, | ||
3541 | 0x00, | ||
3542 | 0x00, | ||
3543 | 0x00, | ||
3544 | 0x00, | ||
3545 | 0x00, | ||
3546 | 0x00, | ||
3547 | |||
3548 | 0x66, | ||
3549 | 0x66, | ||
3550 | 0x66, | ||
3551 | 0x66, | ||
3552 | 0x66, | ||
3553 | 0x66, | ||
3554 | 0x66, | ||
3555 | 0xff, | ||
3556 | 0x00, | ||
3557 | 0x00, | ||
3558 | 0x00, | ||
3559 | 0x00, | ||
3560 | 0x00, | ||
3561 | 0x00, | ||
3562 | 0x00, | ||
3563 | 0x00, | ||
3564 | |||
3565 | 0x00, | ||
3566 | 0x00, | ||
3567 | 0x00, | ||
3568 | 0x00, | ||
3569 | 0x00, | ||
3570 | 0x00, | ||
3571 | 0xff, | ||
3572 | 0x00, | ||
3573 | 0x00, | ||
3574 | 0xff, | ||
3575 | 0x18, | ||
3576 | 0x18, | ||
3577 | 0x18, | ||
3578 | 0x18, | ||
3579 | 0x18, | ||
3580 | 0x18, | ||
3581 | |||
3582 | 0x00, | ||
3583 | 0x00, | ||
3584 | 0x00, | ||
3585 | 0x00, | ||
3586 | 0x00, | ||
3587 | 0x00, | ||
3588 | 0x00, | ||
3589 | 0xff, | ||
3590 | 0x66, | ||
3591 | 0x66, | ||
3592 | 0x66, | ||
3593 | 0x66, | ||
3594 | 0x66, | ||
3595 | 0x66, | ||
3596 | 0x66, | ||
3597 | 0x66, | ||
3598 | |||
3599 | 0x66, | ||
3600 | 0x66, | ||
3601 | 0x66, | ||
3602 | 0x66, | ||
3603 | 0x66, | ||
3604 | 0x66, | ||
3605 | 0x66, | ||
3606 | 0x7f, | ||
3607 | 0x00, | ||
3608 | 0x00, | ||
3609 | 0x00, | ||
3610 | 0x00, | ||
3611 | 0x00, | ||
3612 | 0x00, | ||
3613 | 0x00, | ||
3614 | 0x00, | ||
3615 | |||
3616 | 0x18, | ||
3617 | 0x18, | ||
3618 | 0x18, | ||
3619 | 0x18, | ||
3620 | 0x18, | ||
3621 | 0x18, | ||
3622 | 0x1f, | ||
3623 | 0x18, | ||
3624 | 0x18, | ||
3625 | 0x1f, | ||
3626 | 0x00, | ||
3627 | 0x00, | ||
3628 | 0x00, | ||
3629 | 0x00, | ||
3630 | 0x00, | ||
3631 | 0x00, | ||
3632 | |||
3633 | 0x00, | ||
3634 | 0x00, | ||
3635 | 0x00, | ||
3636 | 0x00, | ||
3637 | 0x00, | ||
3638 | 0x00, | ||
3639 | 0x1f, | ||
3640 | 0x18, | ||
3641 | 0x18, | ||
3642 | 0x1f, | ||
3643 | 0x18, | ||
3644 | 0x18, | ||
3645 | 0x18, | ||
3646 | 0x18, | ||
3647 | 0x18, | ||
3648 | 0x18, | ||
3649 | |||
3650 | 0x00, | ||
3651 | 0x00, | ||
3652 | 0x00, | ||
3653 | 0x00, | ||
3654 | 0x00, | ||
3655 | 0x00, | ||
3656 | 0x00, | ||
3657 | 0x7f, | ||
3658 | 0x66, | ||
3659 | 0x66, | ||
3660 | 0x66, | ||
3661 | 0x66, | ||
3662 | 0x66, | ||
3663 | 0x66, | ||
3664 | 0x66, | ||
3665 | 0x66, | ||
3666 | |||
3667 | 0x66, | ||
3668 | 0x66, | ||
3669 | 0x66, | ||
3670 | 0x66, | ||
3671 | 0x66, | ||
3672 | 0x66, | ||
3673 | 0x66, | ||
3674 | 0xff, | ||
3675 | 0x66, | ||
3676 | 0x66, | ||
3677 | 0x66, | ||
3678 | 0x66, | ||
3679 | 0x66, | ||
3680 | 0x66, | ||
3681 | 0x66, | ||
3682 | 0x66, | ||
3683 | |||
3684 | 0x18, | ||
3685 | 0x18, | ||
3686 | 0x18, | ||
3687 | 0x18, | ||
3688 | 0x18, | ||
3689 | 0x18, | ||
3690 | 0xff, | ||
3691 | 0x00, | ||
3692 | 0x00, | ||
3693 | 0xff, | ||
3694 | 0x18, | ||
3695 | 0x18, | ||
3696 | 0x18, | ||
3697 | 0x18, | ||
3698 | 0x18, | ||
3699 | 0x18, | ||
3700 | |||
3701 | 0x18, | ||
3702 | 0x18, | ||
3703 | 0x18, | ||
3704 | 0x18, | ||
3705 | 0x18, | ||
3706 | 0x18, | ||
3707 | 0x18, | ||
3708 | 0xf8, | ||
3709 | 0x00, | ||
3710 | 0x00, | ||
3711 | 0x00, | ||
3712 | 0x00, | ||
3713 | 0x00, | ||
3714 | 0x00, | ||
3715 | 0x00, | ||
3716 | 0x00, | ||
3717 | |||
3718 | 0x00, | ||
3719 | 0x00, | ||
3720 | 0x00, | ||
3721 | 0x00, | ||
3722 | 0x00, | ||
3723 | 0x00, | ||
3724 | 0x00, | ||
3725 | 0x1f, | ||
3726 | 0x18, | ||
3727 | 0x18, | ||
3728 | 0x18, | ||
3729 | 0x18, | ||
3730 | 0x18, | ||
3731 | 0x18, | ||
3732 | 0x18, | ||
3733 | 0x18, | ||
3734 | |||
3735 | 0xff, | ||
3736 | 0xff, | ||
3737 | 0xff, | ||
3738 | 0xff, | ||
3739 | 0xff, | ||
3740 | 0xff, | ||
3741 | 0xff, | ||
3742 | 0xff, | ||
3743 | 0xff, | ||
3744 | 0xff, | ||
3745 | 0xff, | ||
3746 | 0xff, | ||
3747 | 0xff, | ||
3748 | 0xff, | ||
3749 | 0xff, | ||
3750 | 0xff, | ||
3751 | |||
3752 | 0x00, | ||
3753 | 0x00, | ||
3754 | 0x00, | ||
3755 | 0x00, | ||
3756 | 0x00, | ||
3757 | 0x00, | ||
3758 | 0x00, | ||
3759 | 0x00, | ||
3760 | 0xff, | ||
3761 | 0xff, | ||
3762 | 0xff, | ||
3763 | 0xff, | ||
3764 | 0xff, | ||
3765 | 0xff, | ||
3766 | 0xff, | ||
3767 | 0xff, | ||
3768 | |||
3769 | 0xf0, | ||
3770 | 0xf0, | ||
3771 | 0xf0, | ||
3772 | 0xf0, | ||
3773 | 0xf0, | ||
3774 | 0xf0, | ||
3775 | 0xf0, | ||
3776 | 0xf0, | ||
3777 | 0xf0, | ||
3778 | 0xf0, | ||
3779 | 0xf0, | ||
3780 | 0xf0, | ||
3781 | 0xf0, | ||
3782 | 0xf0, | ||
3783 | 0xf0, | ||
3784 | 0xf0, | ||
3785 | |||
3786 | 0x0f, | ||
3787 | 0x0f, | ||
3788 | 0x0f, | ||
3789 | 0x0f, | ||
3790 | 0x0f, | ||
3791 | 0x0f, | ||
3792 | 0x0f, | ||
3793 | 0x0f, | ||
3794 | 0x0f, | ||
3795 | 0x0f, | ||
3796 | 0x0f, | ||
3797 | 0x0f, | ||
3798 | 0x0f, | ||
3799 | 0x0f, | ||
3800 | 0x0f, | ||
3801 | 0x0f, | ||
3802 | |||
3803 | 0xff, | ||
3804 | 0xff, | ||
3805 | 0xff, | ||
3806 | 0xff, | ||
3807 | 0xff, | ||
3808 | 0xff, | ||
3809 | 0xff, | ||
3810 | 0xff, | ||
3811 | 0x00, | ||
3812 | 0x00, | ||
3813 | 0x00, | ||
3814 | 0x00, | ||
3815 | 0x00, | ||
3816 | 0x00, | ||
3817 | 0x00, | ||
3818 | 0x00, | ||
3819 | |||
3820 | 0x00, | ||
3821 | 0x00, | ||
3822 | 0x00, | ||
3823 | 0x00, | ||
3824 | 0x00, | ||
3825 | 0x00, | ||
3826 | 0x77, | ||
3827 | 0xcc, | ||
3828 | 0xcc, | ||
3829 | 0xcc, | ||
3830 | 0xcc, | ||
3831 | 0xde, | ||
3832 | 0x73, | ||
3833 | 0x00, | ||
3834 | 0x00, | ||
3835 | 0x00, | ||
3836 | |||
3837 | 0x00, | ||
3838 | 0x7c, | ||
3839 | 0xc6, | ||
3840 | 0xc6, | ||
3841 | 0xc6, | ||
3842 | 0xc4, | ||
3843 | 0xc8, | ||
3844 | 0xc4, | ||
3845 | 0xc6, | ||
3846 | 0xc6, | ||
3847 | 0xc6, | ||
3848 | 0xc6, | ||
3849 | 0xdc, | ||
3850 | 0xc0, | ||
3851 | 0xc0, | ||
3852 | 0x00, | ||
3853 | |||
3854 | 0x00, | ||
3855 | 0xff, | ||
3856 | 0x61, | ||
3857 | 0x60, | ||
3858 | 0x60, | ||
3859 | 0x60, | ||
3860 | 0x60, | ||
3861 | 0x60, | ||
3862 | 0x60, | ||
3863 | 0x60, | ||
3864 | 0x60, | ||
3865 | 0x60, | ||
3866 | 0xf0, | ||
3867 | 0x00, | ||
3868 | 0x00, | ||
3869 | 0x00, | ||
3870 | |||
3871 | 0x00, | ||
3872 | 0x00, | ||
3873 | 0x00, | ||
3874 | 0x00, | ||
3875 | 0x01, | ||
3876 | 0x7e, | ||
3877 | 0xa4, | ||
3878 | 0x24, | ||
3879 | 0x2c, | ||
3880 | 0x6c, | ||
3881 | 0x6c, | ||
3882 | 0x6c, | ||
3883 | 0x48, | ||
3884 | 0x00, | ||
3885 | 0x00, | ||
3886 | 0x00, | ||
3887 | |||
3888 | 0x00, | ||
3889 | 0xff, | ||
3890 | 0xc1, | ||
3891 | 0x60, | ||
3892 | 0x30, | ||
3893 | 0x18, | ||
3894 | 0x0c, | ||
3895 | 0x18, | ||
3896 | 0x30, | ||
3897 | 0x60, | ||
3898 | 0xc0, | ||
3899 | 0xc1, | ||
3900 | 0xfe, | ||
3901 | 0x00, | ||
3902 | 0x00, | ||
3903 | 0x00, | ||
3904 | |||
3905 | 0x00, | ||
3906 | 0x00, | ||
3907 | 0x00, | ||
3908 | 0x00, | ||
3909 | 0x00, | ||
3910 | 0x7f, | ||
3911 | 0xc8, | ||
3912 | 0xc8, | ||
3913 | 0xc8, | ||
3914 | 0xc8, | ||
3915 | 0xc8, | ||
3916 | 0xc8, | ||
3917 | 0x70, | ||
3918 | 0x00, | ||
3919 | 0x00, | ||
3920 | 0x00, | ||
3921 | |||
3922 | 0x00, | ||
3923 | 0x00, | ||
3924 | 0x00, | ||
3925 | 0x00, | ||
3926 | 0x00, | ||
3927 | 0x22, | ||
3928 | 0x66, | ||
3929 | 0x66, | ||
3930 | 0x66, | ||
3931 | 0x66, | ||
3932 | 0x66, | ||
3933 | 0x7c, | ||
3934 | 0x60, | ||
3935 | 0x60, | ||
3936 | 0x60, | ||
3937 | 0xc0, | ||
3938 | |||
3939 | 0x00, | ||
3940 | 0x00, | ||
3941 | 0x00, | ||
3942 | 0x00, | ||
3943 | 0x00, | ||
3944 | 0x76, | ||
3945 | 0xdc, | ||
3946 | 0x18, | ||
3947 | 0x18, | ||
3948 | 0x18, | ||
3949 | 0x18, | ||
3950 | 0x18, | ||
3951 | 0x10, | ||
3952 | 0x00, | ||
3953 | 0x00, | ||
3954 | 0x00, | ||
3955 | |||
3956 | 0x00, | ||
3957 | 0x38, | ||
3958 | 0x10, | ||
3959 | 0x7c, | ||
3960 | 0xd6, | ||
3961 | 0xd6, | ||
3962 | 0xd6, | ||
3963 | 0xd6, | ||
3964 | 0xd6, | ||
3965 | 0xd6, | ||
3966 | 0x7c, | ||
3967 | 0x10, | ||
3968 | 0x38, | ||
3969 | 0x00, | ||
3970 | 0x00, | ||
3971 | 0x00, | ||
3972 | |||
3973 | 0x00, | ||
3974 | 0x38, | ||
3975 | 0x6c, | ||
3976 | 0xc6, | ||
3977 | 0xc6, | ||
3978 | 0xc6, | ||
3979 | 0xfe, | ||
3980 | 0xc6, | ||
3981 | 0xc6, | ||
3982 | 0xc6, | ||
3983 | 0xc6, | ||
3984 | 0x6c, | ||
3985 | 0x38, | ||
3986 | 0x00, | ||
3987 | 0x00, | ||
3988 | 0x00, | ||
3989 | |||
3990 | 0x00, | ||
3991 | 0x3c, | ||
3992 | 0x66, | ||
3993 | 0xc3, | ||
3994 | 0xc3, | ||
3995 | 0xc3, | ||
3996 | 0xc3, | ||
3997 | 0xc3, | ||
3998 | 0x66, | ||
3999 | 0x24, | ||
4000 | 0x24, | ||
4001 | 0xa5, | ||
4002 | 0xe7, | ||
4003 | 0x00, | ||
4004 | 0x00, | ||
4005 | 0x00, | ||
4006 | |||
4007 | 0x00, | ||
4008 | 0x1e, | ||
4009 | 0x31, | ||
4010 | 0x30, | ||
4011 | 0x18, | ||
4012 | 0x0c, | ||
4013 | 0x3e, | ||
4014 | 0x66, | ||
4015 | 0x66, | ||
4016 | 0x66, | ||
4017 | 0x66, | ||
4018 | 0x66, | ||
4019 | 0x3c, | ||
4020 | 0x00, | ||
4021 | 0x00, | ||
4022 | 0x00, | ||
4023 | |||
4024 | 0x00, | ||
4025 | 0x00, | ||
4026 | 0x00, | ||
4027 | 0x00, | ||
4028 | 0x6e, | ||
4029 | 0xff, | ||
4030 | 0x99, | ||
4031 | 0x99, | ||
4032 | 0x99, | ||
4033 | 0x99, | ||
4034 | 0xff, | ||
4035 | 0x76, | ||
4036 | 0x00, | ||
4037 | 0x00, | ||
4038 | 0x00, | ||
4039 | 0x00, | ||
4040 | |||
4041 | 0x00, | ||
4042 | 0x00, | ||
4043 | 0x00, | ||
4044 | 0x02, | ||
4045 | 0x04, | ||
4046 | 0x7c, | ||
4047 | 0xca, | ||
4048 | 0x92, | ||
4049 | 0xa6, | ||
4050 | 0x7c, | ||
4051 | 0x40, | ||
4052 | 0x80, | ||
4053 | 0x00, | ||
4054 | 0x00, | ||
4055 | 0x00, | ||
4056 | 0x00, | ||
4057 | |||
4058 | 0x00, | ||
4059 | 0x1c, | ||
4060 | 0x30, | ||
4061 | 0x60, | ||
4062 | 0x60, | ||
4063 | 0x60, | ||
4064 | 0x7c, | ||
4065 | 0x60, | ||
4066 | 0x60, | ||
4067 | 0x60, | ||
4068 | 0x60, | ||
4069 | 0x30, | ||
4070 | 0x1c, | ||
4071 | 0x00, | ||
4072 | 0x00, | ||
4073 | 0x00, | ||
4074 | |||
4075 | 0x00, | ||
4076 | 0x00, | ||
4077 | 0x7c, | ||
4078 | 0xc6, | ||
4079 | 0xc6, | ||
4080 | 0xc6, | ||
4081 | 0xc6, | ||
4082 | 0xc6, | ||
4083 | 0xc6, | ||
4084 | 0xc6, | ||
4085 | 0xc6, | ||
4086 | 0xc6, | ||
4087 | 0xc6, | ||
4088 | 0x00, | ||
4089 | 0x00, | ||
4090 | 0x00, | ||
4091 | |||
4092 | 0x00, | ||
4093 | 0x00, | ||
4094 | 0x00, | ||
4095 | 0xfe, | ||
4096 | 0x00, | ||
4097 | 0x00, | ||
4098 | 0x00, | ||
4099 | 0x7c, | ||
4100 | 0x00, | ||
4101 | 0x00, | ||
4102 | 0x00, | ||
4103 | 0xfe, | ||
4104 | 0x00, | ||
4105 | 0x00, | ||
4106 | 0x00, | ||
4107 | 0x00, | ||
4108 | |||
4109 | 0x00, | ||
4110 | 0x00, | ||
4111 | 0x00, | ||
4112 | 0x00, | ||
4113 | 0x18, | ||
4114 | 0x18, | ||
4115 | 0x7e, | ||
4116 | 0x18, | ||
4117 | 0x18, | ||
4118 | 0x00, | ||
4119 | 0x00, | ||
4120 | 0x7e, | ||
4121 | 0x00, | ||
4122 | 0x00, | ||
4123 | 0x00, | ||
4124 | 0x00, | ||
4125 | |||
4126 | 0x00, | ||
4127 | 0x00, | ||
4128 | 0x00, | ||
4129 | 0x30, | ||
4130 | 0x18, | ||
4131 | 0x0c, | ||
4132 | 0x06, | ||
4133 | 0x0c, | ||
4134 | 0x18, | ||
4135 | 0x30, | ||
4136 | 0x00, | ||
4137 | 0x7e, | ||
4138 | 0x00, | ||
4139 | 0x00, | ||
4140 | 0x00, | ||
4141 | 0x00, | ||
4142 | |||
4143 | 0x00, | ||
4144 | 0x00, | ||
4145 | 0x00, | ||
4146 | 0x0c, | ||
4147 | 0x18, | ||
4148 | 0x30, | ||
4149 | 0x60, | ||
4150 | 0x30, | ||
4151 | 0x18, | ||
4152 | 0x0c, | ||
4153 | 0x00, | ||
4154 | 0x7e, | ||
4155 | 0x00, | ||
4156 | 0x00, | ||
4157 | 0x00, | ||
4158 | 0x00, | ||
4159 | |||
4160 | 0x00, | ||
4161 | 0x00, | ||
4162 | 0x00, | ||
4163 | 0x0e, | ||
4164 | 0x19, | ||
4165 | 0x1b, | ||
4166 | 0x18, | ||
4167 | 0x18, | ||
4168 | 0x18, | ||
4169 | 0x18, | ||
4170 | 0x18, | ||
4171 | 0x18, | ||
4172 | 0x18, | ||
4173 | 0x18, | ||
4174 | 0x18, | ||
4175 | 0x18, | ||
4176 | |||
4177 | 0x18, | ||
4178 | 0x18, | ||
4179 | 0x18, | ||
4180 | 0x18, | ||
4181 | 0x18, | ||
4182 | 0x18, | ||
4183 | 0x18, | ||
4184 | 0x18, | ||
4185 | 0x18, | ||
4186 | 0xd8, | ||
4187 | 0x98, | ||
4188 | 0x70, | ||
4189 | 0x00, | ||
4190 | 0x00, | ||
4191 | 0x00, | ||
4192 | 0x00, | ||
4193 | |||
4194 | 0x00, | ||
4195 | 0x00, | ||
4196 | 0x00, | ||
4197 | 0x00, | ||
4198 | 0x18, | ||
4199 | 0x18, | ||
4200 | 0x00, | ||
4201 | 0x7e, | ||
4202 | 0x00, | ||
4203 | 0x18, | ||
4204 | 0x18, | ||
4205 | 0x00, | ||
4206 | 0x00, | ||
4207 | 0x00, | ||
4208 | 0x00, | ||
4209 | 0x00, | ||
4210 | |||
4211 | 0x00, | ||
4212 | 0x00, | ||
4213 | 0x00, | ||
4214 | 0x00, | ||
4215 | 0x00, | ||
4216 | 0x76, | ||
4217 | 0xdc, | ||
4218 | 0x00, | ||
4219 | 0x00, | ||
4220 | 0x76, | ||
4221 | 0xdc, | ||
4222 | 0x00, | ||
4223 | 0x00, | ||
4224 | 0x00, | ||
4225 | 0x00, | ||
4226 | 0x00, | ||
4227 | |||
4228 | 0x00, | ||
4229 | 0x38, | ||
4230 | 0x44, | ||
4231 | 0x44, | ||
4232 | 0x44, | ||
4233 | 0x38, | ||
4234 | 0x00, | ||
4235 | 0x00, | ||
4236 | 0x00, | ||
4237 | 0x00, | ||
4238 | 0x00, | ||
4239 | 0x00, | ||
4240 | 0x00, | ||
4241 | 0x00, | ||
4242 | 0x00, | ||
4243 | 0x00, | ||
4244 | |||
4245 | 0x00, | ||
4246 | 0x00, | ||
4247 | 0x00, | ||
4248 | 0x00, | ||
4249 | 0x00, | ||
4250 | 0x00, | ||
4251 | 0x00, | ||
4252 | 0x18, | ||
4253 | 0x18, | ||
4254 | 0x00, | ||
4255 | 0x00, | ||
4256 | 0x00, | ||
4257 | 0x00, | ||
4258 | 0x00, | ||
4259 | 0x00, | ||
4260 | 0x00, | ||
4261 | |||
4262 | 0x00, | ||
4263 | 0x00, | ||
4264 | 0x00, | ||
4265 | 0x00, | ||
4266 | 0x00, | ||
4267 | 0x00, | ||
4268 | 0x00, | ||
4269 | 0x00, | ||
4270 | 0x18, | ||
4271 | 0x00, | ||
4272 | 0x00, | ||
4273 | 0x00, | ||
4274 | 0x00, | ||
4275 | 0x00, | ||
4276 | 0x00, | ||
4277 | 0x00, | ||
4278 | |||
4279 | 0x00, | ||
4280 | 0x00, | ||
4281 | 0x07, | ||
4282 | 0x06, | ||
4283 | 0x06, | ||
4284 | 0x0c, | ||
4285 | 0x0c, | ||
4286 | 0x08, | ||
4287 | 0x98, | ||
4288 | 0xd0, | ||
4289 | 0xf0, | ||
4290 | 0x60, | ||
4291 | 0x20, | ||
4292 | 0x00, | ||
4293 | 0x00, | ||
4294 | 0x00, | ||
4295 | |||
4296 | 0x00, | ||
4297 | 0xcc, | ||
4298 | 0x76, | ||
4299 | 0x66, | ||
4300 | 0x66, | ||
4301 | 0x66, | ||
4302 | 0x66, | ||
4303 | 0xf7, | ||
4304 | 0x00, | ||
4305 | 0x00, | ||
4306 | 0x00, | ||
4307 | 0x00, | ||
4308 | 0x00, | ||
4309 | 0x00, | ||
4310 | 0x00, | ||
4311 | 0x00, | ||
4312 | |||
4313 | 0x00, | ||
4314 | 0x70, | ||
4315 | 0x98, | ||
4316 | 0x18, | ||
4317 | 0x30, | ||
4318 | 0x60, | ||
4319 | 0x88, | ||
4320 | 0xf8, | ||
4321 | 0x00, | ||
4322 | 0x00, | ||
4323 | 0x00, | ||
4324 | 0x00, | ||
4325 | 0x00, | ||
4326 | 0x00, | ||
4327 | 0x00, | ||
4328 | 0x00, | ||
4329 | |||
4330 | 0x00, | ||
4331 | 0x00, | ||
4332 | 0x00, | ||
4333 | 0x00, | ||
4334 | 0x00, | ||
4335 | 0x7c, | ||
4336 | 0x64, | ||
4337 | 0x64, | ||
4338 | 0x64, | ||
4339 | 0x64, | ||
4340 | 0x64, | ||
4341 | 0x7c, | ||
4342 | 0x00, | ||
4343 | 0x00, | ||
4344 | 0x00, | ||
4345 | 0x00, | ||
4346 | |||
4347 | 0x00, | ||
4348 | 0x00, | ||
4349 | 0x00, | ||
4350 | 0x00, | ||
4351 | 0x00, | ||
4352 | 0x00, | ||
4353 | 0x00, | ||
4354 | 0x00, | ||
4355 | 0x00, | ||
4356 | 0x00, | ||
4357 | 0x00, | ||
4358 | 0x00, | ||
4359 | 0x00, | ||
4360 | 0x00, | ||
4361 | 0x00, | ||
4362 | 0x00, | ||
4363 | |||
4364 | }; | ||
4365 | |||
4366 | |||
4367 | const struct font_desc font_rl = { | ||
4368 | RL_IDX, | ||
4369 | "RomanLarge", | ||
4370 | 8, | ||
4371 | 16, | ||
4372 | patterns, | ||
4373 | -1 | ||
4374 | }; | ||
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index 9be83bed1959..4fd07d9eca03 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c | |||
@@ -64,10 +64,6 @@ static const struct font_desc *fonts[] = { | |||
64 | #undef NO_FONTS | 64 | #undef NO_FONTS |
65 | &font_mini_4x6, | 65 | &font_mini_4x6, |
66 | #endif | 66 | #endif |
67 | #ifdef CONFIG_FONT_RL | ||
68 | #undef NO_FONTS | ||
69 | &font_rl, | ||
70 | #endif | ||
71 | }; | 67 | }; |
72 | 68 | ||
73 | #define num_fonts (sizeof(fonts)/sizeof(*fonts)) | 69 | #define num_fonts (sizeof(fonts)/sizeof(*fonts)) |
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 04417dc16c2e..2584daec7bbf 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c | |||
@@ -57,6 +57,9 @@ static struct fb_ops ffb_ops = { | |||
57 | .fb_sync = ffb_sync, | 57 | .fb_sync = ffb_sync, |
58 | .fb_mmap = ffb_mmap, | 58 | .fb_mmap = ffb_mmap, |
59 | .fb_ioctl = ffb_ioctl, | 59 | .fb_ioctl = ffb_ioctl, |
60 | #ifdef CONFIG_COMPAT | ||
61 | .fb_compat_ioctl = sbusfb_compat_ioctl, | ||
62 | #endif | ||
60 | }; | 63 | }; |
61 | 64 | ||
62 | /* Register layout and definitions */ | 65 | /* Register layout and definitions */ |
diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 84a7fe435bb8..376d4a171ec7 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c | |||
@@ -51,6 +51,9 @@ static struct fb_ops leo_ops = { | |||
51 | .fb_imageblit = cfb_imageblit, | 51 | .fb_imageblit = cfb_imageblit, |
52 | .fb_mmap = leo_mmap, | 52 | .fb_mmap = leo_mmap, |
53 | .fb_ioctl = leo_ioctl, | 53 | .fb_ioctl = leo_ioctl, |
54 | #ifdef CONFIG_COMPAT | ||
55 | .fb_compat_ioctl = sbusfb_compat_ioctl, | ||
56 | #endif | ||
54 | }; | 57 | }; |
55 | 58 | ||
56 | #define LEO_OFF_LC_SS0_KRN 0x00200000UL | 59 | #define LEO_OFF_LC_SS0_KRN 0x00200000UL |
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index f60b1f432270..3353103e8b0b 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h | |||
@@ -42,7 +42,7 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, | |||
42 | #define nvidia_probe_i2c_connector(p, c, edid) (-1) | 42 | #define nvidia_probe_i2c_connector(p, c, edid) (-1) |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | #ifdef CONFIG_FB_OF | 45 | #ifdef CONFIG_PPC_OF |
46 | int nvidia_probe_of_connector(struct fb_info *info, int conn, | 46 | int nvidia_probe_of_connector(struct fb_info *info, int conn, |
47 | u8 ** out_edid); | 47 | u8 ** out_edid); |
48 | #else | 48 | #else |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 0b40a2a721c1..bee09c6e48f6 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
@@ -1301,7 +1301,7 @@ static int nvidiafb_pan_display(struct fb_var_screeninfo *var, | |||
1301 | struct nvidia_par *par = info->par; | 1301 | struct nvidia_par *par = info->par; |
1302 | u32 total; | 1302 | u32 total; |
1303 | 1303 | ||
1304 | total = info->var.yoffset * info->fix.line_length + info->var.xoffset; | 1304 | total = var->yoffset * info->fix.line_length + var->xoffset; |
1305 | 1305 | ||
1306 | NVSetStartAddress(par, total); | 1306 | NVSetStartAddress(par, total); |
1307 | 1307 | ||
diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 2c856838694e..00d87f5bb7be 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/fb.h> | 26 | #include <linux/fb.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
29 | #include <linux/pci.h> | ||
29 | #include <asm/io.h> | 30 | #include <asm/io.h> |
30 | #include <asm/prom.h> | 31 | #include <asm/prom.h> |
31 | 32 | ||
@@ -325,8 +326,8 @@ static void __init offb_init_nodriver(struct device_node *dp) | |||
325 | int *pp, i; | 326 | int *pp, i; |
326 | unsigned int len; | 327 | unsigned int len; |
327 | int width = 640, height = 480, depth = 8, pitch; | 328 | int width = 640, height = 480, depth = 8, pitch; |
328 | unsigned *up; | 329 | unsigned int rsize, *up; |
329 | unsigned long address; | 330 | unsigned long address = 0; |
330 | 331 | ||
331 | if ((pp = (int *) get_property(dp, "depth", &len)) != NULL | 332 | if ((pp = (int *) get_property(dp, "depth", &len)) != NULL |
332 | && len == sizeof(int)) | 333 | && len == sizeof(int)) |
@@ -344,10 +345,40 @@ static void __init offb_init_nodriver(struct device_node *dp) | |||
344 | pitch = 0x1000; | 345 | pitch = 0x1000; |
345 | } else | 346 | } else |
346 | pitch = width; | 347 | pitch = width; |
347 | if ((up = (unsigned *) get_property(dp, "address", &len)) != NULL | 348 | |
348 | && len == sizeof(unsigned)) | 349 | rsize = (unsigned long)pitch * (unsigned long)height * |
350 | (unsigned long)(depth / 8); | ||
351 | |||
352 | /* Try to match device to a PCI device in order to get a properly | ||
353 | * translated address rather then trying to decode the open firmware | ||
354 | * stuff in various incorrect ways | ||
355 | */ | ||
356 | #ifdef CONFIG_PCI | ||
357 | /* First try to locate the PCI device if any */ | ||
358 | { | ||
359 | struct pci_dev *pdev = NULL; | ||
360 | |||
361 | for_each_pci_dev(pdev) { | ||
362 | if (dp == pci_device_to_OF_node(pdev)) | ||
363 | break; | ||
364 | } | ||
365 | if (pdev) { | ||
366 | for (i = 0; i < 6 && address == 0; i++) { | ||
367 | if ((pci_resource_flags(pdev, i) & | ||
368 | IORESOURCE_MEM) && | ||
369 | (pci_resource_len(pdev, i) >= rsize)) | ||
370 | address = pci_resource_start(pdev, i); | ||
371 | } | ||
372 | pci_dev_put(pdev); | ||
373 | } | ||
374 | } | ||
375 | #endif /* CONFIG_PCI */ | ||
376 | |||
377 | if (address == 0 && | ||
378 | (up = (unsigned *) get_property(dp, "address", &len)) != NULL && | ||
379 | len == sizeof(unsigned)) | ||
349 | address = (u_long) * up; | 380 | address = (u_long) * up; |
350 | else { | 381 | if (address == 0) { |
351 | for (i = 0; i < dp->n_addrs; ++i) | 382 | for (i = 0; i < dp->n_addrs; ++i) |
352 | if (dp->addrs[i].size >= | 383 | if (dp->addrs[i].size >= |
353 | pitch * height * depth / 8) | 384 | pitch * height * depth / 8) |
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 9aaf65fb623a..18bcda23d2cf 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c | |||
@@ -48,6 +48,9 @@ static struct fb_ops p9100_ops = { | |||
48 | .fb_imageblit = cfb_imageblit, | 48 | .fb_imageblit = cfb_imageblit, |
49 | .fb_mmap = p9100_mmap, | 49 | .fb_mmap = p9100_mmap, |
50 | .fb_ioctl = p9100_ioctl, | 50 | .fb_ioctl = p9100_ioctl, |
51 | #ifdef CONFIG_COMPAT | ||
52 | .fb_compat_ioctl = sbusfb_compat_ioctl, | ||
53 | #endif | ||
51 | }; | 54 | }; |
52 | 55 | ||
53 | /* P9100 control registers */ | 56 | /* P9100 control registers */ |
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index 34f72edba820..646c43f921c5 100644 --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * Copyright (C) 2003 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 2003 David S. Miller (davem@redhat.com) |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/compat.h> | ||
6 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
7 | #include <linux/module.h> | 8 | #include <linux/module.h> |
8 | #include <linux/string.h> | 9 | #include <linux/string.h> |
@@ -182,3 +183,109 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, | |||
182 | }; | 183 | }; |
183 | } | 184 | } |
184 | EXPORT_SYMBOL(sbusfb_ioctl_helper); | 185 | EXPORT_SYMBOL(sbusfb_ioctl_helper); |
186 | |||
187 | #ifdef CONFIG_COMPAT | ||
188 | struct fbcmap32 { | ||
189 | int index; /* first element (0 origin) */ | ||
190 | int count; | ||
191 | u32 red; | ||
192 | u32 green; | ||
193 | u32 blue; | ||
194 | }; | ||
195 | |||
196 | #define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32) | ||
197 | #define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32) | ||
198 | |||
199 | static int fbiogetputcmap(struct file *file, struct fb_info *info, | ||
200 | unsigned int cmd, unsigned long arg) | ||
201 | { | ||
202 | struct fbcmap32 __user *argp = (void __user *)arg; | ||
203 | struct fbcmap __user *p = compat_alloc_user_space(sizeof(*p)); | ||
204 | u32 addr; | ||
205 | int ret; | ||
206 | |||
207 | ret = copy_in_user(p, argp, 2 * sizeof(int)); | ||
208 | ret |= get_user(addr, &argp->red); | ||
209 | ret |= put_user(compat_ptr(addr), &p->red); | ||
210 | ret |= get_user(addr, &argp->green); | ||
211 | ret |= put_user(compat_ptr(addr), &p->green); | ||
212 | ret |= get_user(addr, &argp->blue); | ||
213 | ret |= put_user(compat_ptr(addr), &p->blue); | ||
214 | if (ret) | ||
215 | return -EFAULT; | ||
216 | return info->fbops->fb_ioctl(file->f_dentry->d_inode, file, | ||
217 | (cmd == FBIOPUTCMAP32) ? | ||
218 | FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC, | ||
219 | (unsigned long)p, info); | ||
220 | } | ||
221 | |||
222 | struct fbcursor32 { | ||
223 | short set; /* what to set, choose from the list above */ | ||
224 | short enable; /* cursor on/off */ | ||
225 | struct fbcurpos pos; /* cursor position */ | ||
226 | struct fbcurpos hot; /* cursor hot spot */ | ||
227 | struct fbcmap32 cmap; /* color map info */ | ||
228 | struct fbcurpos size; /* cursor bit map size */ | ||
229 | u32 image; /* cursor image bits */ | ||
230 | u32 mask; /* cursor mask bits */ | ||
231 | }; | ||
232 | |||
233 | #define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32) | ||
234 | #define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32) | ||
235 | |||
236 | static int fbiogscursor(struct file *file, struct fb_info *info, | ||
237 | unsigned long arg) | ||
238 | { | ||
239 | struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p)); | ||
240 | struct fbcursor32 __user *argp = (void __user *)arg; | ||
241 | compat_uptr_t addr; | ||
242 | int ret; | ||
243 | |||
244 | ret = copy_in_user(p, argp, | ||
245 | 2 * sizeof (short) + 2 * sizeof(struct fbcurpos)); | ||
246 | ret |= copy_in_user(&p->size, &argp->size, sizeof(struct fbcurpos)); | ||
247 | ret |= copy_in_user(&p->cmap, &argp->cmap, 2 * sizeof(int)); | ||
248 | ret |= get_user(addr, &argp->cmap.red); | ||
249 | ret |= put_user(compat_ptr(addr), &p->cmap.red); | ||
250 | ret |= get_user(addr, &argp->cmap.green); | ||
251 | ret |= put_user(compat_ptr(addr), &p->cmap.green); | ||
252 | ret |= get_user(addr, &argp->cmap.blue); | ||
253 | ret |= put_user(compat_ptr(addr), &p->cmap.blue); | ||
254 | ret |= get_user(addr, &argp->mask); | ||
255 | ret |= put_user(compat_ptr(addr), &p->mask); | ||
256 | ret |= get_user(addr, &argp->image); | ||
257 | ret |= put_user(compat_ptr(addr), &p->image); | ||
258 | if (ret) | ||
259 | return -EFAULT; | ||
260 | return info->fbops->fb_ioctl(file->f_dentry->d_inode, file, | ||
261 | FBIOSCURSOR, (unsigned long)p, info); | ||
262 | } | ||
263 | |||
264 | long sbusfb_compat_ioctl(struct file *file, unsigned int cmd, | ||
265 | unsigned long arg, struct fb_info *info) | ||
266 | { | ||
267 | switch (cmd) { | ||
268 | case FBIOGTYPE: | ||
269 | case FBIOSATTR: | ||
270 | case FBIOGATTR: | ||
271 | case FBIOSVIDEO: | ||
272 | case FBIOGVIDEO: | ||
273 | case FBIOGCURSOR32: /* This is not implemented yet. | ||
274 | Later it should be converted... */ | ||
275 | case FBIOSCURPOS: | ||
276 | case FBIOGCURPOS: | ||
277 | case FBIOGCURMAX: | ||
278 | return info->fbops->fb_ioctl(file->f_dentry->d_inode, | ||
279 | file, cmd, arg, info); | ||
280 | case FBIOPUTCMAP32: | ||
281 | return fbiogetputcmap(file, info, cmd, arg); | ||
282 | case FBIOGETCMAP32: | ||
283 | return fbiogetputcmap(file, info, cmd, arg); | ||
284 | case FBIOSCURSOR32: | ||
285 | return fbiogscursor(file, info, arg); | ||
286 | default: | ||
287 | return -ENOIOCTLCMD; | ||
288 | } | ||
289 | } | ||
290 | EXPORT_SYMBOL(sbusfb_compat_ioctl); | ||
291 | #endif | ||
diff --git a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h index a6aa33ba09d6..b470e52ce9e2 100644 --- a/drivers/video/sbuslib.h +++ b/drivers/video/sbuslib.h | |||
@@ -20,5 +20,7 @@ extern int sbusfb_mmap_helper(struct sbus_mmap_map *map, | |||
20 | int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, | 20 | int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, |
21 | struct fb_info *info, | 21 | struct fb_info *info, |
22 | int type, int fb_depth, unsigned long fb_size); | 22 | int type, int fb_depth, unsigned long fb_size); |
23 | long sbusfb_compat_ioctl(struct file *file, unsigned int cmd, | ||
24 | unsigned long arg, struct fb_info *info); | ||
23 | 25 | ||
24 | #endif /* _SBUSLIB_H */ | 26 | #endif /* _SBUSLIB_H */ |
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 59fff29bc02e..fe4f63f3849d 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c | |||
@@ -52,6 +52,9 @@ static struct fb_ops tcx_ops = { | |||
52 | .fb_imageblit = cfb_imageblit, | 52 | .fb_imageblit = cfb_imageblit, |
53 | .fb_mmap = tcx_mmap, | 53 | .fb_mmap = tcx_mmap, |
54 | .fb_ioctl = tcx_ioctl, | 54 | .fb_ioctl = tcx_ioctl, |
55 | #ifdef CONFIG_COMPAT | ||
56 | .fb_compat_ioctl = sbusfb_compat_ioctl, | ||
57 | #endif | ||
55 | }; | 58 | }; |
56 | 59 | ||
57 | /* THC definitions */ | 60 | /* THC definitions */ |
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 2c3aa2fcfd91..3e58ddc2bc38 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c | |||
@@ -413,6 +413,7 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
413 | * region already (FIXME) */ | 413 | * region already (FIXME) */ |
414 | request_region(0x3c0, 32, "vesafb"); | 414 | request_region(0x3c0, 32, "vesafb"); |
415 | 415 | ||
416 | #ifdef CONFIG_MTRR | ||
416 | if (mtrr) { | 417 | if (mtrr) { |
417 | unsigned int temp_size = size_total; | 418 | unsigned int temp_size = size_total; |
418 | unsigned int type = 0; | 419 | unsigned int type = 0; |
@@ -450,6 +451,7 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
450 | } while (temp_size >= PAGE_SIZE && rc == -EINVAL); | 451 | } while (temp_size >= PAGE_SIZE && rc == -EINVAL); |
451 | } | 452 | } |
452 | } | 453 | } |
454 | #endif | ||
453 | 455 | ||
454 | info->fbops = &vesafb_ops; | 456 | info->fbops = &vesafb_ops; |
455 | info->var = vesafb_defined; | 457 | info->var = vesafb_defined; |
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index daa46051f55d..f6e24ee85f07 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c | |||
@@ -514,7 +514,7 @@ int __init w100fb_probe(struct platform_device *pdev) | |||
514 | if (remapped_fbuf == NULL) | 514 | if (remapped_fbuf == NULL) |
515 | goto out; | 515 | goto out; |
516 | 516 | ||
517 | info=framebuffer_alloc(sizeof(struct w100fb_par), dev); | 517 | info=framebuffer_alloc(sizeof(struct w100fb_par), &pdev->dev); |
518 | if (!info) { | 518 | if (!info) { |
519 | err = -ENOMEM; | 519 | err = -ENOMEM; |
520 | goto out; | 520 | goto out; |