diff --git a/[refs] b/[refs] index 8293865b28ae..ff1669e25424 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c36ad397a30fcf9369d82584324cc24189eb6b1c +refs/heads/master: 8b2af8f0ca807eb13b59dc5961d2e99fc2b1bd87 diff --git a/trunk/Documentation/Changes b/trunk/Documentation/Changes index afebdbcd553a..b37600754762 100644 --- a/trunk/Documentation/Changes +++ b/trunk/Documentation/Changes @@ -44,9 +44,9 @@ running, the suggested command should tell you. Again, keep in mind that this list assumes you are already functionally running a Linux 2.4 kernel. Also, not all tools are -necessary on all systems; obviously, if you don't have any ISDN -hardware, for example, you probably needn't concern yourself with -isdn4k-utils. +necessary on all systems; obviously, if you don't have any PCMCIA (PC +Card) hardware, for example, you probably needn't concern yourself +with pcmcia-cs. o Gnu C 2.95.3 # gcc --version o Gnu make 3.79.1 # make --version @@ -57,7 +57,6 @@ o e2fsprogs 1.29 # tune2fs o jfsutils 1.1.3 # fsck.jfs -V o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs o xfsprogs 2.6.0 # xfs_db -V -o pcmciautils 001 o pcmcia-cs 3.1.21 # cardmgr -V o quota-tools 3.09 # quota -V o PPP 2.4.0 # pppd --version @@ -187,20 +186,13 @@ architecture independent and any version from 2.0.0 onward should work correctly with this version of the XFS kernel code (2.6.0 or later is recommended, due to some significant improvements). -PCMCIAutils ------------ - -PCMCIAutils replaces pcmcia-cs (see below). It properly sets up -PCMCIA sockets at system startup and loads the appropriate modules -for 16-bit PCMCIA devices if the kernel is modularized and the hotplug -subsystem is used. Pcmcia-cs --------- PCMCIA (PC Card) support is now partially implemented in the main -kernel source. The "pcmciautils" package (see above) replaces pcmcia-cs -for newest kernels. +kernel source. Pay attention when you recompile your kernel ;-). +Also, be sure to upgrade to the latest pcmcia-cs release. Quota-tools ----------- @@ -357,13 +349,9 @@ Xfsprogs -------- o -Pcmciautils ------------ -o - Pcmcia-cs --------- -o +o Quota-tools ---------- diff --git a/trunk/Documentation/DocBook/libata.tmpl b/trunk/Documentation/DocBook/libata.tmpl index 6df1dfd18b65..375ae760dc1e 100644 --- a/trunk/Documentation/DocBook/libata.tmpl +++ b/trunk/Documentation/DocBook/libata.tmpl @@ -84,6 +84,14 @@ void (*port_disable) (struct ata_port *); Called from ata_bus_probe() and ata_bus_reset() error paths, as well as when unregistering from the SCSI module (rmmod, hot unplug). + This function should do whatever needs to be done to take the + port out of use. In most cases, ata_port_disable() can be used + as this hook. + + + Called from ata_bus_probe() on a failed probe. + Called from ata_bus_reset() on a failed bus reset. + Called from ata_scsi_release(). @@ -98,6 +106,13 @@ void (*dev_config) (struct ata_port *, struct ata_device *); found. Typically used to apply device-specific fixups prior to issue of SET FEATURES - XFER MODE, and prior to operation. + + Called by ata_device_add() after ata_dev_identify() determines + a device is present. + + + This entry may be specified as NULL in ata_port_operations. + @@ -135,6 +150,8 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); registers / DMA buffers. ->tf_read() is called to read the hardware registers / DMA buffers, to obtain the current set of taskfile register values. + Most drivers for taskfile-based hardware (PIO or MMIO) use + ata_tf_load() and ata_tf_read() for these hooks. @@ -147,6 +164,8 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); causes an ATA command, previously loaded with ->tf_load(), to be initiated in hardware. + Most drivers for taskfile-based hardware use ata_exec_command() + for this hook. @@ -161,6 +180,10 @@ Allow low-level driver to filter ATA PACKET commands, returning a status indicating whether or not it is OK to use DMA for the supplied PACKET command. + + This hook may be specified as NULL, in which case libata will + assume that atapi dma can be supported. + @@ -175,6 +198,14 @@ u8 (*check_err)(struct ata_port *ap); Reads the Status/AltStatus/Error ATA shadow register from hardware. On some hardware, reading the Status register has the side effect of clearing the interrupt condition. + Most drivers for taskfile-based hardware use + ata_check_status() for this hook. + + + Note that because this is called from ata_device_add(), at + least a dummy function that clears device interrupts must be + provided for all drivers, even if the controller doesn't + actually have a taskfile status register. @@ -188,7 +219,13 @@ void (*dev_select)(struct ata_port *ap, unsigned int device); Issues the low-level hardware command(s) that causes one of N hardware devices to be considered 'selected' (active and available for use) on the ATA bus. This generally has no -meaning on FIS-based devices. + meaning on FIS-based devices. + + + Most drivers for taskfile-based hardware use + ata_std_dev_select() for this hook. Controllers which do not + support second drives on a port (such as SATA contollers) will + use ata_noop_dev_select(). @@ -204,6 +241,8 @@ void (*phy_reset) (struct ata_port *ap); for device presence (PATA and SATA), typically a soft reset (SRST) will be performed. Drivers typically use the helper functions ata_bus_reset() or sata_phy_reset() for this hook. + Many SATA drivers use sata_phy_reset() or call it from within + their own phy_reset() functions. @@ -227,6 +266,25 @@ PCI IDE DMA Status register. These hooks are typically either no-ops, or simply not implemented, in FIS-based drivers. + +Most legacy IDE drivers use ata_bmdma_setup() for the bmdma_setup() +hook. ata_bmdma_setup() will write the pointer to the PRD table to +the IDE PRD Table Address register, enable DMA in the DMA Command +register, and call exec_command() to begin the transfer. + + +Most legacy IDE drivers use ata_bmdma_start() for the bmdma_start() +hook. ata_bmdma_start() will write the ATA_DMA_START flag to the DMA +Command register. + + +Many legacy IDE drivers use ata_bmdma_stop() for the bmdma_stop() +hook. ata_bmdma_stop() clears the ATA_DMA_START flag in the DMA +command register. + + +Many legacy IDE drivers use ata_bmdma_status() as the bmdma_status() hook. + @@ -250,6 +308,10 @@ int (*qc_issue) (struct ata_queued_cmd *qc); helper function ata_qc_issue_prot() for taskfile protocol-based dispatch. More advanced drivers implement their own ->qc_issue. + + ata_qc_issue_prot() calls ->tf_load(), ->bmdma_setup(), and + ->bmdma_start() as necessary to initiate a transfer. + @@ -279,6 +341,21 @@ void (*irq_clear) (struct ata_port *); before the interrupt handler is registered, to be sure hardware is quiet. + + The second argument, dev_instance, should be cast to a pointer + to struct ata_host_set. + + + Most legacy IDE drivers use ata_interrupt() for the + irq_handler hook, which scans all ports in the host_set, + determines which queued command was active (if any), and calls + ata_host_intr(ap,qc). + + + Most legacy IDE drivers use ata_bmdma_irq_clear() for the + irq_clear() hook, which simply clears the interrupt and error + flags in the DMA status register. + @@ -292,6 +369,7 @@ void (*scr_write) (struct ata_port *ap, unsigned int sc_reg, Read and write standard SATA phy registers. Currently only used if ->phy_reset hook called the sata_phy_reset() helper function. + sc_reg is one of SCR_STATUS, SCR_CONTROL, SCR_ERROR, or SCR_ACTIVE. @@ -307,17 +385,29 @@ void (*host_stop) (struct ata_host_set *host_set); ->port_start() is called just after the data structures for each port are initialized. Typically this is used to alloc per-port DMA buffers / tables / rings, enable DMA engines, and similar - tasks. + tasks. Some drivers also use this entry point as a chance to + allocate driver-private memory for ap->private_data. + + + Many drivers use ata_port_start() as this hook or call + it from their own port_start() hooks. ata_port_start() + allocates space for a legacy IDE PRD table and returns. ->port_stop() is called after ->host_stop(). It's sole function is to release DMA/memory resources, now that they are no longer - actively being used. + actively being used. Many drivers also free driver-private + data from port at this time. + + + Many drivers use ata_port_stop() as this hook, which frees the + PRD table. ->host_stop() is called after all ->port_stop() calls have completed. The hook must finalize hardware shutdown, release DMA and other resources, etc. + This hook may be specified as NULL, in which case it is not called. diff --git a/trunk/Documentation/pcmcia/devicetable.txt b/trunk/Documentation/pcmcia/devicetable.txt deleted file mode 100644 index 045511acafc9..000000000000 --- a/trunk/Documentation/pcmcia/devicetable.txt +++ /dev/null @@ -1,64 +0,0 @@ -Matching of PCMCIA devices to drivers is done using one or more of the -following criteria: - -- manufactor ID -- card ID -- product ID strings _and_ hashes of these strings -- function ID -- device function (actual and pseudo) - -You should use the helpers in include/pcmcia/device_id.h for generating the -struct pcmcia_device_id[] entries which match devices to drivers. - -If you want to match product ID strings, you also need to pass the crc32 -hashes of the string to the macro, e.g. if you want to match the product ID -string 1, you need to use - -PCMCIA_DEVICE_PROD_ID1("some_string", 0x(hash_of_some_string)), - -If the hash is incorrect, the kernel will inform you about this in "dmesg" -upon module initialization, and tell you of the correct hash. - -You can determine the hash of the product ID strings by running -"pcmcia-modalias %n.%m" [%n being replaced with the socket number and %m being -replaced with the device function] from pcmciautils. It generates a string -in the following form: -pcmcia:m0149cC1ABf06pfn00fn00pa725B842DpbF1EFEE84pc0877B627pd00000000 - -The hex value after "pa" is the hash of product ID string 1, after "pb" for -string 2 and so on. - -Alternatively, you can use this small tool to determine the crc32 hash. -simply pass the string you want to evaluate as argument to this program, -e.g. -$ ./crc32hash "Dual Speed" - -------------------------------------------------------------------------- -/* crc32hash.c - derived from linux/lib/crc32.c, GNU GPL v2 */ -#include -#include -#include -#include - -unsigned int crc32(unsigned char const *p, unsigned int len) -{ - int i; - unsigned int crc = 0; - while (len--) { - crc ^= *p++; - for (i = 0; i < 8; i++) - crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); - } - return crc; -} - -int main(int argc, char **argv) { - unsigned int result; - if (argc != 2) { - printf("no string passed as argument\n"); - return -1; - } - result = crc32(argv[1], strlen(argv[1])); - printf("0x%x\n", result); - return 0; -} diff --git a/trunk/Documentation/pcmcia/driver-changes.txt b/trunk/Documentation/pcmcia/driver-changes.txt deleted file mode 100644 index 9c315ab48a02..000000000000 --- a/trunk/Documentation/pcmcia/driver-changes.txt +++ /dev/null @@ -1,51 +0,0 @@ -This file details changes in 2.6 which affect PCMCIA card driver authors: - -* in-kernel device<->driver matching - PCMCIA devices and their correct drivers can now be matched in - kernelspace. See 'devicetable.txt' for details. - -* Device model integration (as of 2.6.11) - A struct pcmcia_device is registered with the device model core, - and can be used (e.g. for SET_NETDEV_DEV) by using - handle_to_dev(client_handle_t * handle). - -* Convert internal I/O port addresses to unsigned long (as of 2.6.11) - ioaddr_t should be replaced by kio_addr_t in PCMCIA card drivers. - -* irq_mask and irq_list parameters (as of 2.6.11) - The irq_mask and irq_list parameters should no longer be used in - PCMCIA card drivers. Instead, it is the job of the PCMCIA core to - determine which IRQ should be used. Therefore, link->irq.IRQInfo2 - is ignored. - -* client->PendingEvents is gone (as of 2.6.11) - client->PendingEvents is no longer available. - -* client->Attributes are gone (as of 2.6.11) - client->Attributes is unused, therefore it is removed from all - PCMCIA card drivers - -* core functions no longer available (as of 2.6.11) - The following functions have been removed from the kernel source - because they are unused by all in-kernel drivers, and no external - driver was reported to rely on them: - pcmcia_get_first_region() - pcmcia_get_next_region() - pcmcia_modify_window() - pcmcia_set_event_mask() - pcmcia_get_first_window() - pcmcia_get_next_window() - -* device list iteration upon module removal (as of 2.6.10) - It is no longer necessary to iterate on the driver's internal - client list and call the ->detach() function upon module removal. - -* Resource management. (as of 2.6.8) - Although the PCMCIA subsystem will allocate resources for cards, - it no longer marks these resources busy. This means that driver - authors are now responsible for claiming your resources as per - other drivers in Linux. You should use request_region() to mark - your IO regions in-use, and request_mem_region() to mark your - memory regions in-use. The name argument should be a pointer to - your driver name. Eg, for pcnet_cs, name should point to the - string "pcnet_cs". diff --git a/trunk/arch/sparc64/kernel/auxio.c b/trunk/arch/sparc64/kernel/auxio.c index 8852c20c8d99..a0716ccc2f4a 100644 --- a/trunk/arch/sparc64/kernel/auxio.c +++ b/trunk/arch/sparc64/kernel/auxio.c @@ -16,7 +16,7 @@ #include #include -/* This cannot be static, as it is referenced in irq.c */ +/* This cannot be static, as it is referenced in entry.S */ void __iomem *auxio_register = NULL; enum auxio_type { diff --git a/trunk/arch/sparc64/kernel/entry.S b/trunk/arch/sparc64/kernel/entry.S index eee516a71c14..a47f2d0b1a29 100644 --- a/trunk/arch/sparc64/kernel/entry.S +++ b/trunk/arch/sparc64/kernel/entry.S @@ -271,9 +271,8 @@ cplus_fptrap_insn_1: fmuld %f0, %f2, %f26 faddd %f0, %f2, %f28 fmuld %f0, %f2, %f30 - membar #Sync b,pt %xcc, fpdis_exit - nop + membar #Sync 2: andcc %g5, FPRS_DU, %g0 bne,pt %icc, 3f fzero %f32 @@ -302,9 +301,8 @@ cplus_fptrap_insn_2: fmuld %f32, %f34, %f58 faddd %f32, %f34, %f60 fmuld %f32, %f34, %f62 - membar #Sync ba,pt %xcc, fpdis_exit - nop + membar #Sync 3: mov SECONDARY_CONTEXT, %g3 add %g6, TI_FPREGS, %g1 ldxa [%g3] ASI_DMMU, %g5 @@ -701,6 +699,116 @@ utrap_ill: ba,pt %xcc, rtrap clr %l6 +#ifdef CONFIG_BLK_DEV_FD + .globl floppy_hardint +floppy_hardint: + wr %g0, (1 << 11), %clear_softint + sethi %hi(doing_pdma), %g1 + ld [%g1 + %lo(doing_pdma)], %g2 + brz,pn %g2, floppy_dosoftint + sethi %hi(fdc_status), %g3 + ldx [%g3 + %lo(fdc_status)], %g3 + sethi %hi(pdma_vaddr), %g5 + ldx [%g5 + %lo(pdma_vaddr)], %g4 + sethi %hi(pdma_size), %g5 + ldx [%g5 + %lo(pdma_size)], %g5 + +next_byte: + lduba [%g3] ASI_PHYS_BYPASS_EC_E, %g7 + andcc %g7, 0x80, %g0 + be,pn %icc, floppy_fifo_emptied + andcc %g7, 0x20, %g0 + be,pn %icc, floppy_overrun + andcc %g7, 0x40, %g0 + be,pn %icc, floppy_write + sub %g5, 1, %g5 + + inc %g3 + lduba [%g3] ASI_PHYS_BYPASS_EC_E, %g7 + dec %g3 + orcc %g0, %g5, %g0 + stb %g7, [%g4] + bne,pn %xcc, next_byte + add %g4, 1, %g4 + + b,pt %xcc, floppy_tdone + nop + +floppy_write: + ldub [%g4], %g7 + orcc %g0, %g5, %g0 + inc %g3 + stba %g7, [%g3] ASI_PHYS_BYPASS_EC_E + dec %g3 + bne,pn %xcc, next_byte + add %g4, 1, %g4 + +floppy_tdone: + sethi %hi(pdma_vaddr), %g1 + stx %g4, [%g1 + %lo(pdma_vaddr)] + sethi %hi(pdma_size), %g1 + stx %g5, [%g1 + %lo(pdma_size)] + sethi %hi(auxio_register), %g1 + ldx [%g1 + %lo(auxio_register)], %g7 + lduba [%g7] ASI_PHYS_BYPASS_EC_E, %g5 + or %g5, AUXIO_AUX1_FTCNT, %g5 +/* andn %g5, AUXIO_AUX1_MASK, %g5 */ + stba %g5, [%g7] ASI_PHYS_BYPASS_EC_E + andn %g5, AUXIO_AUX1_FTCNT, %g5 +/* andn %g5, AUXIO_AUX1_MASK, %g5 */ + + nop; nop; nop; nop; nop; nop; + nop; nop; nop; nop; nop; nop; + + stba %g5, [%g7] ASI_PHYS_BYPASS_EC_E + sethi %hi(doing_pdma), %g1 + b,pt %xcc, floppy_dosoftint + st %g0, [%g1 + %lo(doing_pdma)] + +floppy_fifo_emptied: + sethi %hi(pdma_vaddr), %g1 + stx %g4, [%g1 + %lo(pdma_vaddr)] + sethi %hi(pdma_size), %g1 + stx %g5, [%g1 + %lo(pdma_size)] + sethi %hi(irq_action), %g1 + or %g1, %lo(irq_action), %g1 + ldx [%g1 + (11 << 3)], %g3 ! irqaction[floppy_irq] + ldx [%g3 + 0x08], %g4 ! action->flags>>48==ino + sethi %hi(ivector_table), %g3 + srlx %g4, 48, %g4 + or %g3, %lo(ivector_table), %g3 + sllx %g4, 5, %g4 + ldx [%g3 + %g4], %g4 ! &ivector_table[ino] + ldx [%g4 + 0x10], %g4 ! bucket->iclr + stwa %g0, [%g4] ASI_PHYS_BYPASS_EC_E ! ICLR_IDLE + membar #Sync ! probably not needed... + retry + +floppy_overrun: + sethi %hi(pdma_vaddr), %g1 + stx %g4, [%g1 + %lo(pdma_vaddr)] + sethi %hi(pdma_size), %g1 + stx %g5, [%g1 + %lo(pdma_size)] + sethi %hi(doing_pdma), %g1 + st %g0, [%g1 + %lo(doing_pdma)] + +floppy_dosoftint: + rdpr %pil, %g2 + wrpr %g0, 15, %pil + sethi %hi(109f), %g7 + b,pt %xcc, etrap_irq +109: or %g7, %lo(109b), %g7 + + mov 11, %o0 + mov 0, %o1 + call sparc_floppy_irq + add %sp, PTREGS_OFF, %o2 + + b,pt %xcc, rtrap_irq + nop + +#endif /* CONFIG_BLK_DEV_FD */ + /* XXX Here is stuff we still need to write... -DaveM XXX */ .globl netbsd_syscall netbsd_syscall: diff --git a/trunk/arch/sparc64/kernel/irq.c b/trunk/arch/sparc64/kernel/irq.c index 424712577307..4dcb8af94090 100644 --- a/trunk/arch/sparc64/kernel/irq.c +++ b/trunk/arch/sparc64/kernel/irq.c @@ -37,7 +37,6 @@ #include #include #include -#include #ifdef CONFIG_SMP static void distribute_irqs(void); @@ -835,65 +834,137 @@ void handler_irq(int irq, struct pt_regs *regs) } #ifdef CONFIG_BLK_DEV_FD -extern irqreturn_t floppy_interrupt(int, void *, struct pt_regs *);; +extern void floppy_interrupt(int irq, void *dev_cookie, struct pt_regs *regs); -/* XXX No easy way to include asm/floppy.h XXX */ -extern unsigned char *pdma_vaddr; -extern unsigned long pdma_size; -extern volatile int doing_pdma; -extern unsigned long fdc_status; +void sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs) +{ + struct irqaction *action = *(irq + irq_action); + struct ino_bucket *bucket; + int cpu = smp_processor_id(); + + irq_enter(); + kstat_this_cpu.irqs[irq]++; + + *(irq_work(cpu, irq)) = 0; + bucket = get_ino_in_irqaction(action) + ivector_table; + + bucket->flags |= IBF_INPROGRESS; + + floppy_interrupt(irq, dev_cookie, regs); + upa_writel(ICLR_IDLE, bucket->iclr); + + bucket->flags &= ~IBF_INPROGRESS; + + irq_exit(); +} +#endif + +/* The following assumes that the branch lies before the place we + * are branching to. This is the case for a trap vector... + * You have been warned. + */ +#define SPARC_BRANCH(dest_addr, inst_addr) \ + (0x10800000 | ((((dest_addr)-(inst_addr))>>2)&0x3fffff)) + +#define SPARC_NOP (0x01000000) -irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs) +static void install_fast_irq(unsigned int cpu_irq, + irqreturn_t (*handler)(int, void *, struct pt_regs *)) { - if (likely(doing_pdma)) { - void __iomem *stat = (void __iomem *) fdc_status; - unsigned char *vaddr = pdma_vaddr; - unsigned long size = pdma_size; - u8 val; - - while (size) { - val = readb(stat); - if (unlikely(!(val & 0x80))) { - pdma_vaddr = vaddr; - pdma_size = size; - return IRQ_HANDLED; - } - if (unlikely(!(val & 0x20))) { - pdma_vaddr = vaddr; - pdma_size = size; - doing_pdma = 0; - goto main_interrupt; - } - if (val & 0x40) { - /* read */ - *vaddr++ = readb(stat + 1); - } else { - unsigned char data = *vaddr++; + extern unsigned long sparc64_ttable_tl0; + unsigned long ttent = (unsigned long) &sparc64_ttable_tl0; + unsigned int *insns; + + ttent += 0x820; + ttent += (cpu_irq - 1) << 5; + insns = (unsigned int *) ttent; + insns[0] = SPARC_BRANCH(((unsigned long) handler), + ((unsigned long)&insns[0])); + insns[1] = SPARC_NOP; + __asm__ __volatile__("membar #StoreStore; flush %0" : : "r" (ttent)); +} - /* write */ - writeb(data, stat + 1); - } - size--; - } +int request_fast_irq(unsigned int irq, + irqreturn_t (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, const char *name, void *dev_id) +{ + struct irqaction *action; + struct ino_bucket *bucket = __bucket(irq); + unsigned long flags; + + /* No pil0 dummy buckets allowed here. */ + if (bucket < &ivector_table[0] || + bucket >= &ivector_table[NUM_IVECS]) { + unsigned int *caller; + + __asm__ __volatile__("mov %%i7, %0" : "=r" (caller)); + printk(KERN_CRIT "request_fast_irq: Old style IRQ registry attempt " + "from %p, irq %08x.\n", caller, irq); + return -EINVAL; + } + + if (!handler) + return -EINVAL; - pdma_vaddr = vaddr; - pdma_size = size; + if ((bucket->pil == 0) || (bucket->pil == 14)) { + printk("request_fast_irq: Trying to register shared IRQ 0 or 14.\n"); + return -EBUSY; + } - /* Send Terminal Count pulse to floppy controller. */ - val = readb(auxio_register); - val |= AUXIO_AUX1_FTCNT; - writeb(val, auxio_register); - val &= AUXIO_AUX1_FTCNT; - writeb(val, auxio_register); + spin_lock_irqsave(&irq_action_lock, flags); - doing_pdma = 0; + action = *(bucket->pil + irq_action); + if (action) { + if (action->flags & SA_SHIRQ) + panic("Trying to register fast irq when already shared.\n"); + if (irqflags & SA_SHIRQ) + panic("Trying to register fast irq as shared.\n"); + printk("request_fast_irq: Trying to register yet already owned.\n"); + spin_unlock_irqrestore(&irq_action_lock, flags); + return -EBUSY; } -main_interrupt: - return floppy_interrupt(irq, dev_cookie, regs); -} -EXPORT_SYMBOL(sparc_floppy_irq); + /* + * We do not check for SA_SAMPLE_RANDOM in this path. Neither do we + * support smp intr affinity in this path. + */ + if (irqflags & SA_STATIC_ALLOC) { + if (static_irq_count < MAX_STATIC_ALLOC) + action = &static_irqaction[static_irq_count++]; + else + printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed " + "using kmalloc\n", bucket->pil, name); + } + if (action == NULL) + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), + GFP_ATOMIC); + if (!action) { + spin_unlock_irqrestore(&irq_action_lock, flags); + return -ENOMEM; + } + install_fast_irq(bucket->pil, handler); + + bucket->irq_info = action; + bucket->flags |= IBF_ACTIVE; + + action->handler = handler; + action->flags = irqflags; + action->dev_id = NULL; + action->name = name; + action->next = NULL; + put_ino_in_irqaction(action, irq); + put_smpaff_in_irqaction(action, CPU_MASK_NONE); + + *(bucket->pil + irq_action) = action; + enable_irq(irq); + + spin_unlock_irqrestore(&irq_action_lock, flags); + +#ifdef CONFIG_SMP + distribute_irqs(); #endif + return 0; +} /* We really don't need these at all on the Sparc. We only have * stubs here because they are exported to modules. diff --git a/trunk/arch/sparc64/kernel/semaphore.c b/trunk/arch/sparc64/kernel/semaphore.c index a809e63f03ef..63496c43fe17 100644 --- a/trunk/arch/sparc64/kernel/semaphore.c +++ b/trunk/arch/sparc64/kernel/semaphore.c @@ -32,9 +32,8 @@ static __inline__ int __sem_update_count(struct semaphore *sem, int incr) " add %1, %4, %1\n" " cas [%3], %0, %1\n" " cmp %0, %1\n" -" membar #StoreLoad | #StoreStore\n" " bne,pn %%icc, 1b\n" -" nop\n" +" membar #StoreLoad | #StoreStore\n" : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) : "r" (&sem->count), "r" (incr), "m" (sem->count) : "cc"); @@ -72,9 +71,8 @@ void up(struct semaphore *sem) " cmp %%g1, %%g7\n" " bne,pn %%icc, 1b\n" " addcc %%g7, 1, %%g0\n" -" membar #StoreLoad | #StoreStore\n" " ble,pn %%icc, 3f\n" -" nop\n" +" membar #StoreLoad | #StoreStore\n" "2:\n" " .subsection 2\n" "3: mov %0, %%g1\n" @@ -130,9 +128,8 @@ void __sched down(struct semaphore *sem) " cmp %%g1, %%g7\n" " bne,pn %%icc, 1b\n" " cmp %%g7, 1\n" -" membar #StoreLoad | #StoreStore\n" " bl,pn %%icc, 3f\n" -" nop\n" +" membar #StoreLoad | #StoreStore\n" "2:\n" " .subsection 2\n" "3: mov %0, %%g1\n" @@ -236,9 +233,8 @@ int __sched down_interruptible(struct semaphore *sem) " cmp %%g1, %%g7\n" " bne,pn %%icc, 1b\n" " cmp %%g7, 1\n" -" membar #StoreLoad | #StoreStore\n" " bl,pn %%icc, 3f\n" -" nop\n" +" membar #StoreLoad | #StoreStore\n" "2:\n" " .subsection 2\n" "3: mov %2, %%g1\n" diff --git a/trunk/arch/sparc64/kernel/sparc64_ksyms.c b/trunk/arch/sparc64/kernel/sparc64_ksyms.c index 56cd96f4a5cd..e78cc53594fa 100644 --- a/trunk/arch/sparc64/kernel/sparc64_ksyms.c +++ b/trunk/arch/sparc64/kernel/sparc64_ksyms.c @@ -227,6 +227,7 @@ EXPORT_SYMBOL(__flush_dcache_range); EXPORT_SYMBOL(mostek_lock); EXPORT_SYMBOL(mstk48t02_regs); +EXPORT_SYMBOL(request_fast_irq); #ifdef CONFIG_SUN_AUXIO EXPORT_SYMBOL(auxio_set_led); EXPORT_SYMBOL(auxio_set_lte); diff --git a/trunk/arch/sparc64/kernel/trampoline.S b/trunk/arch/sparc64/kernel/trampoline.S index 3a145fc39cf2..2c8f9344b4ee 100644 --- a/trunk/arch/sparc64/kernel/trampoline.S +++ b/trunk/arch/sparc64/kernel/trampoline.S @@ -98,9 +98,8 @@ startup_continue: sethi %hi(prom_entry_lock), %g2 1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 - membar #StoreLoad | #StoreStore brnz,pn %g1, 1b - nop + membar #StoreLoad | #StoreStore sethi %hi(p1275buf), %g2 or %g2, %lo(p1275buf), %g2 diff --git a/trunk/arch/sparc64/lib/U1memcpy.S b/trunk/arch/sparc64/lib/U1memcpy.S index bafd2fc07acb..da9b520c7189 100644 --- a/trunk/arch/sparc64/lib/U1memcpy.S +++ b/trunk/arch/sparc64/lib/U1memcpy.S @@ -87,17 +87,14 @@ #define LOOP_CHUNK3(src, dest, len, branch_dest) \ MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest) -#define DO_SYNC membar #Sync; #define STORE_SYNC(dest, fsrc) \ EX_ST(STORE_BLK(%fsrc, %dest)); \ - add %dest, 0x40, %dest; \ - DO_SYNC + add %dest, 0x40, %dest; #define STORE_JUMP(dest, fsrc, target) \ EX_ST(STORE_BLK(%fsrc, %dest)); \ add %dest, 0x40, %dest; \ - ba,pt %xcc, target; \ - nop; + ba,pt %xcc, target; #define FINISH_VISCHUNK(dest, f0, f1, left) \ subcc %left, 8, %left;\ @@ -242,17 +239,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ ba,pt %xcc, 1b+4 faligndata %f0, %f2, %f48 1: FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) - STORE_JUMP(o0, f48, 40f) + STORE_JUMP(o0, f48, 40f) membar #Sync 2: FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) - STORE_JUMP(o0, f48, 48f) + STORE_JUMP(o0, f48, 48f) membar #Sync 3: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) - STORE_JUMP(o0, f48, 56f) + STORE_JUMP(o0, f48, 56f) membar #Sync 1: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) @@ -263,17 +260,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ ba,pt %xcc, 1b+4 faligndata %f2, %f4, %f48 1: FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) - STORE_JUMP(o0, f48, 41f) + STORE_JUMP(o0, f48, 41f) membar #Sync 2: FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) - STORE_JUMP(o0, f48, 49f) + STORE_JUMP(o0, f48, 49f) membar #Sync 3: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) - STORE_JUMP(o0, f48, 57f) + STORE_JUMP(o0, f48, 57f) membar #Sync 1: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) @@ -284,17 +281,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ ba,pt %xcc, 1b+4 faligndata %f4, %f6, %f48 1: FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) - STORE_JUMP(o0, f48, 42f) + STORE_JUMP(o0, f48, 42f) membar #Sync 2: FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) - STORE_JUMP(o0, f48, 50f) + STORE_JUMP(o0, f48, 50f) membar #Sync 3: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) - STORE_JUMP(o0, f48, 58f) + STORE_JUMP(o0, f48, 58f) membar #Sync 1: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) @@ -305,17 +302,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ ba,pt %xcc, 1b+4 faligndata %f6, %f8, %f48 1: FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) - STORE_JUMP(o0, f48, 43f) + STORE_JUMP(o0, f48, 43f) membar #Sync 2: FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) - STORE_JUMP(o0, f48, 51f) + STORE_JUMP(o0, f48, 51f) membar #Sync 3: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) - STORE_JUMP(o0, f48, 59f) + STORE_JUMP(o0, f48, 59f) membar #Sync 1: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) @@ -326,17 +323,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ ba,pt %xcc, 1b+4 faligndata %f8, %f10, %f48 1: FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) - STORE_JUMP(o0, f48, 44f) + STORE_JUMP(o0, f48, 44f) membar #Sync 2: FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) - STORE_JUMP(o0, f48, 52f) + STORE_JUMP(o0, f48, 52f) membar #Sync 3: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) - STORE_JUMP(o0, f48, 60f) + STORE_JUMP(o0, f48, 60f) membar #Sync 1: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) @@ -347,17 +344,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ ba,pt %xcc, 1b+4 faligndata %f10, %f12, %f48 1: FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) - STORE_JUMP(o0, f48, 45f) + STORE_JUMP(o0, f48, 45f) membar #Sync 2: FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) - STORE_JUMP(o0, f48, 53f) + STORE_JUMP(o0, f48, 53f) membar #Sync 3: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) - STORE_JUMP(o0, f48, 61f) + STORE_JUMP(o0, f48, 61f) membar #Sync 1: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) @@ -368,17 +365,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ ba,pt %xcc, 1b+4 faligndata %f12, %f14, %f48 1: FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) - STORE_JUMP(o0, f48, 46f) + STORE_JUMP(o0, f48, 46f) membar #Sync 2: FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) - STORE_JUMP(o0, f48, 54f) + STORE_JUMP(o0, f48, 54f) membar #Sync 3: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) - STORE_JUMP(o0, f48, 62f) + STORE_JUMP(o0, f48, 62f) membar #Sync 1: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f) @@ -389,17 +386,17 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ ba,pt %xcc, 1b+4 faligndata %f14, %f16, %f48 1: FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) - STORE_JUMP(o0, f48, 47f) + STORE_JUMP(o0, f48, 47f) membar #Sync 2: FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) - STORE_JUMP(o0, f48, 55f) + STORE_JUMP(o0, f48, 55f) membar #Sync 3: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) - STORE_SYNC(o0, f48) + STORE_SYNC(o0, f48) membar #Sync FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) - STORE_JUMP(o0, f48, 63f) + STORE_JUMP(o0, f48, 63f) membar #Sync 40: FINISH_VISCHUNK(o0, f0, f2, g3) 41: FINISH_VISCHUNK(o0, f2, f4, g3) diff --git a/trunk/arch/sparc64/lib/VISsave.S b/trunk/arch/sparc64/lib/VISsave.S index 4e18989bd602..65e328d600a8 100644 --- a/trunk/arch/sparc64/lib/VISsave.S +++ b/trunk/arch/sparc64/lib/VISsave.S @@ -72,11 +72,7 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 stda %f48, [%g3 + %g1] ASI_BLK_P 5: membar #Sync - ba,pt %xcc, 80f - nop - - .align 32 -80: jmpl %g7 + %g0, %g0 + jmpl %g7 + %g0, %g0 nop 6: ldub [%g3 + TI_FPSAVED], %o5 @@ -91,11 +87,8 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 stda %f32, [%g2 + %g1] ASI_BLK_P stda %f48, [%g3 + %g1] ASI_BLK_P membar #Sync - ba,pt %xcc, 80f - nop + jmpl %g7 + %g0, %g0 - .align 32 -80: jmpl %g7 + %g0, %g0 nop .align 32 @@ -133,10 +126,6 @@ VISenterhalf: stda %f0, [%g2 + %g1] ASI_BLK_P stda %f16, [%g3 + %g1] ASI_BLK_P membar #Sync - ba,pt %xcc, 4f - nop - - .align 32 4: and %o5, FPRS_DU, %o5 jmpl %g7 + %g0, %g0 wr %o5, FPRS_FEF, %fprs diff --git a/trunk/arch/sparc64/lib/atomic.S b/trunk/arch/sparc64/lib/atomic.S index faf87c31598b..e528b8d1a3e6 100644 --- a/trunk/arch/sparc64/lib/atomic.S +++ b/trunk/arch/sparc64/lib/atomic.S @@ -7,6 +7,18 @@ #include #include + /* On SMP we need to use memory barriers to ensure + * correct memory operation ordering, nop these out + * for uniprocessor. + */ +#ifdef CONFIG_SMP +#define ATOMIC_PRE_BARRIER membar #StoreLoad | #LoadLoad +#define ATOMIC_POST_BARRIER membar #StoreLoad | #StoreStore +#else +#define ATOMIC_PRE_BARRIER nop +#define ATOMIC_POST_BARRIER nop +#endif + .text /* Two versions of the atomic routines, one that @@ -40,24 +52,6 @@ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */ nop .size atomic_sub, .-atomic_sub - /* On SMP we need to use memory barriers to ensure - * correct memory operation ordering, nop these out - * for uniprocessor. - */ -#ifdef CONFIG_SMP - -#define ATOMIC_PRE_BARRIER membar #StoreLoad | #LoadLoad; -#define ATOMIC_POST_BARRIER \ - ba,pt %xcc, 80b; \ - membar #StoreLoad | #StoreStore - -80: retl - nop -#else -#define ATOMIC_PRE_BARRIER -#define ATOMIC_POST_BARRIER -#endif - .globl atomic_add_ret .type atomic_add_ret,#function atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ @@ -68,10 +62,9 @@ atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ cmp %g1, %g7 bne,pn %icc, 1b add %g7, %o0, %g7 - sra %g7, 0, %o0 ATOMIC_POST_BARRIER retl - nop + sra %g7, 0, %o0 .size atomic_add_ret, .-atomic_add_ret .globl atomic_sub_ret @@ -84,10 +77,9 @@ atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ cmp %g1, %g7 bne,pn %icc, 1b sub %g7, %o0, %g7 - sra %g7, 0, %o0 ATOMIC_POST_BARRIER retl - nop + sra %g7, 0, %o0 .size atomic_sub_ret, .-atomic_sub_ret .globl atomic64_add @@ -126,10 +118,9 @@ atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ cmp %g1, %g7 bne,pn %xcc, 1b add %g7, %o0, %g7 - mov %g7, %o0 ATOMIC_POST_BARRIER retl - nop + mov %g7, %o0 .size atomic64_add_ret, .-atomic64_add_ret .globl atomic64_sub_ret @@ -142,8 +133,7 @@ atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ cmp %g1, %g7 bne,pn %xcc, 1b sub %g7, %o0, %g7 - mov %g7, %o0 ATOMIC_POST_BARRIER retl - nop + mov %g7, %o0 .size atomic64_sub_ret, .-atomic64_sub_ret diff --git a/trunk/arch/sparc64/lib/bitops.S b/trunk/arch/sparc64/lib/bitops.S index 31afbfe6c1e8..886dcd2b376a 100644 --- a/trunk/arch/sparc64/lib/bitops.S +++ b/trunk/arch/sparc64/lib/bitops.S @@ -7,26 +7,20 @@ #include #include - .text - /* On SMP we need to use memory barriers to ensure * correct memory operation ordering, nop these out * for uniprocessor. */ - #ifdef CONFIG_SMP #define BITOP_PRE_BARRIER membar #StoreLoad | #LoadLoad -#define BITOP_POST_BARRIER \ - ba,pt %xcc, 80b; \ - membar #StoreLoad | #StoreStore - -80: retl - nop +#define BITOP_POST_BARRIER membar #StoreLoad | #StoreStore #else -#define BITOP_PRE_BARRIER -#define BITOP_POST_BARRIER +#define BITOP_PRE_BARRIER nop +#define BITOP_POST_BARRIER nop #endif + .text + .globl test_and_set_bit .type test_and_set_bit,#function test_and_set_bit: /* %o0=nr, %o1=addr */ @@ -43,11 +37,10 @@ test_and_set_bit: /* %o0=nr, %o1=addr */ cmp %g7, %g1 bne,pn %xcc, 1b and %g7, %o2, %g2 - clr %o0 - movrne %g2, 1, %o0 BITOP_POST_BARRIER + clr %o0 retl - nop + movrne %g2, 1, %o0 .size test_and_set_bit, .-test_and_set_bit .globl test_and_clear_bit @@ -66,11 +59,10 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */ cmp %g7, %g1 bne,pn %xcc, 1b and %g7, %o2, %g2 - clr %o0 - movrne %g2, 1, %o0 BITOP_POST_BARRIER + clr %o0 retl - nop + movrne %g2, 1, %o0 .size test_and_clear_bit, .-test_and_clear_bit .globl test_and_change_bit @@ -89,11 +81,10 @@ test_and_change_bit: /* %o0=nr, %o1=addr */ cmp %g7, %g1 bne,pn %xcc, 1b and %g7, %o2, %g2 - clr %o0 - movrne %g2, 1, %o0 BITOP_POST_BARRIER + clr %o0 retl - nop + movrne %g2, 1, %o0 .size test_and_change_bit, .-test_and_change_bit .globl set_bit diff --git a/trunk/arch/sparc64/lib/debuglocks.c b/trunk/arch/sparc64/lib/debuglocks.c index f03344cf784e..c421e0c65325 100644 --- a/trunk/arch/sparc64/lib/debuglocks.c +++ b/trunk/arch/sparc64/lib/debuglocks.c @@ -252,9 +252,8 @@ void _do_write_lock (rwlock_t *rw, char *str) " andn %%g1, %%g3, %%g7\n" " casx [%0], %%g1, %%g7\n" " cmp %%g1, %%g7\n" -" membar #StoreLoad | #StoreStore\n" " bne,pn %%xcc, 1b\n" -" nop" +" membar #StoreLoad | #StoreStore" : /* no outputs */ : "r" (&(rw->lock)) : "g3", "g1", "g7", "cc", "memory"); @@ -352,9 +351,8 @@ int _do_write_trylock (rwlock_t *rw, char *str) " andn %%g1, %%g3, %%g7\n" " casx [%0], %%g1, %%g7\n" " cmp %%g1, %%g7\n" -" membar #StoreLoad | #StoreStore\n" " bne,pn %%xcc, 1b\n" -" nop" +" membar #StoreLoad | #StoreStore" : /* no outputs */ : "r" (&(rw->lock)) : "g3", "g1", "g7", "cc", "memory"); diff --git a/trunk/arch/sparc64/lib/dec_and_lock.S b/trunk/arch/sparc64/lib/dec_and_lock.S index 8ee288dd0afc..7e6fdaebedba 100644 --- a/trunk/arch/sparc64/lib/dec_and_lock.S +++ b/trunk/arch/sparc64/lib/dec_and_lock.S @@ -48,9 +48,8 @@ start_to_zero: #endif to_zero: ldstub [%o1], %g3 - membar #StoreLoad | #StoreStore brnz,pn %g3, spin_on_lock - nop + membar #StoreLoad | #StoreStore loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */ cmp %g2, %g7 @@ -72,9 +71,8 @@ loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */ nop spin_on_lock: ldub [%o1], %g3 - membar #LoadLoad brnz,pt %g3, spin_on_lock - nop + membar #LoadLoad ba,pt %xcc, to_zero nop nop diff --git a/trunk/arch/sparc64/lib/rwsem.S b/trunk/arch/sparc64/lib/rwsem.S index 75f0e6b951d6..174ff7b9164c 100644 --- a/trunk/arch/sparc64/lib/rwsem.S +++ b/trunk/arch/sparc64/lib/rwsem.S @@ -17,9 +17,8 @@ __down_read: bne,pn %icc, 1b add %g7, 1, %g7 cmp %g7, 0 - membar #StoreLoad | #StoreStore bl,pn %icc, 3f - nop + membar #StoreLoad | #StoreStore 2: retl nop @@ -58,9 +57,8 @@ __down_write: cmp %g3, %g7 bne,pn %icc, 1b cmp %g7, 0 - membar #StoreLoad | #StoreStore bne,pn %icc, 3f - nop + membar #StoreLoad | #StoreStore 2: retl nop 3: @@ -99,9 +97,8 @@ __up_read: cmp %g1, %g7 bne,pn %icc, 1b cmp %g7, 0 - membar #StoreLoad | #StoreStore bl,pn %icc, 3f - nop + membar #StoreLoad | #StoreStore 2: retl nop 3: sethi %hi(RWSEM_ACTIVE_MASK), %g1 @@ -129,9 +126,8 @@ __up_write: bne,pn %icc, 1b sub %g7, %g1, %g7 cmp %g7, 0 - membar #StoreLoad | #StoreStore bl,pn %icc, 3f - nop + membar #StoreLoad | #StoreStore 2: retl nop @@ -155,9 +151,8 @@ __downgrade_write: bne,pn %icc, 1b sub %g7, %g1, %g7 cmp %g7, 0 - membar #StoreLoad | #StoreStore bl,pn %icc, 3f - nop + membar #StoreLoad | #StoreStore 2: retl nop diff --git a/trunk/arch/sparc64/mm/init.c b/trunk/arch/sparc64/mm/init.c index 8fc413cb6acd..9c5222075da9 100644 --- a/trunk/arch/sparc64/mm/init.c +++ b/trunk/arch/sparc64/mm/init.c @@ -136,9 +136,8 @@ static __inline__ void set_dcache_dirty(struct page *page, int this_cpu) "or %%g1, %0, %%g1\n\t" "casx [%2], %%g7, %%g1\n\t" "cmp %%g7, %%g1\n\t" - "membar #StoreLoad | #StoreStore\n\t" "bne,pn %%xcc, 1b\n\t" - " nop" + " membar #StoreLoad | #StoreStore" : /* no outputs */ : "r" (mask), "r" (non_cpu_bits), "r" (&page->flags) : "g1", "g7"); @@ -158,9 +157,8 @@ static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long c " andn %%g7, %1, %%g1\n\t" "casx [%2], %%g7, %%g1\n\t" "cmp %%g7, %%g1\n\t" - "membar #StoreLoad | #StoreStore\n\t" "bne,pn %%xcc, 1b\n\t" - " nop\n" + " membar #StoreLoad | #StoreStore\n" "2:" : /* no outputs */ : "r" (cpu), "r" (mask), "r" (&page->flags), diff --git a/trunk/arch/sparc64/mm/ultra.S b/trunk/arch/sparc64/mm/ultra.S index 7a2431d3abc7..7a0934321010 100644 --- a/trunk/arch/sparc64/mm/ultra.S +++ b/trunk/arch/sparc64/mm/ultra.S @@ -266,9 +266,8 @@ __cheetah_flush_tlb_pending: /* 22 insns */ andn %o3, 1, %o3 stxa %g0, [%o3] ASI_IMMU_DEMAP 2: stxa %g0, [%o3] ASI_DMMU_DEMAP - membar #Sync brnz,pt %o1, 1b - nop + membar #Sync stxa %g2, [%o4] ASI_DMMU flush %g6 wrpr %g0, 0, %tl diff --git a/trunk/drivers/block/cfq-iosched.c b/trunk/drivers/block/cfq-iosched.c index de5746e38af9..ff1cc968f96d 100644 --- a/trunk/drivers/block/cfq-iosched.c +++ b/trunk/drivers/block/cfq-iosched.c @@ -300,6 +300,7 @@ CFQ_CRQ_FNS(requeued); static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short); static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *); static void cfq_put_cfqd(struct cfq_data *cfqd); +static inline int cfq_pending_requests(struct cfq_data *cfqd); #define process_sync(tsk) ((tsk)->flags & PF_SYNCWRITE) @@ -347,28 +348,6 @@ static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset) return NULL; } -static inline int cfq_pending_requests(struct cfq_data *cfqd) -{ - return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues; -} - -/* - * scheduler run of queue, if there are requests pending and no one in the - * driver that will restart queueing - */ -static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) -{ - if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd)) - kblockd_schedule_work(&cfqd->unplug_work); -} - -static int cfq_queue_empty(request_queue_t *q) -{ - struct cfq_data *cfqd = q->elevator->elevator_data; - - return !cfq_pending_requests(cfqd); -} - /* * Lifted from AS - choose which of crq1 and crq2 that is best served now. * We choose the request that is closest to the head right now. Distance @@ -1092,6 +1071,16 @@ cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq) return 2 * (base_rq + base_rq * (CFQ_PRIO_LISTS - 1 - cfqq->ioprio)); } +/* + * scheduler run of queue, if there are requests pending and no one in the + * driver that will restart queueing + */ +static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) +{ + if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd)) + kblockd_schedule_work(&cfqd->unplug_work); +} + /* * get next queue for service */ @@ -1857,6 +1846,18 @@ cfq_insert_request(request_queue_t *q, struct request *rq, int where) } } +static inline int cfq_pending_requests(struct cfq_data *cfqd) +{ + return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues; +} + +static int cfq_queue_empty(request_queue_t *q) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + + return !cfq_pending_requests(cfqd); +} + static void cfq_completed_request(request_queue_t *q, struct request *rq) { struct cfq_rq *crq = RQ_DATA(rq); @@ -1951,7 +1952,7 @@ __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, { #if 1 if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) && - !cfq_cfqq_must_alloc_slice(cfqq)) { + !cfq_cfqq_must_alloc_slice) { cfq_mark_cfqq_must_alloc_slice(cfqq); return ELV_MQUEUE_MUST; } @@ -1968,7 +1969,7 @@ __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we * can quickly flood the queue with writes from a single task */ - if (rw == READ || !cfq_cfqq_must_alloc_slice(cfqq)) { + if (rw == READ || !cfq_cfqq_must_alloc_slice) { cfq_mark_cfqq_must_alloc_slice(cfqq); return ELV_MQUEUE_MUST; } diff --git a/trunk/drivers/bluetooth/bluecard_cs.c b/trunk/drivers/bluetooth/bluecard_cs.c index 5ef9adb9fe73..e481cc411b5d 100644 --- a/trunk/drivers/bluetooth/bluecard_cs.c +++ b/trunk/drivers/bluetooth/bluecard_cs.c @@ -1089,14 +1089,6 @@ static int bluecard_event(event_t event, int priority, event_callback_args_t *ar return 0; } -static struct pcmcia_device_id bluecard_ids[] = { - PCMCIA_DEVICE_PROD_ID12("BlueCard", "LSE041", 0xbaf16fbf, 0x657cc15e), - PCMCIA_DEVICE_PROD_ID12("BTCFCARD", "LSE139", 0xe3987764, 0x2524b59c), - PCMCIA_DEVICE_PROD_ID12("WSS", "LSE039", 0x0a0736ec, 0x24e6dfab), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, bluecard_ids); - static struct pcmcia_driver bluecard_driver = { .owner = THIS_MODULE, .drv = { @@ -1104,7 +1096,6 @@ static struct pcmcia_driver bluecard_driver = { }, .attach = bluecard_attach, .detach = bluecard_detach, - .id_table = bluecard_ids, }; static int __init init_bluecard_cs(void) diff --git a/trunk/drivers/bluetooth/bt3c_cs.c b/trunk/drivers/bluetooth/bt3c_cs.c index 9013cd759afb..f71e5c76963d 100644 --- a/trunk/drivers/bluetooth/bt3c_cs.c +++ b/trunk/drivers/bluetooth/bt3c_cs.c @@ -935,12 +935,6 @@ static int bt3c_event(event_t event, int priority, event_callback_args_t *args) return 0; } -static struct pcmcia_device_id bt3c_ids[] = { - PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, bt3c_ids); - static struct pcmcia_driver bt3c_driver = { .owner = THIS_MODULE, .drv = { @@ -948,7 +942,6 @@ static struct pcmcia_driver bt3c_driver = { }, .attach = bt3c_attach, .detach = bt3c_detach, - .id_table = bt3c_ids, }; static int __init init_bt3c_cs(void) diff --git a/trunk/drivers/bluetooth/btuart_cs.c b/trunk/drivers/bluetooth/btuart_cs.c index c479484a1f7f..ad8d972444a5 100644 --- a/trunk/drivers/bluetooth/btuart_cs.c +++ b/trunk/drivers/bluetooth/btuart_cs.c @@ -855,12 +855,6 @@ static int btuart_event(event_t event, int priority, event_callback_args_t *args return 0; } -static struct pcmcia_device_id btuart_ids[] = { - /* don't use this driver. Use serial_cs + hci_uart instead */ - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, btuart_ids); - static struct pcmcia_driver btuart_driver = { .owner = THIS_MODULE, .drv = { @@ -868,7 +862,6 @@ static struct pcmcia_driver btuart_driver = { }, .attach = btuart_attach, .detach = btuart_detach, - .id_table = btuart_ids, }; static int __init init_btuart_cs(void) diff --git a/trunk/drivers/bluetooth/dtl1_cs.c b/trunk/drivers/bluetooth/dtl1_cs.c index bb12f7daeb91..fe954e5d9a1d 100644 --- a/trunk/drivers/bluetooth/dtl1_cs.c +++ b/trunk/drivers/bluetooth/dtl1_cs.c @@ -807,13 +807,6 @@ static int dtl1_event(event_t event, int priority, event_callback_args_t *args) return 0; } -static struct pcmcia_device_id dtl1_ids[] = { - PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d), - PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, dtl1_ids); - static struct pcmcia_driver dtl1_driver = { .owner = THIS_MODULE, .drv = { @@ -821,7 +814,6 @@ static struct pcmcia_driver dtl1_driver = { }, .attach = dtl1_attach, .detach = dtl1_detach, - .id_table = dtl1_ids, }; static int __init init_dtl1_cs(void) diff --git a/trunk/drivers/char/pcmcia/synclink_cs.c b/trunk/drivers/char/pcmcia/synclink_cs.c index 8f36b1758eb6..1c8d866a49dc 100644 --- a/trunk/drivers/char/pcmcia/synclink_cs.c +++ b/trunk/drivers/char/pcmcia/synclink_cs.c @@ -581,7 +581,7 @@ static dev_link_t *mgslpc_attach(void) /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; link->irq.Handler = NULL; link->conf.Attributes = 0; @@ -3081,12 +3081,6 @@ void mgslpc_remove_device(MGSLPC_INFO *remove_info) } } -static struct pcmcia_device_id mgslpc_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x02c5, 0x0050), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids); - static struct pcmcia_driver mgslpc_driver = { .owner = THIS_MODULE, .drv = { @@ -3094,7 +3088,6 @@ static struct pcmcia_driver mgslpc_driver = { }, .attach = mgslpc_attach, .detach = mgslpc_detach, - .id_table = mgslpc_ids, }; static struct tty_operations mgslpc_ops = { diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig index 5f33df47aa74..0273f124a4f7 100644 --- a/trunk/drivers/ide/Kconfig +++ b/trunk/drivers/ide/Kconfig @@ -606,12 +606,6 @@ config BLK_DEV_IT8172 ; picture of the board at . -config BLK_DEV_IT821X - tristate "IT821X IDE support" - help - This driver adds support for the ITE 8211 IDE controller and the - IT 8212 IDE RAID controller in both RAID and pass-through mode. - config BLK_DEV_NS87415 tristate "NS87415 chipset support" help diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c index f9c1acb4ed6a..d6f934886b04 100644 --- a/trunk/drivers/ide/ide-disk.c +++ b/trunk/drivers/ide/ide-disk.c @@ -119,10 +119,6 @@ static int lba_capacity_is_ok (struct hd_driveid *id) { unsigned long lba_sects, chs_sects, head, tail; - /* No non-LBA info .. so valid! */ - if (id->cyls == 0) - return 1; - /* * The ATA spec tells large drives to return * C/H/S = 16383/16/63 independent of their size. diff --git a/trunk/drivers/ide/ide-dma.c b/trunk/drivers/ide/ide-dma.c index 1e1531334c25..2d2eefb610dd 100644 --- a/trunk/drivers/ide/ide-dma.c +++ b/trunk/drivers/ide/ide-dma.c @@ -132,6 +132,7 @@ static const struct drive_list_entry drive_blacklist [] = { { "SAMSUNG CD-ROM SC-148C", "ALL" }, { "SAMSUNG CD-ROM SC", "ALL" }, { "SanDisk SDP3B-64" , "ALL" }, + { "SAMSUNG CD-ROM SN-124", "ALL" }, { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" }, { "_NEC DV5800A", "ALL" }, { NULL , NULL } diff --git a/trunk/drivers/ide/ide-iops.c b/trunk/drivers/ide/ide-iops.c index b443b04a4c5a..53024942a7eb 100644 --- a/trunk/drivers/ide/ide-iops.c +++ b/trunk/drivers/ide/ide-iops.c @@ -1181,8 +1181,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) pre_reset(drive); SELECT_DRIVE(drive); udelay (20); - hwif->OUTBSYNC(drive, WIN_SRST, IDE_COMMAND_REG); - ndelay(400); + hwif->OUTB(WIN_SRST, IDE_COMMAND_REG); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; hwgroup->polling = 1; __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); diff --git a/trunk/drivers/ide/legacy/ide-cs.c b/trunk/drivers/ide/legacy/ide-cs.c index 978d27d6452d..e20327e54b1a 100644 --- a/trunk/drivers/ide/legacy/ide-cs.c +++ b/trunk/drivers/ide/legacy/ide-cs.c @@ -457,40 +457,6 @@ int ide_event(event_t event, int priority, return 0; } /* ide_event */ -static struct pcmcia_device_id ide_ids[] = { - PCMCIA_DEVICE_FUNC_ID(4), - PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), - PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), - PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), - PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), - PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0), - PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74), - PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9), - PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728), - PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4), - PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde), - PCMCIA_DEVICE_PROD_ID12("EXP", "CD", 0x6f58c983, 0xaae5994f), - PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), - PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), - PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), - PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), - PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), - PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674), - PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b), - PCMCIA_DEVICE_PROD_ID12(" ", "NinjaATA-", 0x3b6e20c8, 0xebe0bd79), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728), - PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1), - PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), - PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), - PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, ide_ids); - static struct pcmcia_driver ide_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -498,7 +464,6 @@ static struct pcmcia_driver ide_cs_driver = { }, .attach = ide_attach, .detach = ide_detach, - .id_table = ide_ids, }; static int __init init_ide_cs(void) diff --git a/trunk/drivers/ide/pci/Makefile b/trunk/drivers/ide/pci/Makefile index af46226c1796..55e6e553e497 100644 --- a/trunk/drivers/ide/pci/Makefile +++ b/trunk/drivers/ide/pci/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o #obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o -obj-$(CONFIG_BLK_DEV_IT821X) += it821x.o obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o obj-$(CONFIG_BLK_DEV_PDC202XX_OLD) += pdc202xx_old.o diff --git a/trunk/drivers/ide/pci/generic.c b/trunk/drivers/ide/pci/generic.c index da46577380f3..4565cc311ff3 100644 --- a/trunk/drivers/ide/pci/generic.c +++ b/trunk/drivers/ide/pci/generic.c @@ -39,17 +39,6 @@ #include -static int ide_generic_all; /* Set to claim all devices */ - -static int __init ide_generic_all_on(char *unused) -{ - ide_generic_all = 1; - printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n"); - return 1; -} - -__setup("all-generic-ide", ide_generic_all_on); - static void __devinit init_hwif_generic (ide_hwif_t *hwif) { switch(hwif->pci_dev->device) { @@ -89,85 +78,79 @@ static void __devinit init_hwif_generic (ide_hwif_t *hwif) static ide_pci_device_t generic_chipsets[] __devinitdata = { { /* 0 */ - .name = "Unknown", - .init_hwif = init_hwif_generic, - .channels = 2, - .autodma = AUTODMA, - .bootable = ON_BOARD, - },{ /* 1 */ .name = "NS87410", .init_hwif = init_hwif_generic, .channels = 2, .autodma = AUTODMA, .enablebits = {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, .bootable = ON_BOARD, - },{ /* 2 */ + },{ /* 1 */ .name = "SAMURAI", .init_hwif = init_hwif_generic, .channels = 2, .autodma = AUTODMA, .bootable = ON_BOARD, - },{ /* 3 */ + },{ /* 2 */ .name = "HT6565", .init_hwif = init_hwif_generic, .channels = 2, .autodma = AUTODMA, .bootable = ON_BOARD, - },{ /* 4 */ + },{ /* 3 */ .name = "UM8673F", .init_hwif = init_hwif_generic, .channels = 2, .autodma = NODMA, .bootable = ON_BOARD, - },{ /* 5 */ + },{ /* 4 */ .name = "UM8886A", .init_hwif = init_hwif_generic, .channels = 2, .autodma = NODMA, .bootable = ON_BOARD, - },{ /* 6 */ + },{ /* 5 */ .name = "UM8886BF", .init_hwif = init_hwif_generic, .channels = 2, .autodma = NODMA, .bootable = ON_BOARD, - },{ /* 7 */ + },{ /* 6 */ .name = "HINT_IDE", .init_hwif = init_hwif_generic, .channels = 2, .autodma = AUTODMA, .bootable = ON_BOARD, - },{ /* 8 */ + },{ /* 7 */ .name = "VIA_IDE", .init_hwif = init_hwif_generic, .channels = 2, .autodma = NOAUTODMA, .bootable = ON_BOARD, - },{ /* 9 */ + },{ /* 8 */ .name = "OPTI621V", .init_hwif = init_hwif_generic, .channels = 2, .autodma = NOAUTODMA, .bootable = ON_BOARD, - },{ /* 10 */ + },{ /* 9 */ .name = "VIA8237SATA", .init_hwif = init_hwif_generic, .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - },{ /* 11 */ + },{ /* 10 */ .name = "Piccolo0102", .init_hwif = init_hwif_generic, .channels = 2, .autodma = NOAUTODMA, .bootable = ON_BOARD, - },{ /* 12 */ + },{ /* 11 */ .name = "Piccolo0103", .init_hwif = init_hwif_generic, .channels = 2, .autodma = NOAUTODMA, .bootable = ON_BOARD, - },{ /* 13 */ + },{ /* 12 */ .name = "Piccolo0105", .init_hwif = init_hwif_generic, .channels = 2, @@ -191,10 +174,6 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi u16 command; int ret = -ENODEV; - /* Don't use the generic entry unless instructed to do so */ - if (id->driver_data == 0 && ide_generic_all == 0) - goto out; - if (dev->vendor == PCI_VENDOR_ID_UMC && dev->device == PCI_DEVICE_ID_UMC_UM8886A && (!(PCI_FUNC(dev->devfn) & 1))) @@ -216,23 +195,21 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi } static struct pci_device_id generic_pci_tbl[] = { - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, - { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, - { PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, - { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, - { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, - { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, - { PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, - { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, - { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, + { PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7}, + { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8}, #ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9}, #endif - { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11}, - { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, - { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13}, - /* Must come last. If you add entries adjust this table appropriately and the init_one code */ - { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0}, + { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10}, + { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11}, + { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, { 0, }, }; MODULE_DEVICE_TABLE(pci, generic_pci_tbl); diff --git a/trunk/drivers/ide/pci/hpt366.c b/trunk/drivers/ide/pci/hpt366.c index 7b64db10d1b0..c8ee0b8c0292 100644 --- a/trunk/drivers/ide/pci/hpt366.c +++ b/trunk/drivers/ide/pci/hpt366.c @@ -10,11 +10,6 @@ * donation of an ABit BP6 mainboard, processor, and memory acellerated * development and support. * - * - * Highpoint have their own driver (source except for the raid part) - * available from http://www.highpoint-tech.com/hpt3xx-opensource-v131.tgz - * This may be useful to anyone wanting to work on the mainstream hpt IDE. - * * Note that final HPT370 support was done by force extraction of GPL. * * - add function for getting/setting power status of drive @@ -451,29 +446,44 @@ static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { #define F_LOW_PCI_50 0x2d #define F_LOW_PCI_66 0x42 -/* - * Hold all the highpoint quirks and revision information in one - * place. - */ - -struct hpt_info -{ - u8 max_mode; /* Speeds allowed */ - int revision; /* Chipset revision */ - int flags; /* Chipset properties */ -#define PLL_MODE 1 -#define IS_372N 2 - /* Speed table */ - struct chipset_bus_clock_list_entry *speed; -}; - -/* - * This wants fixing so that we do everything not by classrev - * (which breaks on the newest chips) but by creating an - * enumeration of chip variants and using that - */ +/* FIXME: compare with driver's code before removing */ +#if 0 + if (hpt_minimum_revision(dev, 3)) { + u8 cbl; + cbl = inb(iobase + 0x7b); + outb(cbl | 1, iobase + 0x7b); + outb(cbl & ~1, iobase + 0x7b); + cbl = inb(iobase + 0x7a); + p += sprintf(p, "Cable: ATA-%d" + " ATA-%d\n", + (cbl & 0x02) ? 33 : 66, + (cbl & 0x01) ? 33 : 66); + p += sprintf(p, "\n"); + } + { + u8 c2, c3; + /* older revs don't have these registers mapped + * into io space */ + pci_read_config_byte(dev, 0x43, &c0); + pci_read_config_byte(dev, 0x47, &c1); + pci_read_config_byte(dev, 0x4b, &c2); + pci_read_config_byte(dev, 0x4f, &c3); + + p += sprintf(p, "Mode: %s %s" + " %s %s\n", + (c0 & 0x10) ? "UDMA" : (c0 & 0x20) ? "DMA " : + (c0 & 0x80) ? "PIO " : "off ", + (c1 & 0x10) ? "UDMA" : (c1 & 0x20) ? "DMA " : + (c1 & 0x80) ? "PIO " : "off ", + (c2 & 0x10) ? "UDMA" : (c2 & 0x20) ? "DMA " : + (c2 & 0x80) ? "PIO " : "off ", + (c3 & 0x10) ? "UDMA" : (c3 & 0x20) ? "DMA " : + (c3 & 0x80) ? "PIO " : "off "); + } + } +#endif -static __devinit u32 hpt_revision (struct pci_dev *dev) +static u32 hpt_revision (struct pci_dev *dev) { u32 class_rev; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); @@ -497,33 +507,37 @@ static __devinit u32 hpt_revision (struct pci_dev *dev) return class_rev; } +static u32 hpt_minimum_revision (struct pci_dev *dev, int revision) +{ + unsigned int class_rev = hpt_revision(dev); + revision--; + return ((int) (class_rev > revision) ? 1 : 0); +} + static int check_in_drive_lists(ide_drive_t *drive, const char **list); static u8 hpt3xx_ratemask (ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); + struct pci_dev *dev = HWIF(drive)->pci_dev; u8 mode = 0; - /* FIXME: TODO - move this to set info->mode once at boot */ - - if (info->revision >= 8) { /* HPT374 */ + if (hpt_minimum_revision(dev, 8)) { /* HPT374 */ mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 7) { /* HPT371 */ + } else if (hpt_minimum_revision(dev, 7)) { /* HPT371 */ mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 6) { /* HPT302 */ + } else if (hpt_minimum_revision(dev, 6)) { /* HPT302 */ mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 5) { /* HPT372 */ + } else if (hpt_minimum_revision(dev, 5)) { /* HPT372 */ mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 4) { /* HPT370A */ + } else if (hpt_minimum_revision(dev, 4)) { /* HPT370A */ mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; - } else if (info->revision >= 3) { /* HPT370 */ + } else if (hpt_minimum_revision(dev, 3)) { /* HPT370 */ mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode; } else { /* HPT366 and HPT368 */ mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2; } - if (!eighty_ninty_three(drive) && mode) + if (!eighty_ninty_three(drive) && (mode)) mode = min(mode, (u8)1); return mode; } @@ -535,8 +549,7 @@ static u8 hpt3xx_ratemask (ide_drive_t *drive) static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) { - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); + struct pci_dev *dev = HWIF(drive)->pci_dev; u8 mode = hpt3xx_ratemask(drive); if (drive->media != ide_disk) @@ -548,7 +561,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) break; case 0x03: speed = min(speed, (u8)XFER_UDMA_5); - if (info->revision >= 5) + if (hpt_minimum_revision(dev, 5)) break; if (check_in_drive_lists(drive, bad_ata100_5)) speed = min(speed, (u8)XFER_UDMA_4); @@ -558,7 +571,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) /* * CHECK ME, Does this need to be set to 5 ?? */ - if (info->revision >= 3) + if (hpt_minimum_revision(dev, 3)) break; if ((check_in_drive_lists(drive, bad_ata66_4)) || (!(HPT366_ALLOW_ATA66_4))) @@ -572,7 +585,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) /* * CHECK ME, Does this need to be set to 5 ?? */ - if (info->revision >= 3) + if (hpt_minimum_revision(dev, 3)) break; if (check_in_drive_lists(drive, bad_ata33)) speed = min(speed, (u8)XFER_MW_DMA_2); @@ -611,12 +624,11 @@ static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) { - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); + struct pci_dev *dev = HWIF(drive)->pci_dev; u8 speed = hpt3xx_ratefilter(drive, xferspeed); +// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed); u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; - u8 regfast = (hwif->channel) ? 0x55 : 0x51; + u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; u8 drive_fast = 0; u32 reg1 = 0, reg2 = 0; @@ -624,11 +636,16 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) * Disable the "fast interrupt" prediction. */ pci_read_config_byte(dev, regfast, &drive_fast); +#if 0 + if (drive_fast & 0x02) + pci_write_config_byte(dev, regfast, drive_fast & ~0x20); +#else if (drive_fast & 0x80) pci_write_config_byte(dev, regfast, drive_fast & ~0x80); +#endif - reg2 = pci_bus_clock_list(speed, info->speed); - + reg2 = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) pci_get_drvdata(dev)); /* * Disable on-chip PIO FIFO/buffer * (to avoid problems handling I/O errors later) @@ -648,11 +665,10 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) { - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); + struct pci_dev *dev = HWIF(drive)->pci_dev; u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; +// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed); + u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; u8 drive_pci = 0x40 + (drive->dn * 4); u8 new_fast = 0, drive_fast = 0; u32 list_conf = 0, drive_conf = 0; @@ -677,13 +693,17 @@ static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) if (new_fast != drive_fast) pci_write_config_byte(dev, regfast, new_fast); - list_conf = pci_bus_clock_list(speed, info->speed); + list_conf = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) + pci_get_drvdata(dev)); pci_read_config_dword(dev, drive_pci, &drive_conf); list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); - if (speed < XFER_MW_DMA_0) + if (speed < XFER_MW_DMA_0) { list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ + } + pci_write_config_dword(dev, drive_pci, list_conf); return ide_config_drive_speed(drive, speed); @@ -691,11 +711,10 @@ static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) { - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); + struct pci_dev *dev = HWIF(drive)->pci_dev; u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; +// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed); + u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4); u32 list_conf = 0, drive_conf = 0; u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; @@ -707,8 +726,10 @@ static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) pci_read_config_byte(dev, regfast, &drive_fast); drive_fast &= ~0x07; pci_write_config_byte(dev, regfast, drive_fast); - - list_conf = pci_bus_clock_list(speed, info->speed); + + list_conf = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) + pci_get_drvdata(dev)); pci_read_config_dword(dev, drive_pci, &drive_conf); list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); if (speed < XFER_MW_DMA_0) @@ -720,14 +741,19 @@ static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed) { - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); + struct pci_dev *dev = HWIF(drive)->pci_dev; - if (info->revision >= 8) + if (hpt_minimum_revision(dev, 8)) return hpt372_tune_chipset(drive, speed); /* not a typo */ - else if (info->revision >= 5) +#if 0 + else if (hpt_minimum_revision(dev, 7)) + hpt371_tune_chipset(drive, speed); + else if (hpt_minimum_revision(dev, 6)) + hpt302_tune_chipset(drive, speed); +#endif + else if (hpt_minimum_revision(dev, 5)) return hpt372_tune_chipset(drive, speed); - else if (info->revision >= 3) + else if (hpt_minimum_revision(dev, 3)) return hpt370_tune_chipset(drive, speed); else /* hpt368: hpt_minimum_revision(dev, 2) */ return hpt36x_tune_chipset(drive, speed); @@ -753,14 +779,8 @@ static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio) static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); - if (!speed) - return 0; - - /* If we don't have any timings we can't do a lot */ - if (info->speed == NULL) + if (!(speed)) return 0; (void) hpt3xx_tune_chipset(drive, speed); @@ -774,7 +794,7 @@ static int hpt3xx_quirkproc (ide_drive_t *drive) static void hpt3xx_intrproc (ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = HWIF(drive); if (drive->quirk_list) return; @@ -784,26 +804,24 @@ static void hpt3xx_intrproc (ide_drive_t *drive) static void hpt3xx_maskproc (ide_drive_t *drive, int mask) { - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = HWIF(drive)->pci_dev; if (drive->quirk_list) { - if (info->revision >= 3) { + if (hpt_minimum_revision(dev,3)) { u8 reg5a = 0; pci_read_config_byte(dev, 0x5a, ®5a); if (((reg5a & 0x10) >> 4) != mask) pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); } else { if (mask) { - disable_irq(hwif->irq); + disable_irq(HWIF(drive)->irq); } else { - enable_irq(hwif->irq); + enable_irq(HWIF(drive)->irq); } } } else { if (IDE_CONTROL_REG) - hwif->OUTB(mask ? (drive->ctl | 2) : + HWIF(drive)->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2), IDE_CONTROL_REG); } @@ -811,12 +829,12 @@ static void hpt3xx_maskproc (ide_drive_t *drive, int mask) static int hpt366_config_drive_xfer_rate (ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = HWIF(drive); struct hd_driveid *id = drive->id; drive->init_speed = 0; - if ((id->capability & 1) && drive->autodma) { + if (id && (id->capability & 1) && drive->autodma) { if (ide_use_dma(drive)) { if (config_chipset_for_dma(drive)) @@ -850,6 +868,15 @@ static int hpt366_ide_dma_lostirq (ide_drive_t *drive) drive->name, __FUNCTION__, reg50h, reg52h, reg5ah); if (reg5ah & 0x10) pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); +#if 0 + /* how about we flush and reset, mmmkay? */ + pci_write_config_byte(dev, 0x51, 0x1F); + /* fall through to a reset */ + case dma_start: + case ide_dma_end: + /* reset the chips state over and over.. */ + pci_write_config_byte(dev, 0x51, 0x13); +#endif return __ide_dma_lostirq(drive); } @@ -892,7 +919,7 @@ static void hpt370_lostirq_timeout (ide_drive_t *drive) u8 dma_stat = 0, dma_cmd = 0; pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo); - printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo); + printk("%s: %d bytes in FIFO\n", drive->name, bfifo); hpt370_clear_engine(drive); /* get dma command mode */ dma_cmd = hwif->INB(hwif->dma_command); @@ -1020,6 +1047,15 @@ static void hpt372n_rw_disk(ide_drive_t *drive, struct request *rq) static void hpt3xx_reset (ide_drive_t *drive) { +#if 0 + unsigned long high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4); + u8 reset = (HWIF(drive)->channel) ? 0x80 : 0x40; + u8 reg59h = 0; + + pci_read_config_byte(HWIF(drive)->pci_dev, 0x59, ®59h); + pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h|reset); + pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h); +#endif } static int hpt3xx_tristate (ide_drive_t * drive, int state) @@ -1029,6 +1065,8 @@ static int hpt3xx_tristate (ide_drive_t * drive, int state) u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40; u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53; +// hwif->bus_state = state; + pci_read_config_byte(dev, 0x59, ®59h); pci_read_config_byte(dev, state_reg, ®XXh); @@ -1055,7 +1093,7 @@ static int hpt3xx_tristate (ide_drive_t * drive, int state) #define TRISTATE_BIT 0x8000 static int hpt370_busproc(ide_drive_t * drive, int state) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 tristate = 0, resetmask = 0, bus_reg = 0; u16 tri_reg; @@ -1110,44 +1148,33 @@ static int hpt370_busproc(ide_drive_t * drive, int state) return 0; } -static void __devinit hpt366_clocking(ide_hwif_t *hwif) -{ - u32 reg1 = 0; - struct hpt_info *info = ide_get_hwifdata(hwif); - - pci_read_config_dword(hwif->pci_dev, 0x40, ®1); - - /* detect bus speed by looking at control reg timing: */ - switch((reg1 >> 8) & 7) { - case 5: - info->speed = forty_base_hpt366; - break; - case 9: - info->speed = twenty_five_base_hpt366; - break; - case 7: - default: - info->speed = thirty_three_base_hpt366; - break; - } -} - -static void __devinit hpt37x_clocking(ide_hwif_t *hwif) +static int __devinit init_hpt37x(struct pci_dev *dev) { - struct hpt_info *info = ide_get_hwifdata(hwif); - struct pci_dev *dev = hwif->pci_dev; int adjust, i; u16 freq; u32 pll; u8 reg5bh; + u8 reg5ah = 0; + unsigned long dmabase = pci_resource_start(dev, 4); + u8 did, rid; + int is_372n = 0; + pci_read_config_byte(dev, 0x5a, ®5ah); + /* interrupt force enable */ + pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); + + if(dmabase) + { + did = inb(dmabase + 0x22); + rid = inb(dmabase + 0x28); + + if((did == 4 && rid == 6) || (did == 5 && rid > 1)) + is_372n = 1; + } + /* * default to pci clock. make sure MA15/16 are set to output - * to prevent drives having problems with 40-pin cables. Needed - * for some drives such as IBM-DTLA which will not enter ready - * state on reset when PDIAG is a input. - * - * ToDo: should we set 0x21 when using PLL mode ? + * to prevent drives having problems with 40-pin cables. */ pci_write_config_byte(dev, 0x5b, 0x23); @@ -1170,7 +1197,9 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) * Currently we always set up the PLL for the 372N */ - if(info->flags & IS_372N) + pci_set_drvdata(dev, NULL); + + if(is_372n) { printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n"); if(freq < 0x55) @@ -1198,38 +1227,39 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pll = F_LOW_PCI_66; if (pll == F_LOW_PCI_33) { - if (info->revision >= 8) - info->speed = thirty_three_base_hpt374; - else if (info->revision >= 5) - info->speed = thirty_three_base_hpt372; - else if (info->revision >= 4) - info->speed = thirty_three_base_hpt370a; + if (hpt_minimum_revision(dev,8)) + pci_set_drvdata(dev, (void *) thirty_three_base_hpt374); + else if (hpt_minimum_revision(dev,5)) + pci_set_drvdata(dev, (void *) thirty_three_base_hpt372); + else if (hpt_minimum_revision(dev,4)) + pci_set_drvdata(dev, (void *) thirty_three_base_hpt370a); else - info->speed = thirty_three_base_hpt370; - printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n"); + pci_set_drvdata(dev, (void *) thirty_three_base_hpt370); + printk("HPT37X: using 33MHz PCI clock\n"); } else if (pll == F_LOW_PCI_40) { /* Unsupported */ } else if (pll == F_LOW_PCI_50) { - if (info->revision >= 8) - info->speed = fifty_base_hpt370a; - else if (info->revision >= 5) - info->speed = fifty_base_hpt372; - else if (info->revision >= 4) - info->speed = fifty_base_hpt370a; + if (hpt_minimum_revision(dev,8)) + pci_set_drvdata(dev, (void *) fifty_base_hpt370a); + else if (hpt_minimum_revision(dev,5)) + pci_set_drvdata(dev, (void *) fifty_base_hpt372); + else if (hpt_minimum_revision(dev,4)) + pci_set_drvdata(dev, (void *) fifty_base_hpt370a); else - info->speed = fifty_base_hpt370a; - printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n"); + pci_set_drvdata(dev, (void *) fifty_base_hpt370a); + printk("HPT37X: using 50MHz PCI clock\n"); } else { - if (info->revision >= 8) { + if (hpt_minimum_revision(dev,8)) + { printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n"); } - else if (info->revision >= 5) - info->speed = sixty_six_base_hpt372; - else if (info->revision >= 4) - info->speed = sixty_six_base_hpt370a; + else if (hpt_minimum_revision(dev,5)) + pci_set_drvdata(dev, (void *) sixty_six_base_hpt372); + else if (hpt_minimum_revision(dev,4)) + pci_set_drvdata(dev, (void *) sixty_six_base_hpt370a); else - info->speed = sixty_six_base_hpt370; - printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); + pci_set_drvdata(dev, (void *) sixty_six_base_hpt370); + printk("HPT37X: using 66MHz PCI clock\n"); } } @@ -1239,19 +1269,11 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) * result in slow reads when using a 33MHz PCI clock. we also * don't like to use the PLL because it will cause glitches * on PRST/SRST when the HPT state engine gets reset. - * - * ToDo: Use 66MHz PLL when ATA133 devices are present on a - * 372 device so we can get ATA133 support */ - if (info->speed) + if (pci_get_drvdata(dev)) goto init_hpt37X_done; - - info->flags |= PLL_MODE; /* - * FIXME: make this work correctly, esp with 372N as per - * reference driver code. - * * adjust PLL based upon PCI clock, enable it, and wait for * stabilization. */ @@ -1276,14 +1298,14 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pci_write_config_dword(dev, 0x5c, pll & ~0x100); pci_write_config_byte(dev, 0x5b, 0x21); - if (info->revision >= 8) - info->speed = fifty_base_hpt370a; - else if (info->revision >= 5) - info->speed = fifty_base_hpt372; - else if (info->revision >= 4) - info->speed = fifty_base_hpt370a; + if (hpt_minimum_revision(dev,8)) + pci_set_drvdata(dev, (void *) fifty_base_hpt370a); + else if (hpt_minimum_revision(dev,5)) + pci_set_drvdata(dev, (void *) fifty_base_hpt372); + else if (hpt_minimum_revision(dev,4)) + pci_set_drvdata(dev, (void *) fifty_base_hpt370a); else - info->speed = fifty_base_hpt370a; + pci_set_drvdata(dev, (void *) fifty_base_hpt370a); printk("HPT37X: using 50MHz internal PLL\n"); goto init_hpt37X_done; } @@ -1296,22 +1318,10 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) } init_hpt37X_done: - if (!info->speed) - printk(KERN_ERR "HPT37X%s: unknown bus timing [%d %d].\n", - (info->flags & IS_372N)?"N":"", pll, freq); /* reset state engine */ pci_write_config_byte(dev, 0x50, 0x37); pci_write_config_byte(dev, 0x54, 0x37); udelay(100); -} - -static int __devinit init_hpt37x(struct pci_dev *dev) -{ - u8 reg5ah; - - pci_read_config_byte(dev, 0x5a, ®5ah); - /* interrupt force enable */ - pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); return 0; } @@ -1328,27 +1338,59 @@ static int __devinit init_hpt366(struct pci_dev *dev) pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); pci_read_config_dword(dev, 0x40, ®1); + /* detect bus speed by looking at control reg timing: */ + switch((reg1 >> 8) & 7) { + case 5: + pci_set_drvdata(dev, (void *) forty_base_hpt366); + break; + case 9: + pci_set_drvdata(dev, (void *) twenty_five_base_hpt366); + break; + case 7: + default: + pci_set_drvdata(dev, (void *) thirty_three_base_hpt366); + break; + } + + if (!pci_get_drvdata(dev)) + { + printk(KERN_ERR "hpt366: unknown bus timing.\n"); + pci_set_drvdata(dev, NULL); + } return 0; } static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) { int ret = 0; - /* FIXME: Not portable */ + u8 test = 0; + if (dev->resource[PCI_ROM_RESOURCE].start) pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); + pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test); + if (test != (L1_CACHE_BYTES / 4)) + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, + (L1_CACHE_BYTES / 4)); - if (hpt_revision(dev) >= 3) - ret = init_hpt37x(dev); - else - ret = init_hpt366(dev); + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test); + if (test != 0x78) + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); + + pci_read_config_byte(dev, PCI_MIN_GNT, &test); + if (test != 0x08) + pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); + + pci_read_config_byte(dev, PCI_MAX_LAT, &test); + if (test != 0x08) + pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); + if (hpt_minimum_revision(dev, 3)) { + ret = init_hpt37x(dev); + } else { + ret =init_hpt366(dev); + } if (ret) return ret; @@ -1358,16 +1400,27 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02; + u8 did, rid; + unsigned long dmabase = hwif->dma_base; + int is_372n = 0; + if(dmabase) + { + did = inb(dmabase + 0x22); + rid = inb(dmabase + 0x28); + + if((did == 4 && rid == 6) || (did == 5 && rid > 1)) + is_372n = 1; + } + hwif->tuneproc = &hpt3xx_tune_drive; hwif->speedproc = &hpt3xx_tune_chipset; hwif->quirkproc = &hpt3xx_quirkproc; hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc; - if(info->flags & IS_372N) + if(is_372n) hwif->rw_disk = &hpt372n_rw_disk; /* @@ -1375,7 +1428,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) * address lines to access an external eeprom. To read valid * cable detect state the pins must be enabled as inputs. */ - if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) { + if (hpt_minimum_revision(dev, 8) && PCI_FUNC(dev->devfn) & 1) { /* * HPT374 PCI function 1 * - set bit 15 of reg 0x52 to enable TCBLID as input @@ -1390,7 +1443,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) pci_read_config_byte(dev, 0x5a, &ata66); pci_write_config_word(dev, 0x52, mcr3); pci_write_config_word(dev, 0x56, mcr6); - } else if (info->revision >= 3) { + } else if (hpt_minimum_revision(dev, 3)) { /* * HPT370/372 and 374 pcifn 0 * - clear bit 0 of 0x5b to enable P/SCBLID as inputs @@ -1417,7 +1470,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->serialized = hwif->mate->serialized = 1; #endif - if (info->revision >= 3) { + if (hpt_minimum_revision(dev,3)) { u8 reg5ah = 0; pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); /* @@ -1427,7 +1480,8 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) */ hwif->resetproc = &hpt3xx_reset; hwif->busproc = &hpt370_busproc; - } else if (info->revision >= 2) { +// hwif->drives[0].autotune = hwif->drives[1].autotune = 1; + } else if (hpt_minimum_revision(dev,2)) { hwif->resetproc = &hpt3xx_reset; hwif->busproc = &hpt3xx_tristate; } else { @@ -1448,18 +1502,18 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->udma_four = ((ata66 & regmask) ? 0 : 1); hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; - if (info->revision >= 8) { + if (hpt_minimum_revision(dev,8)) { hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; hwif->ide_dma_end = &hpt374_ide_dma_end; - } else if (info->revision >= 5) { + } else if (hpt_minimum_revision(dev,5)) { hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; hwif->ide_dma_end = &hpt374_ide_dma_end; - } else if (info->revision >= 3) { + } else if (hpt_minimum_revision(dev,3)) { hwif->dma_start = &hpt370_ide_dma_start; hwif->ide_dma_end = &hpt370_ide_dma_end; hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq; - } else if (info->revision >= 2) + } else if (hpt_minimum_revision(dev,2)) hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; else hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; @@ -1472,7 +1526,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) { - struct hpt_info *info = ide_get_hwifdata(hwif); u8 masterdma = 0, slavedma = 0; u8 dma_new = 0, dma_old = 0; u8 primary = hwif->channel ? 0x4b : 0x43; @@ -1482,7 +1535,8 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) if (!dmabase) return; - if(info->speed == NULL) { + if(pci_get_drvdata(hwif->pci_dev) == NULL) + { printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n"); return; } @@ -1505,40 +1559,6 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) ide_setup_dma(hwif, dmabase, 8); } -/* - * We "borrow" this hook in order to set the data structures - * up early enough before dma or init_hwif calls are made. - */ - -static void __devinit init_iops_hpt366(ide_hwif_t *hwif) -{ - struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL); - unsigned long dmabase = pci_resource_start(hwif->pci_dev, 4); - u8 did, rid; - - if(info == NULL) { - printk(KERN_WARNING "hpt366: out of memory.\n"); - return; - } - memset(info, 0, sizeof(struct hpt_info)); - ide_set_hwifdata(hwif, info); - - if(dmabase) { - did = inb(dmabase + 0x22); - rid = inb(dmabase + 0x28); - - if((did == 4 && rid == 6) || (did == 5 && rid > 1)) - info->flags |= IS_372N; - } - - info->revision = hpt_revision(hwif->pci_dev); - - if (info->revision >= 3) - hpt37x_clocking(hwif); - else - hpt366_clocking(hwif); -} - static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) { struct pci_dev *findev = NULL; @@ -1626,7 +1646,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .name = "HPT366", .init_setup = init_setup_hpt366, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, @@ -1637,7 +1656,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .name = "HPT372A", .init_setup = init_setup_hpt37x, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, @@ -1647,7 +1665,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .name = "HPT302", .init_setup = init_setup_hpt37x, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, @@ -1657,7 +1674,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .name = "HPT371", .init_setup = init_setup_hpt37x, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, @@ -1667,7 +1683,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .name = "HPT374", .init_setup = init_setup_hpt374, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, /* 4 */ @@ -1677,7 +1692,6 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .name = "HPT372N", .init_setup = init_setup_hpt37x, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, /* 4 */ diff --git a/trunk/drivers/ide/pci/it821x.c b/trunk/drivers/ide/pci/it821x.c deleted file mode 100644 index e440036e651f..000000000000 --- a/trunk/drivers/ide/pci/it821x.c +++ /dev/null @@ -1,812 +0,0 @@ - -/* - * linux/drivers/ide/pci/it821x.c Version 0.09 December 2004 - * - * Copyright (C) 2004 Red Hat - * - * May be copied or modified under the terms of the GNU General Public License - * Based in part on the ITE vendor provided SCSI driver. - * - * Documentation available from - * http://www.ite.com.tw/pc/IT8212F_V04.pdf - * Some other documents are NDA. - * - * The ITE8212 isn't exactly a standard IDE controller. It has two - * modes. In pass through mode then it is an IDE controller. In its smart - * mode its actually quite a capable hardware raid controller disguised - * as an IDE controller. Smart mode only understands DMA read/write and - * identify, none of the fancier commands apply. The IT8211 is identical - * in other respects but lacks the raid mode. - * - * Errata: - * o Rev 0x10 also requires master/slave hold the same DMA timings and - * cannot do ATAPI MWDMA. - * o The identify data for raid volumes lacks CHS info (technically ok) - * but also fails to set the LBA28 and other bits. We fix these in - * the IDE probe quirk code. - * o If you write LBA48 sized I/O's (ie > 256 sector) in smart mode - * raid then the controller firmware dies - * o Smart mode without RAID doesn't clear all the necessary identify - * bits to reduce the command set to the one used - * - * This has a few impacts on the driver - * - In pass through mode we do all the work you would expect - * - In smart mode the clocking set up is done by the controller generally - * but we must watch the other limits and filter. - * - There are a few extra vendor commands that actually talk to the - * controller but only work PIO with no IRQ. - * - * Vendor areas of the identify block in smart mode are used for the - * timing and policy set up. Each HDD in raid mode also has a serial - * block on the disk. The hardware extra commands are get/set chip status, - * rebuild, get rebuild status. - * - * In Linux the driver supports pass through mode as if the device was - * just another IDE controller. If the smart mode is running then - * volumes are managed by the controller firmware and each IDE "disk" - * is a raid volume. Even more cute - the controller can do automated - * hotplug and rebuild. - * - * The pass through controller itself is a little demented. It has a - * flaw that it has a single set of PIO/MWDMA timings per channel so - * non UDMA devices restrict each others performance. It also has a - * single clock source per channel so mixed UDMA100/133 performance - * isn't perfect and we have to pick a clock. Thankfully none of this - * matters in smart mode. ATAPI DMA is not currently supported. - * - * It seems the smart mode is a win for RAID1/RAID10 but otherwise not. - * - * TODO - * - ATAPI UDMA is ok but not MWDMA it seems - * - RAID configuration ioctls - * - Move to libata once it grows up - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -struct it821x_dev -{ - unsigned int smart:1, /* Are we in smart raid mode */ - timing10:1; /* Rev 0x10 */ - u8 clock_mode; /* 0, ATA_50 or ATA_66 */ - u8 want[2][2]; /* Mode/Pri log for master slave */ - /* We need these for switching the clock when DMA goes on/off - The high byte is the 66Mhz timing */ - u16 pio[2]; /* Cached PIO values */ - u16 mwdma[2]; /* Cached MWDMA values */ - u16 udma[2]; /* Cached UDMA values (per drive) */ -}; - -#define ATA_66 0 -#define ATA_50 1 -#define ATA_ANY 2 - -#define UDMA_OFF 0 -#define MWDMA_OFF 0 - -/* - * We allow users to force the card into non raid mode without - * flashing the alternative BIOS. This is also neccessary right now - * for embedded platforms that cannot run a PC BIOS but are using this - * device. - */ - -static int it8212_noraid; - -/** - * it821x_program - program the PIO/MWDMA registers - * @drive: drive to tune - * - * Program the PIO/MWDMA timing for this channel according to the - * current clock. - */ - -static void it821x_program(ide_drive_t *drive, u16 timing) -{ - ide_hwif_t *hwif = drive->hwif; - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - int channel = hwif->channel; - u8 conf; - - /* Program PIO/MWDMA timing bits */ - if(itdev->clock_mode == ATA_66) - conf = timing >> 8; - else - conf = timing & 0xFF; - pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf); -} - -/** - * it821x_program_udma - program the UDMA registers - * @drive: drive to tune - * - * Program the UDMA timing for this drive according to the - * current clock. - */ - -static void it821x_program_udma(ide_drive_t *drive, u16 timing) -{ - ide_hwif_t *hwif = drive->hwif; - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - int channel = hwif->channel; - int unit = drive->select.b.unit; - u8 conf; - - /* Program UDMA timing bits */ - if(itdev->clock_mode == ATA_66) - conf = timing >> 8; - else - conf = timing & 0xFF; - if(itdev->timing10 == 0) - pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, conf); - else { - pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel, conf); - pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + 1, conf); - } -} - - -/** - * it821x_clock_strategy - * @hwif: hardware interface - * - * Select between the 50 and 66Mhz base clocks to get the best - * results for this interface. - */ - -static void it821x_clock_strategy(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - - u8 unit = drive->select.b.unit; - ide_drive_t *pair = &hwif->drives[1-unit]; - - int clock, altclock; - u8 v; - int sel = 0; - - if(itdev->want[0][0] > itdev->want[1][0]) { - clock = itdev->want[0][1]; - altclock = itdev->want[1][1]; - } else { - clock = itdev->want[1][1]; - altclock = itdev->want[0][1]; - } - - /* Master doesn't care does the slave ? */ - if(clock == ATA_ANY) - clock = altclock; - - /* Nobody cares - keep the same clock */ - if(clock == ATA_ANY) - return; - /* No change */ - if(clock == itdev->clock_mode) - return; - - /* Load this into the controller ? */ - if(clock == ATA_66) - itdev->clock_mode = ATA_66; - else { - itdev->clock_mode = ATA_50; - sel = 1; - } - pci_read_config_byte(hwif->pci_dev, 0x50, &v); - v &= ~(1 << (1 + hwif->channel)); - v |= sel << (1 + hwif->channel); - pci_write_config_byte(hwif->pci_dev, 0x50, v); - - /* - * Reprogram the UDMA/PIO of the pair drive for the switch - * MWDMA will be dealt with by the dma switcher - */ - if(pair && itdev->udma[1-unit] != UDMA_OFF) { - it821x_program_udma(pair, itdev->udma[1-unit]); - it821x_program(pair, itdev->pio[1-unit]); - } - /* - * Reprogram the UDMA/PIO of our drive for the switch. - * MWDMA will be dealt with by the dma switcher - */ - if(itdev->udma[unit] != UDMA_OFF) { - it821x_program_udma(drive, itdev->udma[unit]); - it821x_program(drive, itdev->pio[unit]); - } -} - -/** - * it821x_ratemask - Compute available modes - * @drive: IDE drive - * - * Compute the available speeds for the devices on the interface. This - * is all modes to ATA133 clipped by drive cable setup. - */ - -static u8 it821x_ratemask (ide_drive_t *drive) -{ - u8 mode = 4; - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); - return mode; -} - -/** - * it821x_tuneproc - tune a drive - * @drive: drive to tune - * @mode_wanted: the target operating mode - * - * Load the timing settings for this device mode into the - * controller. By the time we are called the mode has been - * modified as neccessary to handle the absence of seperate - * master/slave timers for MWDMA/PIO. - * - * This code is only used in pass through mode. - */ - -static void it821x_tuneproc (ide_drive_t *drive, byte mode_wanted) -{ - ide_hwif_t *hwif = drive->hwif; - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - int unit = drive->select.b.unit; - - /* Spec says 89 ref driver uses 88 */ - static u16 pio[] = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 }; - static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY }; - - if(itdev->smart) - return; - - /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */ - itdev->want[unit][1] = pio_want[mode_wanted]; - itdev->want[unit][0] = 1; /* PIO is lowest priority */ - itdev->pio[unit] = pio[mode_wanted]; - it821x_clock_strategy(drive); - it821x_program(drive, itdev->pio[unit]); -} - -/** - * it821x_tune_mwdma - tune a channel for MWDMA - * @drive: drive to set up - * @mode_wanted: the target operating mode - * - * Load the timing settings for this device mode into the - * controller when doing MWDMA in pass through mode. The caller - * must manage the whole lack of per device MWDMA/PIO timings and - * the shared MWDMA/PIO timing register. - */ - -static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted) -{ - ide_hwif_t *hwif = drive->hwif; - struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif); - int unit = drive->select.b.unit; - int channel = hwif->channel; - u8 conf; - - static u16 dma[] = { 0x8866, 0x3222, 0x3121 }; - static u8 mwdma_want[] = { ATA_ANY, ATA_66, ATA_ANY }; - - itdev->want[unit][1] = mwdma_want[mode_wanted]; - itdev->want[unit][0] = 2; /* MWDMA is low priority */ - itdev->mwdma[unit] = dma[mode_wanted]; - itdev->udma[unit] = UDMA_OFF; - - /* UDMA bits off - Revision 0x10 do them in pairs */ - pci_read_config_byte(hwif->pci_dev, 0x50, &conf); - if(itdev->timing10) - conf |= channel ? 0x60: 0x18; - else - conf |= 1 << (3 + 2 * channel + unit); - pci_write_config_byte(hwif->pci_dev, 0x50, conf); - - it821x_clock_strategy(drive); - /* FIXME: do we need to program this ? */ - /* it821x_program(drive, itdev->mwdma[unit]); */ -} - -/** - * it821x_tune_udma - tune a channel for UDMA - * @drive: drive to set up - * @mode_wanted: the target operating mode - * - * Load the timing settings for this device mode into the - * controller when doing UDMA modes in pass through. - */ - -static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted) -{ - ide_hwif_t *hwif = drive->hwif; - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - int unit = drive->select.b.unit; - int channel = hwif->channel; - u8 conf; - - static u16 udma[] = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 }; - static u8 udma_want[] = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 }; - - itdev->want[unit][1] = udma_want[mode_wanted]; - itdev->want[unit][0] = 3; /* UDMA is high priority */ - itdev->mwdma[unit] = MWDMA_OFF; - itdev->udma[unit] = udma[mode_wanted]; - if(mode_wanted >= 5) - itdev->udma[unit] |= 0x8080; /* UDMA 5/6 select on */ - - /* UDMA on. Again revision 0x10 must do the pair */ - pci_read_config_byte(hwif->pci_dev, 0x50, &conf); - if(itdev->timing10) - conf &= channel ? 0x9F: 0xE7; - else - conf &= ~ (1 << (3 + 2 * channel + unit)); - pci_write_config_byte(hwif->pci_dev, 0x50, conf); - - it821x_clock_strategy(drive); - it821x_program_udma(drive, itdev->udma[unit]); - -} - -/** - * config_it821x_chipset_for_pio - set drive timings - * @drive: drive to tune - * @speed we want - * - * Compute the best pio mode we can for a given device. We must - * pick a speed that does not cause problems with the other device - * on the cable. - */ - -static void config_it821x_chipset_for_pio (ide_drive_t *drive, byte set_speed) -{ - u8 unit = drive->select.b.unit; - ide_hwif_t *hwif = drive->hwif; - ide_drive_t *pair = &hwif->drives[1-unit]; - u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - u8 pair_pio; - - /* We have to deal with this mess in pairs */ - if(pair != NULL) { - pair_pio = ide_get_best_pio_mode(pair, 255, 5, NULL); - /* Trim PIO to the slowest of the master/slave */ - if(pair_pio < set_pio) - set_pio = pair_pio; - } - it821x_tuneproc(drive, set_pio); - speed = XFER_PIO_0 + set_pio; - /* XXX - We trim to the lowest of the pair so the other drive - will always be fine at this point until we do hotplug passthru */ - - if (set_speed) - (void) ide_config_drive_speed(drive, speed); -} - -/** - * it821x_dma_read - DMA hook - * @drive: drive for DMA - * - * The IT821x has a single timing register for MWDMA and for PIO - * operations. As we flip back and forth we have to reload the - * clock. In addition the rev 0x10 device only works if the same - * timing value is loaded into the master and slave UDMA clock - * so we must also reload that. - * - * FIXME: we could figure out in advance if we need to do reloads - */ - -static void it821x_dma_start(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - int unit = drive->select.b.unit; - if(itdev->mwdma[unit] != MWDMA_OFF) - it821x_program(drive, itdev->mwdma[unit]); - else if(itdev->udma[unit] != UDMA_OFF && itdev->timing10) - it821x_program_udma(drive, itdev->udma[unit]); - ide_dma_start(drive); -} - -/** - * it821x_dma_write - DMA hook - * @drive: drive for DMA stop - * - * The IT821x has a single timing register for MWDMA and for PIO - * operations. As we flip back and forth we have to reload the - * clock. - */ - -static int it821x_dma_end(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - int unit = drive->select.b.unit; - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - int ret = __ide_dma_end(drive); - if(itdev->mwdma[unit] != MWDMA_OFF) - it821x_program(drive, itdev->pio[unit]); - return ret; -} - - -/** - * it821x_tune_chipset - set controller timings - * @drive: Drive to set up - * @xferspeed: speed we want to achieve - * - * Tune the ITE chipset for the desired mode. If we can't achieve - * the desired mode then tune for a lower one, but ultimately - * make the thing work. - */ - -static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed) -{ - - ide_hwif_t *hwif = drive->hwif; - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - u8 speed = ide_rate_filter(it821x_ratemask(drive), xferspeed); - - if(!itdev->smart) { - switch(speed) { - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - it821x_tuneproc(drive, (speed - XFER_PIO_0)); - break; - /* MWDMA tuning is really hard because our MWDMA and PIO - timings are kept in the same place. We can switch in the - host dma on/off callbacks */ - case XFER_MW_DMA_2: - case XFER_MW_DMA_1: - case XFER_MW_DMA_0: - it821x_tune_mwdma(drive, (speed - XFER_MW_DMA_0)); - break; - case XFER_UDMA_6: - case XFER_UDMA_5: - case XFER_UDMA_4: - case XFER_UDMA_3: - case XFER_UDMA_2: - case XFER_UDMA_1: - case XFER_UDMA_0: - it821x_tune_udma(drive, (speed - XFER_UDMA_0)); - break; - default: - return 1; - } - } - /* - * In smart mode the clocking is done by the host controller - * snooping the mode we picked. The rest of it is not our problem - */ - return ide_config_drive_speed(drive, speed); -} - -/** - * config_chipset_for_dma - configure for DMA - * @drive: drive to configure - * - * Called by the IDE layer when it wants the timings set up. - */ - -static int config_chipset_for_dma (ide_drive_t *drive) -{ - u8 speed = ide_dma_speed(drive, it821x_ratemask(drive)); - - config_it821x_chipset_for_pio(drive, !speed); - it821x_tune_chipset(drive, speed); - return ide_dma_enable(drive); -} - -/** - * it821x_configure_drive_for_dma - set up for DMA transfers - * @drive: drive we are going to set up - * - * Set up the drive for DMA, tune the controller and drive as - * required. If the drive isn't suitable for DMA or we hit - * other problems then we will drop down to PIO and set up - * PIO appropriately - */ - -static int it821x_config_drive_for_dma (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } - config_it821x_chipset_for_pio(drive, 1); - return hwif->ide_dma_off_quietly(drive); -} - -/** - * ata66_it821x - check for 80 pin cable - * @hwif: interface to check - * - * Check for the presence of an ATA66 capable cable on the - * interface. Problematic as it seems some cards don't have - * the needed logic onboard. - */ - -static unsigned int __devinit ata66_it821x(ide_hwif_t *hwif) -{ - /* The reference driver also only does disk side */ - return 1; -} - -/** - * it821x_fixup - post init callback - * @hwif: interface - * - * This callback is run after the drives have been probed but - * before anything gets attached. It allows drivers to do any - * final tuning that is needed, or fixups to work around bugs. - */ - -static void __devinit it821x_fixups(ide_hwif_t *hwif) -{ - struct it821x_dev *itdev = ide_get_hwifdata(hwif); - int i; - - if(!itdev->smart) { - /* - * If we are in pass through mode then not much - * needs to be done, but we do bother to clear the - * IRQ mask as we may well be in PIO (eg rev 0x10) - * for now and we know unmasking is safe on this chipset. - */ - for (i = 0; i < 2; i++) { - ide_drive_t *drive = &hwif->drives[i]; - if(drive->present) - drive->unmask = 1; - } - return; - } - /* - * Perform fixups on smart mode. We need to "lose" some - * capabilities the firmware lacks but does not filter, and - * also patch up some capability bits that it forgets to set - * in RAID mode. - */ - - for(i = 0; i < 2; i++) { - ide_drive_t *drive = &hwif->drives[i]; - struct hd_driveid *id; - u16 *idbits; - - if(!drive->present) - continue; - id = drive->id; - idbits = (u16 *)drive->id; - - /* Check for RAID v native */ - if(strstr(id->model, "Integrated Technology Express")) { - /* In raid mode the ident block is slightly buggy - We need to set the bits so that the IDE layer knows - LBA28. LBA48 and DMA ar valid */ - id->capability |= 3; /* LBA28, DMA */ - id->command_set_2 |= 0x0400; /* LBA48 valid */ - id->cfs_enable_2 |= 0x0400; /* LBA48 on */ - /* Reporting logic */ - printk(KERN_INFO "%s: IT8212 %sRAID %d volume", - drive->name, - idbits[147] ? "Bootable ":"", - idbits[129]); - if(idbits[129] != 1) - printk("(%dK stripe)", idbits[146]); - printk(".\n"); - /* Now the core code will have wrongly decided no DMA - so we need to fix this */ - hwif->ide_dma_off_quietly(drive); -#ifdef CONFIG_IDEDMA_ONLYDISK - if (drive->media == ide_disk) -#endif - hwif->ide_dma_check(drive); - } else { - /* Non RAID volume. Fixups to stop the core code - doing unsupported things */ - id->field_valid &= 1; - id->queue_depth = 0; - id->command_set_1 = 0; - id->command_set_2 &= 0xC400; - id->cfsse &= 0xC000; - id->cfs_enable_1 = 0; - id->cfs_enable_2 &= 0xC400; - id->csf_default &= 0xC000; - id->word127 = 0; - id->dlf = 0; - id->csfo = 0; - id->cfa_power = 0; - printk(KERN_INFO "%s: Performing identify fixups.\n", - drive->name); - } - } - -} - -/** - * init_hwif_it821x - set up hwif structs - * @hwif: interface to set up - * - * We do the basic set up of the interface structure. The IT8212 - * requires several custom handlers so we override the default - * ide DMA handlers appropriately - */ - -static void __devinit init_hwif_it821x(ide_hwif_t *hwif) -{ - struct it821x_dev *idev = kmalloc(sizeof(struct it821x_dev), GFP_KERNEL); - u8 conf; - - if(idev == NULL) { - printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n"); - goto fallback; - } - memset(idev, 0, sizeof(struct it821x_dev)); - ide_set_hwifdata(hwif, idev); - - pci_read_config_byte(hwif->pci_dev, 0x50, &conf); - if(conf & 1) { - idev->smart = 1; - hwif->atapi_dma = 0; - /* Long I/O's although allowed in LBA48 space cause the - onboard firmware to enter the twighlight zone */ - hwif->rqsize = 256; - } - - /* Pull the current clocks from 0x50 also */ - if (conf & (1 << (1 + hwif->channel))) - idev->clock_mode = ATA_50; - else - idev->clock_mode = ATA_66; - - idev->want[0][1] = ATA_ANY; - idev->want[1][1] = ATA_ANY; - - /* - * Not in the docs but according to the reference driver - * this is neccessary. - */ - - pci_read_config_byte(hwif->pci_dev, 0x08, &conf); - if(conf == 0x10) { - idev->timing10 = 1; - hwif->atapi_dma = 0; - if(!idev->smart) - printk(KERN_WARNING "it821x: Revision 0x10, workarounds activated.\n"); - } - - hwif->speedproc = &it821x_tune_chipset; - hwif->tuneproc = &it821x_tuneproc; - - /* MWDMA/PIO clock switching for pass through mode */ - if(!idev->smart) { - hwif->dma_start = &it821x_dma_start; - hwif->ide_dma_end = &it821x_dma_end; - } - - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (!hwif->dma_base) - goto fallback; - - hwif->ultra_mask = 0x7f; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x07; - - hwif->ide_dma_check = &it821x_config_drive_for_dma; - if (!(hwif->udma_four)) - hwif->udma_four = ata66_it821x(hwif); - - /* - * The BIOS often doesn't set up DMA on this controller - * so we always do it. - */ - - hwif->autodma = 1; - hwif->drives[0].autodma = hwif->autodma; - hwif->drives[1].autodma = hwif->autodma; - return; -fallback: - hwif->autodma = 0; - return; -} - -static void __devinit it8212_disable_raid(struct pci_dev *dev) -{ - /* Reset local CPU, and set BIOS not ready */ - pci_write_config_byte(dev, 0x5E, 0x01); - - /* Set to bypass mode, and reset PCI bus */ - pci_write_config_byte(dev, 0x50, 0x00); - pci_write_config_word(dev, PCI_COMMAND, - PCI_COMMAND_PARITY | PCI_COMMAND_IO | - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - pci_write_config_word(dev, 0x40, 0xA0F3); - - pci_write_config_dword(dev,0x4C, 0x02040204); - pci_write_config_byte(dev, 0x42, 0x36); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0); -} - -static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const char *name) -{ - u8 conf; - static char *mode[2] = { "pass through", "smart" }; - - /* Force the card into bypass mode if so requested */ - if (it8212_noraid) { - printk(KERN_INFO "it8212: forcing bypass mode.\n"); - it8212_disable_raid(dev); - } - pci_read_config_byte(dev, 0x50, &conf); - printk(KERN_INFO "it821x: controller in %s mode.\n", mode[conf & 1]); - return 0; -} - - -#define DECLARE_ITE_DEV(name_str) \ - { \ - .name = name_str, \ - .init_chipset = init_chipset_it821x, \ - .init_hwif = init_hwif_it821x, \ - .channels = 2, \ - .autodma = AUTODMA, \ - .bootable = ON_BOARD, \ - .fixup = it821x_fixups \ - } - -static ide_pci_device_t it821x_chipsets[] __devinitdata = { - /* 0 */ DECLARE_ITE_DEV("IT8212"), -}; - -/** - * it821x_init_one - pci layer discovery entry - * @dev: PCI device - * @id: ident table entry - * - * Called by the PCI code when it finds an ITE821x controller. - * We then use the IDE PCI generic helper to do most of the work. - */ - -static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id) -{ - ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]); - return 0; -} - -static struct pci_device_id it821x_pci_tbl[] = { - { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { 0, }, -}; - -MODULE_DEVICE_TABLE(pci, it821x_pci_tbl); - -static struct pci_driver driver = { - .name = "ITE821x IDE", - .id_table = it821x_pci_tbl, - .probe = it821x_init_one, -}; - -static int __init it821x_ide_init(void) -{ - return ide_pci_register_driver(&driver); -} - -module_init(it821x_ide_init); - -module_param_named(noraid, it8212_noraid, int, S_IRUGO); -MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode"); - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("PCI driver module for the ITE 821x"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/ide/pci/serverworks.c b/trunk/drivers/ide/pci/serverworks.c index c6f5fa4b4ca6..82a1103b2413 100644 --- a/trunk/drivers/ide/pci/serverworks.c +++ b/trunk/drivers/ide/pci/serverworks.c @@ -442,7 +442,7 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha return (dev->irq) ? dev->irq : 0; } -static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif) +static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif) { return 1; } @@ -454,7 +454,7 @@ static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif) * Bit 14 clear = primary IDE channel does not have 80-pin cable. * Bit 14 set = primary IDE channel has 80-pin cable. */ -static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif) +static unsigned int __init ata66_svwks_dell (ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL && @@ -472,7 +472,7 @@ static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif) * * WARNING: this only works on Alpine hardware! */ -static unsigned int __devinit ata66_svwks_cobalt (ide_hwif_t *hwif) +static unsigned int __init ata66_svwks_cobalt (ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN && @@ -483,7 +483,7 @@ static unsigned int __devinit ata66_svwks_cobalt (ide_hwif_t *hwif) return 0; } -static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif) +static unsigned int __init ata66_svwks (ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; @@ -573,7 +573,7 @@ static int __devinit init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d) return ide_setup_pci_device(dev, d); } -static int __devinit init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d) +static int __init init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d) { if (!(PCI_FUNC(dev->devfn) & 1)) { d->bootable = NEVER_BOARD; diff --git a/trunk/drivers/input/gameport/gameport.c b/trunk/drivers/input/gameport/gameport.c index 3e72c9b1461e..c77a82e46055 100644 --- a/trunk/drivers/input/gameport/gameport.c +++ b/trunk/drivers/input/gameport/gameport.c @@ -17,10 +17,11 @@ #include #include #include +#include #include +#include #include #include -#include /*#include */ @@ -237,7 +238,8 @@ struct gameport_event { static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ static LIST_HEAD(gameport_event_list); static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); -static struct task_struct *gameport_task; +static DECLARE_COMPLETION(gameport_exited); +static int gameport_pid; static void gameport_queue_event(void *object, struct module *owner, enum gameport_event_type event_type) @@ -248,12 +250,12 @@ static void gameport_queue_event(void *object, struct module *owner, spin_lock_irqsave(&gameport_event_lock, flags); /* - * Scan event list for the other events for the same gameport port, + * Scan event list for the other events for the same gameport port, * starting with the most recent one. If event is the same we * do not need add new one. If event is of different type we * need to add this event and should not look further because * we need to preseve sequence of distinct events. - */ + */ list_for_each_entry_reverse(event, &gameport_event_list, node) { if (event->object == object) { if (event->type == event_type) @@ -430,15 +432,20 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent) static int gameport_thread(void *nothing) { + lock_kernel(); + daemonize("kgameportd"); + allow_signal(SIGTERM); + do { gameport_handle_events(); - wait_event_interruptible(gameport_wait, - kthread_should_stop() || !list_empty(&gameport_event_list)); + wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list)); try_to_freeze(); - } while (!kthread_should_stop()); + } while (!signal_pending(current)); printk(KERN_DEBUG "gameport: kgameportd exiting\n"); - return 0; + + unlock_kernel(); + complete_and_exit(&gameport_exited, 0); } @@ -766,10 +773,9 @@ void gameport_close(struct gameport *gameport) static int __init gameport_init(void) { - gameport_task = kthread_run(gameport_thread, NULL, "kgameportd"); - if (IS_ERR(gameport_task)) { + if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) { printk(KERN_ERR "gameport: Failed to start kgameportd\n"); - return PTR_ERR(gameport_task); + return -1; } gameport_bus.dev_attrs = gameport_device_attrs; @@ -783,7 +789,8 @@ static int __init gameport_init(void) static void __exit gameport_exit(void) { bus_unregister(&gameport_bus); - kthread_stop(gameport_task); + kill_proc(gameport_pid, SIGTERM, 1); + wait_for_completion(&gameport_exited); } module_init(gameport_init); diff --git a/trunk/drivers/input/serio/serio.c b/trunk/drivers/input/serio/serio.c index f367695e69b5..341824c48529 100644 --- a/trunk/drivers/input/serio/serio.c +++ b/trunk/drivers/input/serio/serio.c @@ -31,9 +31,10 @@ #include #include #include +#include #include +#include #include -#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Serio abstraction core"); @@ -42,7 +43,6 @@ MODULE_LICENSE("GPL"); EXPORT_SYMBOL(serio_interrupt); EXPORT_SYMBOL(__serio_register_port); EXPORT_SYMBOL(serio_unregister_port); -EXPORT_SYMBOL(serio_unregister_child_port); EXPORT_SYMBOL(__serio_unregister_port_delayed); EXPORT_SYMBOL(__serio_register_driver); EXPORT_SYMBOL(serio_unregister_driver); @@ -68,37 +68,6 @@ static void serio_destroy_port(struct serio *serio); static void serio_reconnect_port(struct serio *serio); static void serio_disconnect_port(struct serio *serio); -static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) -{ - int retval; - - down(&serio->drv_sem); - retval = drv->connect(serio, drv); - up(&serio->drv_sem); - - return retval; -} - -static int serio_reconnect_driver(struct serio *serio) -{ - int retval = -1; - - down(&serio->drv_sem); - if (serio->drv && serio->drv->reconnect) - retval = serio->drv->reconnect(serio); - up(&serio->drv_sem); - - return retval; -} - -static void serio_disconnect_driver(struct serio *serio) -{ - down(&serio->drv_sem); - if (serio->drv) - serio->drv->disconnect(serio); - up(&serio->drv_sem); -} - static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) { while (ids->type || ids->proto) { @@ -122,7 +91,7 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) if (serio_match_port(drv->id_table, serio)) { serio->dev.driver = &drv->driver; - if (serio_connect_driver(serio, drv)) { + if (drv->connect(serio, drv)) { serio->dev.driver = NULL; goto out; } @@ -169,7 +138,8 @@ struct serio_event { static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ static LIST_HEAD(serio_event_list); static DECLARE_WAIT_QUEUE_HEAD(serio_wait); -static struct task_struct *serio_task; +static DECLARE_COMPLETION(serio_exited); +static int serio_pid; static void serio_queue_event(void *object, struct module *owner, enum serio_event_type event_type) @@ -180,12 +150,12 @@ static void serio_queue_event(void *object, struct module *owner, spin_lock_irqsave(&serio_event_lock, flags); /* - * Scan event list for the other events for the same serio port, + * Scan event list for the other events for the same serio port, * starting with the most recent one. If event is the same we * do not need add new one. If event is of different type we * need to add this event and should not look further because * we need to preseve sequence of distinct events. - */ + */ list_for_each_entry_reverse(event, &serio_event_list, node) { if (event->object == object) { if (event->type == event_type) @@ -367,15 +337,20 @@ static struct serio *serio_get_pending_child(struct serio *parent) static int serio_thread(void *nothing) { + lock_kernel(); + daemonize("kseriod"); + allow_signal(SIGTERM); + do { serio_handle_events(); - wait_event_interruptible(serio_wait, - kthread_should_stop() || !list_empty(&serio_event_list)); + wait_event_interruptible(serio_wait, !list_empty(&serio_event_list)); try_to_freeze(); - } while (!kthread_should_stop()); + } while (!signal_pending(current)); printk(KERN_DEBUG "serio: kseriod exiting\n"); - return 0; + + unlock_kernel(); + complete_and_exit(&serio_exited, 0); } @@ -582,7 +557,7 @@ static void serio_destroy_port(struct serio *serio) static void serio_reconnect_port(struct serio *serio) { do { - if (serio_reconnect_driver(serio)) { + if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { serio_disconnect_port(serio); serio_find_driver(serio); /* Ok, old children are now gone, we are done */ @@ -654,19 +629,6 @@ void serio_unregister_port(struct serio *serio) up(&serio_sem); } -/* - * Safely unregisters child port if one is present. - */ -void serio_unregister_child_port(struct serio *serio) -{ - down(&serio_sem); - if (serio->child) { - serio_disconnect_port(serio->child); - serio_destroy_port(serio->child); - } - up(&serio_sem); -} - /* * Submits register request to kseriod for subsequent execution. * Can be used when it is not obvious whether the serio_sem is @@ -724,14 +686,15 @@ static int serio_driver_probe(struct device *dev) struct serio *serio = to_serio_port(dev); struct serio_driver *drv = to_serio_driver(dev->driver); - return serio_connect_driver(serio, drv); + return drv->connect(serio, drv); } static int serio_driver_remove(struct device *dev) { struct serio *serio = to_serio_port(dev); + struct serio_driver *drv = to_serio_driver(dev->driver); - serio_disconnect_driver(serio); + drv->disconnect(serio); return 0; } @@ -767,9 +730,11 @@ void serio_unregister_driver(struct serio_driver *drv) static void serio_set_drv(struct serio *serio, struct serio_driver *drv) { + down(&serio->drv_sem); serio_pause_rx(serio); serio->drv = drv; serio_continue_rx(serio); + up(&serio->drv_sem); } static int serio_bus_match(struct device *dev, struct device_driver *drv) @@ -829,7 +794,7 @@ static int serio_resume(struct device *dev) { struct serio *serio = to_serio_port(dev); - if (serio_reconnect_driver(serio)) { + if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { /* * Driver re-probing can take a while, so better let kseriod * deal with it. @@ -883,10 +848,9 @@ irqreturn_t serio_interrupt(struct serio *serio, static int __init serio_init(void) { - serio_task = kthread_run(serio_thread, NULL, "kseriod"); - if (IS_ERR(serio_task)) { + if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) { printk(KERN_ERR "serio: Failed to start kseriod\n"); - return PTR_ERR(serio_task); + return -1; } serio_bus.dev_attrs = serio_device_attrs; @@ -902,7 +866,8 @@ static int __init serio_init(void) static void __exit serio_exit(void) { bus_unregister(&serio_bus); - kthread_stop(serio_task); + kill_proc(serio_pid, SIGTERM, 1); + wait_for_completion(&serio_exited); } module_init(serio_init); diff --git a/trunk/drivers/isdn/hardware/avm/avm_cs.c b/trunk/drivers/isdn/hardware/avm/avm_cs.c index ee750e9456dd..dc00c85e3e35 100644 --- a/trunk/drivers/isdn/hardware/avm/avm_cs.c +++ b/trunk/drivers/isdn/hardware/avm/avm_cs.c @@ -486,14 +486,6 @@ static int avmcs_event(event_t event, int priority, return 0; } /* avmcs_event */ -static struct pcmcia_device_id avmcs_ids[] = { - PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335), - PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M1", 0x95d42008, 0x81e10430), - PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M2", 0x95d42008, 0x18e8558a), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, avmcs_ids); - static struct pcmcia_driver avmcs_driver = { .owner = THIS_MODULE, .drv = { @@ -501,7 +493,6 @@ static struct pcmcia_driver avmcs_driver = { }, .attach = avmcs_attach, .detach = avmcs_detach, - .id_table = avmcs_ids, }; static int __init avmcs_init(void) diff --git a/trunk/drivers/isdn/hisax/avma1_cs.c b/trunk/drivers/isdn/hisax/avma1_cs.c index 67c60e04a37b..663a0bf703b7 100644 --- a/trunk/drivers/isdn/hisax/avma1_cs.c +++ b/trunk/drivers/isdn/hisax/avma1_cs.c @@ -501,13 +501,6 @@ static int avma1cs_event(event_t event, int priority, return 0; } /* avma1cs_event */ -static struct pcmcia_device_id avma1cs_ids[] = { - PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb), - PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, avma1cs_ids); - static struct pcmcia_driver avma1cs_driver = { .owner = THIS_MODULE, .drv = { @@ -515,7 +508,6 @@ static struct pcmcia_driver avma1cs_driver = { }, .attach = avma1cs_attach, .detach = avma1cs_detach, - .id_table = avma1cs_ids, }; /*====================================================================*/ diff --git a/trunk/drivers/isdn/hisax/elsa_cs.c b/trunk/drivers/isdn/hisax/elsa_cs.c index 9146be547044..bfc013225f46 100644 --- a/trunk/drivers/isdn/hisax/elsa_cs.c +++ b/trunk/drivers/isdn/hisax/elsa_cs.c @@ -508,13 +508,6 @@ static int elsa_cs_event(event_t event, int priority, return 0; } /* elsa_cs_event */ -static struct pcmcia_device_id elsa_ids[] = { - PCMCIA_DEVICE_PROD_ID12("ELSA AG (Aachen, Germany)", "MicroLink ISDN/MC ", 0x983de2c4, 0x333ba257), - PCMCIA_DEVICE_PROD_ID12("ELSA GmbH, Aachen", "MicroLink ISDN/MC ", 0x639e5718, 0x333ba257), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, elsa_ids); - static struct pcmcia_driver elsa_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -522,7 +515,6 @@ static struct pcmcia_driver elsa_cs_driver = { }, .attach = elsa_cs_attach, .detach = elsa_cs_detach, - .id_table = elsa_ids, }; static int __init init_elsa_cs(void) diff --git a/trunk/drivers/isdn/hisax/sedlbauer_cs.c b/trunk/drivers/isdn/hisax/sedlbauer_cs.c index 058147a69576..449651241477 100644 --- a/trunk/drivers/isdn/hisax/sedlbauer_cs.c +++ b/trunk/drivers/isdn/hisax/sedlbauer_cs.c @@ -616,18 +616,6 @@ static int sedlbauer_event(event_t event, int priority, return 0; } /* sedlbauer_event */ -static struct pcmcia_device_id sedlbauer_ids[] = { - PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", "speed star II", "V 3.1", "(c) 93 - 98 cb ", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a, 0x50d4149c), - PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90), - PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce), - PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe), - PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (c) 93-95 VK", 0x81fb79f5, 0xe4e9bc12, 0xb391ab4c), - PCMCIA_DEVICE_PROD_ID12("HST High Soft Tech GmbH", "Saphir II B", 0xd79e0b84, 0x21d083ae), -/* PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", 0x81fb79f5), */ /* too generic*/ - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, sedlbauer_ids); - static struct pcmcia_driver sedlbauer_driver = { .owner = THIS_MODULE, .drv = { @@ -635,7 +623,6 @@ static struct pcmcia_driver sedlbauer_driver = { }, .attach = sedlbauer_attach, .detach = sedlbauer_detach, - .id_table = sedlbauer_ids, }; static int __init init_sedlbauer_cs(void) diff --git a/trunk/drivers/isdn/hisax/teles_cs.c b/trunk/drivers/isdn/hisax/teles_cs.c index 107376ff5b9b..63e8e20c17a8 100644 --- a/trunk/drivers/isdn/hisax/teles_cs.c +++ b/trunk/drivers/isdn/hisax/teles_cs.c @@ -489,12 +489,6 @@ static int teles_cs_event(event_t event, int priority, return 0; } /* teles_cs_event */ -static struct pcmcia_device_id teles_ids[] = { - PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, teles_ids); - static struct pcmcia_driver teles_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -502,7 +496,6 @@ static struct pcmcia_driver teles_cs_driver = { }, .attach = teles_attach, .detach = teles_detach, - .id_table = teles_ids, }; static int __init init_teles_cs(void) diff --git a/trunk/drivers/mtd/maps/Kconfig b/trunk/drivers/mtd/maps/Kconfig index 2bea2e0b06f2..8480057eadb4 100644 --- a/trunk/drivers/mtd/maps/Kconfig +++ b/trunk/drivers/mtd/maps/Kconfig @@ -607,16 +607,6 @@ config MTD_PCMCIA cards are usually around 4-16MiB in size. This does not include Compact Flash cards which are treated as IDE devices. -config MTD_PCMCIA_ANONYMOUS - bool "Use PCMCIA MTD drivers for anonymous PCMCIA cards" - depends on MTD_PCMCIA - default N - help - If this option is enabled, PCMCIA cards which do not report - anything about themselves are assumed to be MTD cards. - - If unsure, say N. - config MTD_UCLINUX tristate "Generic uClinux RAM/ROM filesystem support" depends on MTD_PARTITIONS && !MMU diff --git a/trunk/drivers/mtd/maps/pcmciamtd.c b/trunk/drivers/mtd/maps/pcmciamtd.c index c2655a817e3d..e37b4c1976e5 100644 --- a/trunk/drivers/mtd/maps/pcmciamtd.c +++ b/trunk/drivers/mtd/maps/pcmciamtd.c @@ -818,32 +818,6 @@ static dev_link_t *pcmciamtd_attach(void) return link; } -static struct pcmcia_device_id pcmciamtd_ids[] = { - PCMCIA_DEVICE_FUNC_ID(1), - PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCS-2M", "2MB SRAM", 0x547e66dc, 0x1fed36cd, 0x36eadd21), - PCMCIA_DEVICE_PROD_ID12("IBM", "2MB SRAM", 0xb569a6e5, 0x36eadd21), - PCMCIA_DEVICE_PROD_ID12("IBM", "4MB FLASH", 0xb569a6e5, 0x8bc54d2a), - PCMCIA_DEVICE_PROD_ID12("IBM", "8MB FLASH", 0xb569a6e5, 0x6df1be3e), - PCMCIA_DEVICE_PROD_ID12("Intel", "S2E20SW", 0x816cc815, 0xd14c9dcf), - PCMCIA_DEVICE_PROD_ID12("Intel", "S2E8 SW", 0x816cc815, 0xa2d7dedb), - PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-02 ", 0x40ade711, 0x145cea5c), - PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-04 ", 0x40ade711, 0x42064dda), - PCMCIA_DEVICE_PROD_ID12("intel", "SERIES2-20 ", 0x40ade711, 0x25ee5cb0), - PCMCIA_DEVICE_PROD_ID12("intel", "VALUE SERIES 100 ", 0x40ade711, 0xdf8506d8), - PCMCIA_DEVICE_PROD_ID12("KINGMAX TECHNOLOGY INC.", "SRAM 256K Bytes", 0x54d0c69c, 0xad12c29c), - PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0), - PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b), - PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad), - PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-3000", 0x05ddca47, 0xe7d67bca), - PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-4100", 0x05ddca47, 0x7bc32944), - /* the following was commented out in pcmcia-cs-3.2.7 */ - /* PCMCIA_DEVICE_PROD_ID12("RATOC Systems,Inc.", "SmartMedia ADAPTER PC Card", 0xf4a2fefe, 0x5885b2ae), */ -#ifdef CONFIG_MTD_PCMCIA_ANONYMOUS - { .match_flags = PCMCIA_DEV_ID_MATCH_ANONYMOUS, }, -#endif - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, pcmciamtd_ids); static struct pcmcia_driver pcmciamtd_driver = { .drv = { @@ -851,8 +825,7 @@ static struct pcmcia_driver pcmciamtd_driver = { }, .attach = pcmciamtd_attach, .detach = pcmciamtd_detach, - .owner = THIS_MODULE, - .id_table = pcmciamtd_ids, + .owner = THIS_MODULE }; diff --git a/trunk/drivers/net/amd8111e.c b/trunk/drivers/net/amd8111e.c index 8618012df06a..b7dd7260cafb 100755 --- a/trunk/drivers/net/amd8111e.c +++ b/trunk/drivers/net/amd8111e.c @@ -87,7 +87,6 @@ Revision History: #include #include #include -#include #include #include @@ -2007,11 +2006,12 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev, } /* Initialize DMA */ - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) < 0) { + if(!pci_dma_supported(pdev, 0xffffffff)){ printk(KERN_ERR "amd8111e: DMA not supported," "exiting.\n"); - goto err_free_reg; - } + goto err_free_reg; + } else + pdev->dma_mask = 0xffffffff; reg_addr = pci_resource_start(pdev, 0); reg_len = pci_resource_len(pdev, 0); diff --git a/trunk/drivers/net/at1700.c b/trunk/drivers/net/at1700.c index e613cc289749..b8ab2b6355eb 100644 --- a/trunk/drivers/net/at1700.c +++ b/trunk/drivers/net/at1700.c @@ -34,6 +34,10 @@ only is it difficult to detect, it also moves around in I/O space in response to inb()s from other device probes! */ +/* + 99/03/03 Allied Telesis RE1000 Plus support by T.Hagawa + 99/12/30 port to 2.3.35 by K.Takai +*/ #include #include diff --git a/trunk/drivers/net/pcmcia/3c574_cs.c b/trunk/drivers/net/pcmcia/3c574_cs.c index f0fc04bd37c4..c6e8b25f9685 100644 --- a/trunk/drivers/net/pcmcia/3c574_cs.c +++ b/trunk/drivers/net/pcmcia/3c574_cs.c @@ -1286,13 +1286,6 @@ static int el3_close(struct net_device *dev) return 0; } -static struct pcmcia_device_id tc574_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "3CCFEM556.cis"), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, tc574_ids); - static struct pcmcia_driver tc574_driver = { .owner = THIS_MODULE, .drv = { @@ -1300,7 +1293,6 @@ static struct pcmcia_driver tc574_driver = { }, .attach = tc574_attach, .detach = tc574_detach, - .id_table = tc574_ids, }; static int __init init_tc574(void) diff --git a/trunk/drivers/net/pcmcia/3c589_cs.c b/trunk/drivers/net/pcmcia/3c589_cs.c index 8fa1b5f0fb68..89abdda1d343 100644 --- a/trunk/drivers/net/pcmcia/3c589_cs.c +++ b/trunk/drivers/net/pcmcia/3c589_cs.c @@ -1057,17 +1057,6 @@ static int el3_close(struct net_device *dev) return 0; } -static struct pcmcia_device_id tc589_ids[] = { - PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0101, 0x0562), - PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77), - PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589), - PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "3CXEM556.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "3CXEM556.cis"), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, tc589_ids); - static struct pcmcia_driver tc589_driver = { .owner = THIS_MODULE, .drv = { @@ -1075,7 +1064,6 @@ static struct pcmcia_driver tc589_driver = { }, .attach = tc589_attach, .detach = tc589_detach, - .id_table = tc589_ids, }; static int __init init_tc589(void) diff --git a/trunk/drivers/net/pcmcia/axnet_cs.c b/trunk/drivers/net/pcmcia/axnet_cs.c index 23ce77b1d5b0..853b586e481a 100644 --- a/trunk/drivers/net/pcmcia/axnet_cs.c +++ b/trunk/drivers/net/pcmcia/axnet_cs.c @@ -850,34 +850,6 @@ static void block_output(struct net_device *dev, int count, outsw(nic_base + AXNET_DATAPORT, buf, count>>1); } -static struct pcmcia_device_id axnet_ids[] = { - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081), - PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301), - PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0301), - PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0303), - PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309), - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106), - PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), - PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef), - PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef), - PCMCIA_DEVICE_PROD_ID12("Billionton", "LNA-100B", 0x552ab682, 0xbc3b87e1), - PCMCIA_DEVICE_PROD_ID12("CHEETAH ETHERCARD", "EN2228", 0x00fa7bc8, 0x00e990cc), - PCMCIA_DEVICE_PROD_ID12("CNet", "CNF301", 0xbc477dde, 0x78c5f40b), - PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5), - PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e), - PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90), - PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8), - PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058), - PCMCIA_DEVICE_PROD_ID14("Network Everywhere", "AX88190", 0x820a67b6, 0xab9be5ef), - /* this is not specific enough */ - /* PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), */ - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, axnet_ids); - static struct pcmcia_driver axnet_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -885,7 +857,6 @@ static struct pcmcia_driver axnet_cs_driver = { }, .attach = axnet_attach, .detach = axnet_detach, - .id_table = axnet_ids, }; static int __init init_axnet_cs(void) diff --git a/trunk/drivers/net/pcmcia/com20020_cs.c b/trunk/drivers/net/pcmcia/com20020_cs.c index 68d58cc58d31..4294e1e3f156 100644 --- a/trunk/drivers/net/pcmcia/com20020_cs.c +++ b/trunk/drivers/net/pcmcia/com20020_cs.c @@ -483,11 +483,7 @@ static int com20020_event(event_t event, int priority, return 0; } /* com20020_event */ -static struct pcmcia_device_id com20020_ids[] = { - PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, com20020_ids); + static struct pcmcia_driver com20020_cs_driver = { .owner = THIS_MODULE, @@ -496,7 +492,6 @@ static struct pcmcia_driver com20020_cs_driver = { }, .attach = com20020_attach, .detach = com20020_detach, - .id_table = com20020_ids, }; static int __init init_com20020_cs(void) diff --git a/trunk/drivers/net/pcmcia/fmvj18x_cs.c b/trunk/drivers/net/pcmcia/fmvj18x_cs.c index 917adbbf0b5b..0424865e8094 100644 --- a/trunk/drivers/net/pcmcia/fmvj18x_cs.c +++ b/trunk/drivers/net/pcmcia/fmvj18x_cs.c @@ -435,9 +435,7 @@ static void fmvj18x_config(dev_link_t *link) pcmcia_get_status(handle, &status); if (status.CardState & CS_EVENT_3VCARD) link->conf.Vcc = 33; /* inserted in 3.3V slot */ - } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410 - || le16_to_cpu(buf[1]) == PRODID_TDK_NP9610 - || le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) { + } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410) { /* MultiFunction Card */ link->conf.ConfigBase = 0x800; link->conf.ConfigIndex = 0x47; @@ -766,31 +764,6 @@ static int fmvj18x_event(event_t event, int priority, return 0; } /* fmvj18x_event */ -static struct pcmcia_device_id fmvj18x_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004), - PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59), - PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922), - PCMCIA_DEVICE_PROD_ID12("Eiger labs,Inc.", "EPX-10BT PC Card Ethernet 10BT", 0xf47e6c66, 0x877f9922), - PCMCIA_DEVICE_PROD_ID12("FUJITSU", "LAN Card(FMV-J182)", 0x6ee5a3d8, 0x5baf31db), - PCMCIA_DEVICE_PROD_ID12("FUJITSU", "MBH10308", 0x6ee5a3d8, 0x3f04875e), - PCMCIA_DEVICE_PROD_ID12("FUJITSU TOWA", "LA501", 0xb8451188, 0x12939ba2), - PCMCIA_DEVICE_PROD_ID12("HITACHI", "HT-4840-11", 0xf4f43949, 0x773910f4), - PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310B Ver1.0 ", 0x8cef4d3a, 0x075fc7b6), - PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310 Ver1.0 ", 0x8cef4d3a, 0xbccf43e6), - PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "10BASE_T CARD R280", 0x85c10e17, 0xd9413666), - PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CD02x", 0x1eae9475, 0x8fa0ee70), - PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CF010", 0x1eae9475, 0x7683bc9a), - PCMCIA_DEVICE_PROD_ID1("CONTEC Co.,Ltd.", 0x58d8fee2), - PCMCIA_DEVICE_PROD_ID1("PCMCIA LAN MBH10304 ES", 0x2599f454), - PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da), - PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed), - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a), - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids); - static struct pcmcia_driver fmvj18x_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -798,7 +771,6 @@ static struct pcmcia_driver fmvj18x_cs_driver = { }, .attach = fmvj18x_attach, .detach = fmvj18x_detach, - .id_table = fmvj18x_ids, }; static int __init init_fmvj18x_cs(void) diff --git a/trunk/drivers/net/pcmcia/ibmtr_cs.c b/trunk/drivers/net/pcmcia/ibmtr_cs.c index cf6d073ea558..f0ff06e20410 100644 --- a/trunk/drivers/net/pcmcia/ibmtr_cs.c +++ b/trunk/drivers/net/pcmcia/ibmtr_cs.c @@ -508,13 +508,6 @@ static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase) return; } -static struct pcmcia_device_id ibmtr_ids[] = { - PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e), - PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids); - static struct pcmcia_driver ibmtr_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -522,7 +515,6 @@ static struct pcmcia_driver ibmtr_cs_driver = { }, .attach = ibmtr_attach, .detach = ibmtr_detach, - .id_table = ibmtr_ids, }; static int __init init_ibmtr_cs(void) diff --git a/trunk/drivers/net/pcmcia/nmclan_cs.c b/trunk/drivers/net/pcmcia/nmclan_cs.c index b86e7253fbfc..4603807fcafb 100644 --- a/trunk/drivers/net/pcmcia/nmclan_cs.c +++ b/trunk/drivers/net/pcmcia/nmclan_cs.c @@ -1675,13 +1675,6 @@ static void set_multicast_list(struct net_device *dev) } /* set_multicast_list */ -static struct pcmcia_device_id nmclan_ids[] = { - PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Ethernet", 0x085a850b, 0x00b2e941), - PCMCIA_DEVICE_PROD_ID12("Portable Add-ons", "Ethernet", 0x0ebf1d60, 0x00b2e941), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, nmclan_ids); - static struct pcmcia_driver nmclan_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -1689,7 +1682,6 @@ static struct pcmcia_driver nmclan_cs_driver = { }, .attach = nmclan_attach, .detach = nmclan_detach, - .id_table = nmclan_ids, }; static int __init init_nmclan_cs(void) diff --git a/trunk/drivers/net/pcmcia/pcnet_cs.c b/trunk/drivers/net/pcmcia/pcnet_cs.c index 855a45d062b1..f3ea4a9f2bf1 100644 --- a/trunk/drivers/net/pcmcia/pcnet_cs.c +++ b/trunk/drivers/net/pcmcia/pcnet_cs.c @@ -1637,208 +1637,6 @@ static int setup_shmem_window(dev_link_t *link, int start_pg, /*====================================================================*/ -static struct pcmcia_device_id pcnet_ids[] = { - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0057, 0x0021), - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0104, 0x000a), - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0xea15), - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0x3341), - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0xc0ab), - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x021b, 0x0101), - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x08a1, 0xc0ab), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "AnyCom", "Fast Ethernet ", 0x578ba6e7, 0x02d92d1e), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f), - PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c), - PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3), - PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15), - PCMCIA_MFC_DEVICE_PROD_ID123(0, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f), - PCMCIA_MFC_DEVICE_PROD_ID2(0, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302), - PCMCIA_DEVICE_MANF_CARD(0x0057, 0x1004), - PCMCIA_DEVICE_MANF_CARD(0x0104, 0x000d), - PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0075), - PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0145), - PCMCIA_DEVICE_MANF_CARD(0x0149, 0x0230), - PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530), -/* PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab), conflict with axnet_cs */ - PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110), - PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328), - PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041), - PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452), -/* PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), conflict with axnet_cs */ - PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300), - PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0307), - PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a), - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103), - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121), - PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941), - PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b), - PCMCIA_DEVICE_PROD_ID123("CNet ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b), - PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e), - PCMCIA_DEVICE_PROD_ID123("Edimax Technology Inc.", "PCMCIA", "Ethernet Card", 0x738a0019, 0x281f1c5d, 0x5e9d92c0), - PCMCIA_DEVICE_PROD_ID123("EFA ", "EFA207", "ETHERNET", 0x3d294be4, 0xeb9aab6c, 0x3ff7175b), - PCMCIA_DEVICE_PROD_ID123("I-O DATA", "PCLA", "ETHERNET", 0x1d55d7ec, 0xe4c64d34, 0x3ff7175b), - PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCLATE", "ETHERNET", 0x547e66dc, 0x6b260753, 0x3ff7175b), - PCMCIA_DEVICE_PROD_ID123("KingMax Technology Inc.", "EN10-T2", "PCMCIA Ethernet Card", 0x932b7189, 0x699e4436, 0x6f6652e0), - PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2216", 0x281f1c5d, 0xd4cd2f20, 0xb87add82), - PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2620", 0x281f1c5d, 0xd4cd2f20, 0x7d3d83a8), - PCMCIA_DEVICE_PROD_ID1("2412LAN", 0x67f236ab), - PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2212", 0xdfc6b5b2, 0xcb112a11), - PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2216-PCMCIA-ETHERNET", 0xdfc6b5b2, 0x5542bfff), - PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA100-PCM-T V2 100/10M LAN PC Card", 0xbb7fbdd7, 0xcd91cc68), - PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM", 0xbb7fbdd7, 0x5ba10d49), - PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA100-PCM V2", 0x36634a66, 0xc6d05997), - PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM_V2", 0xbb7fBdd7, 0x28e299f8), - PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA-PCM V3", 0x36634a66, 0x62241d96), - PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8010", 0x5070a7f9, 0x82f96e96), - PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8610", 0x5070a7f9, 0x86741224), - PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002", 0x93b15570, 0x75ec3efb), - PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002T", 0x93b15570, 0x461c5247), - PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8010", 0x93b15570, 0x82f96e96), - PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet", 0x578ba6e7, 0x0a9888c1), - PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet 10/100", 0x578ba6e7, 0x939fedbd), - PCMCIA_DEVICE_PROD_ID12("AROWANA", "PCMCIA Ethernet LAN Card", 0x313adbc8, 0x08d9f190), - PCMCIA_DEVICE_PROD_ID12("ASANTE", "FriendlyNet PC Card", 0x3a7ade0f, 0x41c64504), - PCMCIA_DEVICE_PROD_ID12("Billionton", "LNT-10TB", 0x552ab682, 0xeeb1ba6a), - PCMCIA_DEVICE_PROD_ID12("CF", "10Base-Ethernet", 0x44ebf863, 0x93ae4d79), - PCMCIA_DEVICE_PROD_ID12("CNet", "CN40BC Ethernet", 0xbc477dde, 0xfba775a7), - PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "BASEline PCMCIA 10 MBit Ethernetadapter", 0xfa2e424d, 0xe9190d8a), - PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9), - PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), - PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), - PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), - PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), - PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa), - PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9), - PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2), - PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2), - PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04), - PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d), - PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814), - PCMCIA_DEVICE_PROD_ID12("DataTrek.", "NetCard ", 0x5cd66d9d, 0x84697ce0), - PCMCIA_DEVICE_PROD_ID12("Dayna Communications, Inc.", "CommuniCard E", 0x0c629325, 0xb4e7dbaf), - PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100", 0x697403d8, 0xe160b995), - PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100 Dongless", 0x697403d8, 0xa6d3b233), - PCMCIA_DEVICE_PROD_ID12("DIGITAL", "DEPCM-XX", 0x69616cb3, 0xe600e76e), - PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-650", 0x1a424a1c, 0xf28c8398), - PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660", 0x1a424a1c, 0xd9a1d05b), - PCMCIA_DEVICE_PROD_ID12("D-Link", "DFE-650", 0x1a424a1c, 0x0f0073f9), - PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 PC Card", 0x725b842d, 0xf1efee84), - PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 Port Attached PC Card", 0x725b842d, 0x2db1f8e9), - PCMCIA_DEVICE_PROD_ID12("Dynalink", "L10BC", 0x55632fd5, 0xdc65f2b1), - PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10BC", 0x6a26d1cf, 0xdc65f2b1), - PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10C", 0x6a26d1cf, 0xc4f84efb), - PCMCIA_DEVICE_PROD_ID12("E-CARD", "E-CARD", 0x6701da11, 0x6701da11), - PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet 10BaseT card", 0x53c864c6, 0xedd059f6), - PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet Combo card", 0x53c864c6, 0x929c486c), - PCMCIA_DEVICE_PROD_ID12("Ethernet", "Adapter", 0x00b2e941, 0x4b0d829e), - PCMCIA_DEVICE_PROD_ID12("Ethernet Adapter", "E2000 PCMCIA Ethernet", 0x96767301, 0x71fbbc61), - PCMCIA_DEVICE_PROD_ID12("Ethernet PCMCIA adapter", "EP-210", 0x8dd86181, 0xf2b52517), - PCMCIA_DEVICE_PROD_ID12("Fast Ethernet", "Adapter", 0xb4be14e3, 0x4b0d829e), - PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2000", 0x2a151fac, 0xf00555cb), - PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2220", 0x2a151fac, 0xc1b7e327), - PCMCIA_DEVICE_PROD_ID12("GVC", "NIC-2000p", 0x76e171bd, 0x6eb1c947), - PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "Ethernet", 0xe3736c88, 0x00b2e941), - PCMCIA_DEVICE_PROD_ID12("IC-CARD", "IC-CARD", 0x60cb09a6, 0x60cb09a6), - PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b), - PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0), - PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956), - PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64), - PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5), - PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3), - PCMCIA_DEVICE_PROD_ID12("Kingston Technology Corp.", "EtheRx PC Card Ethernet Adapter", 0x313c7be3, 0x0afb54a2), - PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-10/100CD", 0x1b7827b2, 0xcda71d1c), - PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDF", 0x1b7827b2, 0xfec71e40), - PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDL/T", 0x1b7827b2, 0x79fba4f7), - PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDS", 0x1b7827b2, 0x931afaab), - PCMCIA_DEVICE_PROD_ID12("Linksys", "Combo PCMCIA EthernetCard (EC2T)", 0x0733cc81, 0x32ee8c78), - PCMCIA_DEVICE_PROD_ID12("LINKSYS", "E-CARD", 0xf7cb0b07, 0x6701da11), - PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 Integrated PC Card (PCM100)", 0x0733cc81, 0x453c3f9d), - PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100)", 0x0733cc81, 0x66c5a389), - PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9), - PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline ", 0x0733cc81, 0x5e07cfa0), - PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737), - PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922), - PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0), - PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578), - PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307), - PCMCIA_DEVICE_PROD_ID12("Matsushita Electric Industrial Co.,LTD.", "CF-VEL211", 0x44445376, 0x8ded41d4), - PCMCIA_DEVICE_PROD_ID12("MAXTECH", "PCN2000", 0x78d64bc0, 0xca0ca4b8), - PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-T", 0x481e0094, 0xa2eb0cf3), - PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-TX", 0x481e0094, 0x41a6916c), - PCMCIA_DEVICE_PROD_ID12("Microcom C.E.", "Travel Card LAN 10/100", 0x4b91cec7, 0xe70220d6), - PCMCIA_DEVICE_PROD_ID12("Microdyne", "NE4200", 0x2e6da59b, 0x0478e472), - PCMCIA_DEVICE_PROD_ID12("MIDORI ELEC.", "LT-PCMT", 0x648d55c1, 0xbde526c7), - PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover 4100", 0x36e1191f, 0x60c229b9), - PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8), - PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76), - PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e), - PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875), - PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f), - PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet", 0x281f1c5d, 0x00b2e941), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET", 0x281f1c5d, 0x3ff7175b), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet 10BaseT Card", 0x281f1c5d, 0x4de2f6c8), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Card", 0x281f1c5d, 0x5e9d92c0), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Combo card", 0x281f1c5d, 0x929c486c), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET V1.0", 0x281f1c5d, 0x4d8817c8), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEthernet", 0x281f1c5d, 0xfe871eeb), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast-Ethernet", 0x281f1c5d, 0x45f1f3b4), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FAST ETHERNET CARD", 0x281f1c5d, 0xec5dbca7), - PCMCIA_DEVICE_PROD_ID12("PCMCIA LAN", "Ethernet", 0x7500e246, 0x00b2e941), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "LNT-10TN", 0x281f1c5d, 0xe707f641), - PCMCIA_DEVICE_PROD_ID12("PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "UE2212", 0x281f1c5d, 0xbf17199b), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", " Ethernet NE2000 Compatible", 0x281f1c5d, 0x42d5d7e1), - PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10baseT 3.3V", 0xebf91155, 0x30074c80), - PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50), - PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110), - PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941), - PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df), - PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0), - PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd), - PCMCIA_DEVICE_PROD_ID12("RPTI LTD.", "EP400", 0xc53ac515, 0x81e39388), - PCMCIA_DEVICE_PROD_ID12("SCM", "Ethernet Combo card", 0xbdc3b102, 0x929c486c), - PCMCIA_DEVICE_PROD_ID12("Seiko Epson Corp.", "Ethernet", 0x09928730, 0x00b2e941), - PCMCIA_DEVICE_PROD_ID12("SMC", "EZCard-10-PCMCIA", 0xc4f8b18b, 0xfb21d265), - PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision D", 0xc70a4760, 0x2ade483e), - PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision E", 0xc70a4760, 0x5dd978a8), - PCMCIA_DEVICE_PROD_ID12("TDK", "LAK-CD031 for PCMCIA", 0x1eae9475, 0x0ed386fa), - PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE450T", 0x466b05f0, 0x8b74bc4f), - PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE550T", 0x466b05f0, 0x33c8db2a), - PCMCIA_DEVICE_PROD_ID13("Hypertec", "EP401", 0x8787bec7, 0xf6e4a31e), - PCMCIA_DEVICE_PROD_ID13("KingMax Technology Inc.", "Ethernet Card", 0x932b7189, 0x5e9d92c0), - PCMCIA_DEVICE_PROD_ID13("LONGSHINE", "EP401", 0xf866b0b0, 0xf6e4a31e), - PCMCIA_DEVICE_PROD_ID13("Xircom", "CFE-10", 0x2e3ee845, 0x22a49f89), - PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360), - PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de), - PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f), - PCMCIA_DEVICE_PROD_ID1("IC-CARD", 0x60cb09a6), - PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a), - PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078), - /* too generic! */ - /* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */ - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"), - PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "DP83903.cis"), - PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "LA-PCM.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "PE520.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "NE2K.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, pcnet_ids); - static struct pcmcia_driver pcnet_driver = { .drv = { .name = "pcnet_cs", @@ -1846,7 +1644,6 @@ static struct pcmcia_driver pcnet_driver = { .attach = pcnet_attach, .detach = pcnet_detach, .owner = THIS_MODULE, - .id_table = pcnet_ids, }; static int __init init_pcnet_cs(void) diff --git a/trunk/drivers/net/pcmcia/smc91c92_cs.c b/trunk/drivers/net/pcmcia/smc91c92_cs.c index bc01c88c6709..8a5e52c40e46 100644 --- a/trunk/drivers/net/pcmcia/smc91c92_cs.c +++ b/trunk/drivers/net/pcmcia/smc91c92_cs.c @@ -2327,38 +2327,6 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) return rc; } -static struct pcmcia_device_id smc91c92_ids[] = { - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0109, 0x0501), - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0140, 0x000a), - PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63), - PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63), - PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef), - PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), - PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x016c, 0x0020), - PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0023), - PCMCIA_DEVICE_PROD_ID123("BASICS by New Media Corporation", "Ethernet", "SMC91C94", 0x23c78a9d, 0x00b2e941, 0xcef397fb), - PCMCIA_DEVICE_PROD_ID12("ARGOSY", "Fast Ethernet PCCard", 0x78f308dc, 0xdcea68bc), - PCMCIA_DEVICE_PROD_ID12("dit Co., Ltd.", "PC Card-10/100BTX", 0xe59365c8, 0x6a2161d1), - PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L100C", 0x6a26d1cf, 0xc16ce9c5), - PCMCIA_DEVICE_PROD_ID12("Farallon", "Farallon Enet", 0x58d93fc4, 0x244734e9), - PCMCIA_DEVICE_PROD_ID12("Megahertz", "CC10BT/2", 0x33234748, 0x3c95b953), - PCMCIA_DEVICE_PROD_ID12("MELCO/SMC", "LPC-TX", 0xa2cd8e6d, 0x42da662a), - PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), - PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), - PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast Ethernet PCCard", 0x281f1c5d, 0xdcea68bc), - PCMCIA_DEVICE_PROD_ID12("Psion", "10Mb Ethernet", 0x4ef00b21, 0x844be9e9), - PCMCIA_DEVICE_PROD_ID12("SMC", "EtherEZ Ethernet 8020", 0xc4f8b18b, 0x4a0eeb2d), - /* These conflict with other cards! */ - /* PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0100), */ - /* PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), */ - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, smc91c92_ids); - static struct pcmcia_driver smc91c92_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -2366,7 +2334,6 @@ static struct pcmcia_driver smc91c92_cs_driver = { }, .attach = smc91c92_attach, .detach = smc91c92_detach, - .id_table = smc91c92_ids, }; static int __init init_smc91c92_cs(void) diff --git a/trunk/drivers/net/pcmcia/xirc2ps_cs.c b/trunk/drivers/net/pcmcia/xirc2ps_cs.c index 0cd225e1595c..58177d67ea12 100644 --- a/trunk/drivers/net/pcmcia/xirc2ps_cs.c +++ b/trunk/drivers/net/pcmcia/xirc2ps_cs.c @@ -1983,33 +1983,6 @@ do_stop(struct net_device *dev) return 0; } -static struct pcmcia_device_id xirc2ps_ids[] = { - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0089, 0x110a), - PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0138, 0x110a), - PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea), - PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM33", 0x2e3ee845, 0x80609023), - PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a), - PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29), - PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719), - PCMCIA_PFC_DEVICE_PROD_ID12(0, "Xircom", "CreditCard Ethernet", 0x2e3ee845, 0xc0e778c2), - PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x010a), - PCMCIA_DEVICE_PROD_ID13("Toshiba Information Systems", "TPCENET", 0x1b3b94fe, 0xf381c1a2), - PCMCIA_DEVICE_PROD_ID13("Xircom", "CE3-10/100", 0x2e3ee845, 0x0ec0ac37), - PCMCIA_DEVICE_PROD_ID13("Xircom", "PS-CE2-10", 0x2e3ee845, 0x947d9073), - PCMCIA_DEVICE_PROD_ID13("Xircom", "R2E-100BTX", 0x2e3ee845, 0x2464a6e3), - PCMCIA_DEVICE_PROD_ID13("Xircom", "RE-10", 0x2e3ee845, 0x3e08d609), - PCMCIA_DEVICE_PROD_ID13("Xircom", "XE2000", 0x2e3ee845, 0xf7188e46), - PCMCIA_DEVICE_PROD_ID12("Compaq", "Ethernet LAN Card", 0x54f7c49c, 0x9fd2f0a2), - PCMCIA_DEVICE_PROD_ID12("Compaq", "Netelligent 10/100 PC Card", 0x54f7c49c, 0xefe96769), - PCMCIA_DEVICE_PROD_ID12("Intel", "EtherExpress(TM) PRO/100 PC Card Mobile Adapter16", 0x816cc815, 0x174397db), - PCMCIA_DEVICE_PROD_ID12("Toshiba", "10/100 Ethernet PC Card", 0x44a09d9c, 0xb44deecf), - /* also matches CFE-10 cards! */ - /* PCMCIA_DEVICE_MANF_CARD(0x0105, 0x010a), */ - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, xirc2ps_ids); - - static struct pcmcia_driver xirc2ps_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -2017,7 +1990,6 @@ static struct pcmcia_driver xirc2ps_cs_driver = { }, .attach = xirc2ps_attach, .detach = xirc2ps_detach, - .id_table = xirc2ps_ids, }; static int __init diff --git a/trunk/drivers/net/skge.c b/trunk/drivers/net/skge.c index 3dbb1cb09ed8..30e8d589d167 100644 --- a/trunk/drivers/net/skge.c +++ b/trunk/drivers/net/skge.c @@ -7,7 +7,7 @@ * of the original driver such as link fail-over and link management because * those should be done at higher levels. * - * Copyright (C) 2004, 2005 Stephen Hemminger + * Copyright (C) 2004, Stephen Hemminger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,20 +42,19 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "0.7" +#define DRV_VERSION "0.6" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 #define DEFAULT_RX_RING_SIZE 512 #define MAX_TX_RING_SIZE 1024 #define MAX_RX_RING_SIZE 4096 -#define RX_COPY_THRESHOLD 128 -#define RX_BUF_SIZE 1536 #define PHY_RETRIES 1000 #define ETH_JUMBO_MTU 9000 #define TX_WATCHDOG (5 * HZ) #define NAPI_WEIGHT 64 #define BLINK_HZ (HZ/4) +#define LINK_POLL_HZ (HZ/10) MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); MODULE_AUTHOR("Stephen Hemminger "); @@ -71,17 +70,28 @@ module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); static const struct pci_device_id skge_id_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940) }, - { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) }, - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ - { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) }, - { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032) }, - { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064) }, + { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_SYSKONNECT, 0x9E00, /* SK-9Exx */ + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_MARVELL, 0x4320, /* Gigabit Ethernet Controller */ + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_MARVELL, 0x5005, /* Marvell (11ab), Belkin */ + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064, + PCI_ANY_ID, PCI_ANY_ID }, { 0 } }; MODULE_DEVICE_TABLE(pci, skge_id_table); @@ -89,22 +99,19 @@ MODULE_DEVICE_TABLE(pci, skge_id_table); static int skge_up(struct net_device *dev); static int skge_down(struct net_device *dev); static void skge_tx_clean(struct skge_port *skge); -static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); -static void gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); +static void skge_xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); +static void skge_gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); static void genesis_get_stats(struct skge_port *skge, u64 *data); static void yukon_get_stats(struct skge_port *skge, u64 *data); static void yukon_init(struct skge_hw *hw, int port); static void yukon_reset(struct skge_hw *hw, int port); static void genesis_mac_init(struct skge_hw *hw, int port); static void genesis_reset(struct skge_hw *hw, int port); -static void genesis_link_up(struct skge_port *skge); -/* Avoid conditionals by using array */ static const int txqaddr[] = { Q_XA1, Q_XA2 }; static const int rxqaddr[] = { Q_R1, Q_R2 }; static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F }; static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F }; -static const u32 portirqmask[] = { IS_PORT_1, IS_PORT_2 }; /* Don't need to look at whole 16K. * last interesting register is descriptor poll timer. @@ -147,7 +154,7 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs, static int wol_supported(const struct skge_hw *hw) { return !((hw->chip_id == CHIP_ID_GENESIS || - (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0))); + (hw->chip_id == CHIP_ID_YUKON && chip_rev(hw) == 0))); } static void skge_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) @@ -163,7 +170,7 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; - if (wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) + if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) return -EOPNOTSUPP; if (wol->wolopts == WAKE_MAGIC && !wol_supported(hw)) @@ -183,36 +190,6 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) return 0; } -/* Determine supported/adverised modes based on hardware. - * Note: ethtoool ADVERTISED_xxx == SUPPORTED_xxx - */ -static u32 skge_supported_modes(const struct skge_hw *hw) -{ - u32 supported; - - if (iscopper(hw)) { - supported = SUPPORTED_10baseT_Half - | SUPPORTED_10baseT_Full - | SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full - | SUPPORTED_1000baseT_Half - | SUPPORTED_1000baseT_Full - | SUPPORTED_Autoneg| SUPPORTED_TP; - - if (hw->chip_id == CHIP_ID_GENESIS) - supported &= ~(SUPPORTED_10baseT_Half - | SUPPORTED_10baseT_Full - | SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full); - - else if (hw->chip_id == CHIP_ID_YUKON) - supported &= ~SUPPORTED_1000baseT_Half; - } else - supported = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE - | SUPPORTED_Autoneg; - - return supported; -} static int skge_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) @@ -221,13 +198,38 @@ static int skge_get_settings(struct net_device *dev, struct skge_hw *hw = skge->hw; ecmd->transceiver = XCVR_INTERNAL; - ecmd->supported = skge_supported_modes(hw); if (iscopper(hw)) { + if (hw->chip_id == CHIP_ID_GENESIS) + ecmd->supported = SUPPORTED_1000baseT_Full + | SUPPORTED_1000baseT_Half + | SUPPORTED_Autoneg | SUPPORTED_TP; + else { + ecmd->supported = SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full + | SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full + | SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full + | SUPPORTED_Autoneg| SUPPORTED_TP; + + if (hw->chip_id == CHIP_ID_YUKON) + ecmd->supported &= ~SUPPORTED_1000baseT_Half; + + else if (hw->chip_id == CHIP_ID_YUKON_FE) + ecmd->supported &= ~(SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full); + } + ecmd->port = PORT_TP; ecmd->phy_address = hw->phy_addr; - } else + } else { + ecmd->supported = SUPPORTED_1000baseT_Full + | SUPPORTED_FIBRE + | SUPPORTED_Autoneg; + ecmd->port = PORT_FIBRE; + } ecmd->advertising = skge->advertising; ecmd->autoneg = skge->autoneg; @@ -236,57 +238,65 @@ static int skge_get_settings(struct net_device *dev, return 0; } +static u32 skge_modes(const struct skge_hw *hw) +{ + u32 modes = ADVERTISED_Autoneg + | ADVERTISED_1000baseT_Full | ADVERTISED_1000baseT_Half + | ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half + | ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half; + + if (iscopper(hw)) { + modes |= ADVERTISED_TP; + switch(hw->chip_id) { + case CHIP_ID_GENESIS: + modes &= ~(ADVERTISED_100baseT_Full + | ADVERTISED_100baseT_Half + | ADVERTISED_10baseT_Full + | ADVERTISED_10baseT_Half); + break; + + case CHIP_ID_YUKON: + modes &= ~ADVERTISED_1000baseT_Half; + break; + + case CHIP_ID_YUKON_FE: + modes &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full); + break; + } + } else { + modes |= ADVERTISED_FIBRE; + modes &= ~ADVERTISED_1000baseT_Half; + } + return modes; +} + static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct skge_port *skge = netdev_priv(dev); const struct skge_hw *hw = skge->hw; - u32 supported = skge_supported_modes(hw); if (ecmd->autoneg == AUTONEG_ENABLE) { - ecmd->advertising = supported; - skge->duplex = -1; - skge->speed = -1; + if (ecmd->advertising & skge_modes(hw)) + return -EINVAL; } else { - u32 setting; - switch(ecmd->speed) { case SPEED_1000: - if (ecmd->duplex == DUPLEX_FULL) - setting = SUPPORTED_1000baseT_Full; - else if (ecmd->duplex == DUPLEX_HALF) - setting = SUPPORTED_1000baseT_Half; - else + if (hw->chip_id == CHIP_ID_YUKON_FE) return -EINVAL; break; case SPEED_100: - if (ecmd->duplex == DUPLEX_FULL) - setting = SUPPORTED_100baseT_Full; - else if (ecmd->duplex == DUPLEX_HALF) - setting = SUPPORTED_100baseT_Half; - else - return -EINVAL; - break; - case SPEED_10: - if (ecmd->duplex == DUPLEX_FULL) - setting = SUPPORTED_10baseT_Full; - else if (ecmd->duplex == DUPLEX_HALF) - setting = SUPPORTED_10baseT_Half; - else + if (iscopper(hw) || hw->chip_id == CHIP_ID_GENESIS) return -EINVAL; break; default: return -EINVAL; } - - if ((setting & supported) == 0) - return -EINVAL; - - skge->speed = ecmd->speed; - skge->duplex = ecmd->duplex; } skge->autoneg = ecmd->autoneg; + skge->speed = ecmd->speed; + skge->duplex = ecmd->duplex; skge->advertising = ecmd->advertising; if (netif_running(dev)) { @@ -383,7 +393,7 @@ static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data) { int i; - switch (stringset) { + switch(stringset) { case ETH_SS_STATS: for (i = 0; i < ARRAY_SIZE(skge_stats); i++) memcpy(data + i * ETH_GSTRING_LEN, @@ -501,6 +511,14 @@ static int skge_set_rx_csum(struct net_device *dev, u32 data) return 0; } +/* Only Yukon II supports TSO (not implemented yet) */ +static int skge_set_tso(struct net_device *dev, u32 data) +{ + if (data) + return -EOPNOTSUPP; + return 0; +} + static void skge_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *ecmd) { @@ -522,9 +540,9 @@ static int skge_set_pauseparam(struct net_device *dev, skge->autoneg = ecmd->autoneg; if (ecmd->rx_pause && ecmd->tx_pause) skge->flow_control = FLOW_MODE_SYMMETRIC; - else if (ecmd->rx_pause && !ecmd->tx_pause) + else if(ecmd->rx_pause && !ecmd->tx_pause) skge->flow_control = FLOW_MODE_REM_SEND; - else if (!ecmd->rx_pause && ecmd->tx_pause) + else if(!ecmd->rx_pause && ecmd->tx_pause) skge->flow_control = FLOW_MODE_LOC_SEND; else skge->flow_control = FLOW_MODE_NONE; @@ -541,6 +559,8 @@ static inline u32 hwkhz(const struct skge_hw *hw) { if (hw->chip_id == CHIP_ID_GENESIS) return 53215; /* or: 53.125 MHz */ + else if (hw->chip_id == CHIP_ID_YUKON_EC) + return 125000; /* or: 125.000 MHz */ else return 78215; /* or: 78.125 MHz */ } @@ -623,18 +643,30 @@ static int skge_set_coalesce(struct net_device *dev, static void skge_led_on(struct skge_hw *hw, int port) { if (hw->chip_id == CHIP_ID_GENESIS) { - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); + skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_ON); skge_write8(hw, B0_LED, LED_STAT_ON); - skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); - skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); + skge_write8(hw, SKGEMAC_REG(port, RX_LED_TST), LED_T_ON); + skge_write32(hw, SKGEMAC_REG(port, RX_LED_VAL), 100); + skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_START); - /* For Broadcom Phy only */ - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); + switch (hw->phy_type) { + case SK_PHY_BCOM: + skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, + PHY_B_PEC_LED_ON); + break; + case SK_PHY_LONE: + skge_xm_phy_write(hw, port, PHY_LONE_LED_CFG, + 0x0800); + break; + default: + skge_write8(hw, SKGEMAC_REG(port, TX_LED_TST), LED_T_ON); + skge_write32(hw, SKGEMAC_REG(port, TX_LED_VAL), 100); + skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_START); + } } else { - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, + skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); + skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER, PHY_M_LED_MO_DUP(MO_LED_ON) | PHY_M_LED_MO_10(MO_LED_ON) | PHY_M_LED_MO_100(MO_LED_ON) | @@ -646,17 +678,28 @@ static void skge_led_on(struct skge_hw *hw, int port) static void skge_led_off(struct skge_hw *hw, int port) { if (hw->chip_id == CHIP_ID_GENESIS) { - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); + skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_OFF); skge_write8(hw, B0_LED, LED_STAT_OFF); - skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); + skge_write32(hw, SKGEMAC_REG(port, RX_LED_VAL), 0); + skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_T_OFF); - /* Broadcom only */ - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); + switch (hw->phy_type) { + case SK_PHY_BCOM: + skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, + PHY_B_PEC_LED_OFF); + break; + case SK_PHY_LONE: + skge_xm_phy_write(hw, port, PHY_LONE_LED_CFG, + PHY_L_LC_LEDT); + break; + default: + skge_write32(hw, SKGEMAC_REG(port, TX_LED_VAL), 0); + skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_T_OFF); + } } else { - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, + skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); + skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER, PHY_M_LED_MO_DUP(MO_LED_OFF) | PHY_M_LED_MO_10(MO_LED_OFF) | PHY_M_LED_MO_100(MO_LED_OFF) | @@ -687,7 +730,7 @@ static int skge_phys_id(struct net_device *dev, u32 data) { struct skge_port *skge = netdev_priv(dev); - if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) + if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); /* start blinking */ @@ -720,6 +763,8 @@ static struct ethtool_ops skge_ethtool_ops = { .set_pauseparam = skge_set_pauseparam, .get_coalesce = skge_get_coalesce, .set_coalesce = skge_set_coalesce, + .get_tso = ethtool_op_get_tso, + .set_tso = skge_set_tso, .get_sg = ethtool_op_get_sg, .set_sg = skge_set_sg, .get_tx_csum = ethtool_op_get_tx_csum, @@ -748,7 +793,6 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base) for (i = 0, e = ring->start, d = vaddr; i < ring->count; i++, e++, d++) { e->desc = d; - e->skb = NULL; if (i == ring->count - 1) { e->next = ring->start; d->next_offset = base; @@ -762,23 +806,24 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base) return 0; } -static struct sk_buff *skge_rx_alloc(struct net_device *dev, unsigned int size) +/* Setup buffer for receiving */ +static inline int skge_rx_alloc(struct skge_port *skge, + struct skge_element *e) { - struct sk_buff *skb = dev_alloc_skb(size); + unsigned long bufsize = skge->netdev->mtu + ETH_HLEN; /* VLAN? */ + struct skge_rx_desc *rd = e->desc; + struct sk_buff *skb; + u64 map; - if (likely(skb)) { - skb->dev = dev; - skb_reserve(skb, NET_IP_ALIGN); + skb = dev_alloc_skb(bufsize + NET_IP_ALIGN); + if (unlikely(!skb)) { + printk(KERN_DEBUG PFX "%s: out of memory for receive\n", + skge->netdev->name); + return -ENOMEM; } - return skb; -} -/* Allocate and setup a new buffer for receiving */ -static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, - struct sk_buff *skb, unsigned int bufsize) -{ - struct skge_rx_desc *rd = e->desc; - u64 map; + skb->dev = skge->netdev; + skb_reserve(skb, NET_IP_ALIGN); map = pci_map_single(skge->hw->pdev, skb->data, bufsize, PCI_DMA_FROMDEVICE); @@ -796,69 +841,55 @@ static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize; pci_unmap_addr_set(e, mapaddr, map); pci_unmap_len_set(e, maplen, bufsize); + return 0; } -/* Resume receiving using existing skb, - * Note: DMA address is not changed by chip. - * MTU not changed while receiver active. - */ -static void skge_rx_reuse(struct skge_element *e, unsigned int size) -{ - struct skge_rx_desc *rd = e->desc; - - rd->csum2 = 0; - rd->csum2_start = ETH_HLEN; - - wmb(); - - rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | size; -} - - -/* Free all buffers in receive ring, assumes receiver stopped */ +/* Free all unused buffers in receive ring, assumes receiver stopped */ static void skge_rx_clean(struct skge_port *skge) { struct skge_hw *hw = skge->hw; struct skge_ring *ring = &skge->rx_ring; struct skge_element *e; - e = ring->start; - do { + for (e = ring->to_clean; e != ring->to_use; e = e->next) { struct skge_rx_desc *rd = e->desc; rd->control = 0; - if (e->skb) { - pci_unmap_single(hw->pdev, - pci_unmap_addr(e, mapaddr), - pci_unmap_len(e, maplen), - PCI_DMA_FROMDEVICE); - dev_kfree_skb(e->skb); - e->skb = NULL; - } - } while ((e = e->next) != ring->start); -} + pci_unmap_single(hw->pdev, + pci_unmap_addr(e, mapaddr), + pci_unmap_len(e, maplen), + PCI_DMA_FROMDEVICE); + dev_kfree_skb(e->skb); + e->skb = NULL; + } + ring->to_clean = e; +} /* Allocate buffers for receive ring - * For receive: to_clean is next received frame. + * For receive: to_use is refill location + * to_clean is next received frame. + * + * if (to_use == to_clean) + * then ring all frames in ring need buffers + * if (to_use->next == to_clean) + * then ring all frames in ring have buffers */ static int skge_rx_fill(struct skge_port *skge) { struct skge_ring *ring = &skge->rx_ring; struct skge_element *e; - unsigned int bufsize = skge->rx_buf_size; - - e = ring->start; - do { - struct sk_buff *skb = skge_rx_alloc(skge->netdev, bufsize); + int ret = 0; - if (!skb) - return -ENOMEM; + for (e = ring->to_use; e->next != ring->to_clean; e = e->next) { + if (skge_rx_alloc(skge, e)) { + ret = 1; + break; + } - skge_rx_setup(skge, e, skb, bufsize); - } while ( (e = e->next) != ring->start); + } + ring->to_use = e; - ring->to_clean = ring->start; - return 0; + return ret; } static void skge_link_up(struct skge_port *skge) @@ -888,50 +919,50 @@ static void skge_link_down(struct skge_port *skge) printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name); } -static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg) +static u16 skge_xm_phy_read(struct skge_hw *hw, int port, u16 reg) { int i; u16 v; - xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); - v = xm_read16(hw, port, XM_PHY_DATA); + skge_xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); + v = skge_xm_read16(hw, port, XM_PHY_DATA); + if (hw->phy_type != SK_PHY_XMAC) { + for (i = 0; i < PHY_RETRIES; i++) { + udelay(1); + if (skge_xm_read16(hw, port, XM_MMU_CMD) + & XM_MMU_PHY_RDY) + goto ready; + } - /* Need to wait for external PHY */ - for (i = 0; i < PHY_RETRIES; i++) { - udelay(1); - if (xm_read16(hw, port, XM_MMU_CMD) - & XM_MMU_PHY_RDY) - goto ready; + printk(KERN_WARNING PFX "%s: phy read timed out\n", + hw->dev[port]->name); + return 0; + ready: + v = skge_xm_read16(hw, port, XM_PHY_DATA); } - printk(KERN_WARNING PFX "%s: phy read timed out\n", - hw->dev[port]->name); - return 0; - ready: - v = xm_read16(hw, port, XM_PHY_DATA); - return v; } -static void xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) +static void skge_xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) { int i; - xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); + skge_xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); for (i = 0; i < PHY_RETRIES; i++) { - if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY)) + if (!(skge_xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY)) goto ready; - udelay(1); + cpu_relax(); } printk(KERN_WARNING PFX "%s: phy write failed to come ready\n", hw->dev[port]->name); ready: - xm_write16(hw, port, XM_PHY_DATA, val); + skge_xm_write16(hw, port, XM_PHY_DATA, val); for (i = 0; i < PHY_RETRIES; i++) { udelay(1); - if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY)) + if (!(skge_xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY)) return; } printk(KERN_WARNING PFX "%s: phy write timed out\n", @@ -968,112 +999,34 @@ static void genesis_init(struct skge_hw *hw) static void genesis_reset(struct skge_hw *hw, int port) { - const u8 zero[8] = { 0 }; + int i; + u64 zero = 0; /* reset the statistics module */ - xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); - xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */ - xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */ - xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */ - xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */ + skge_xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); + skge_xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */ + skge_xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */ + skge_xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */ + skge_xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */ - /* disable Broadcom PHY IRQ */ - xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff); + /* disable all PHY IRQs */ + if (hw->phy_type == SK_PHY_BCOM) + skge_xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff); - xm_outhash(hw, port, XM_HSM, zero); + skge_xm_outhash(hw, port, XM_HSM, (u8 *) &zero); + for (i = 0; i < 15; i++) + skge_xm_outaddr(hw, port, XM_EXM(i), (u8 *) &zero); + skge_xm_outhash(hw, port, XM_SRC_CHK, (u8 *) &zero); } -/* Convert mode to MII values */ -static const u16 phy_pause_map[] = { - [FLOW_MODE_NONE] = 0, - [FLOW_MODE_LOC_SEND] = PHY_AN_PAUSE_ASYM, - [FLOW_MODE_SYMMETRIC] = PHY_AN_PAUSE_CAP, - [FLOW_MODE_REM_SEND] = PHY_AN_PAUSE_CAP | PHY_AN_PAUSE_ASYM, -}; - - -/* Check status of Broadcom phy link */ -static void bcom_check_link(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - u16 status; - - /* read twice because of latch */ - (void) xm_phy_read(hw, port, PHY_BCOM_STAT); - status = xm_phy_read(hw, port, PHY_BCOM_STAT); - - pr_debug("bcom_check_link status=0x%x\n", status); - - if ((status & PHY_ST_LSYNC) == 0) { - u16 cmd = xm_read16(hw, port, XM_MMU_CMD); - cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); - xm_write16(hw, port, XM_MMU_CMD, cmd); - /* dummy read to ensure writing */ - (void) xm_read16(hw, port, XM_MMU_CMD); - - if (netif_carrier_ok(dev)) - skge_link_down(skge); - } else { - if (skge->autoneg == AUTONEG_ENABLE && - (status & PHY_ST_AN_OVER)) { - u16 lpa = xm_phy_read(hw, port, PHY_BCOM_AUNE_LP); - u16 aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT); - - if (lpa & PHY_B_AN_RF) { - printk(KERN_NOTICE PFX "%s: remote fault\n", - dev->name); - return; - } - - /* Check Duplex mismatch */ - switch(aux & PHY_B_AS_AN_RES_MSK) { - case PHY_B_RES_1000FD: - skge->duplex = DUPLEX_FULL; - break; - case PHY_B_RES_1000HD: - skge->duplex = DUPLEX_HALF; - break; - default: - printk(KERN_NOTICE PFX "%s: duplex mismatch\n", - dev->name); - return; - } - - - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - switch (aux & PHY_B_AS_PAUSE_MSK) { - case PHY_B_AS_PAUSE_MSK: - skge->flow_control = FLOW_MODE_SYMMETRIC; - break; - case PHY_B_AS_PRR: - skge->flow_control = FLOW_MODE_REM_SEND; - break; - case PHY_B_AS_PRT: - skge->flow_control = FLOW_MODE_LOC_SEND; - break; - default: - skge->flow_control = FLOW_MODE_NONE; - } - - skge->speed = SPEED_1000; - } - - if (!netif_carrier_ok(dev)) - genesis_link_up(skge); - } -} - -/* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional - * Phy on for 100 or 10Mbit operation - */ -static void bcom_phy_init(struct skge_port *skge, int jumbo) +static void genesis_mac_init(struct skge_hw *hw, int port) { - struct skge_hw *hw = skge->hw; - int port = skge->port; + struct skge_port *skge = netdev_priv(hw->dev[port]); int i; - u16 id1, r, ext, ctl; + u32 r; + u16 id1; + u16 ctrl1, ctrl2, ctrl3, ctrl4, ctrl5; /* magic workaround patterns for Broadcom */ static const struct { @@ -1089,120 +1042,16 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo) { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 }, }; - pr_debug("bcom_phy_init\n"); - - /* read Id from external PHY (all have the same address) */ - id1 = xm_phy_read(hw, port, PHY_XMAC_ID1); - - /* Optimize MDIO transfer by suppressing preamble. */ - r = xm_read16(hw, port, XM_MMU_CMD); - r |= XM_MMU_NO_PRE; - xm_write16(hw, port, XM_MMU_CMD,r); - - switch(id1) { - case PHY_BCOM_ID1_C0: - /* - * Workaround BCOM Errata for the C0 type. - * Write magic patterns to reserved registers. - */ - for (i = 0; i < ARRAY_SIZE(C0hack); i++) - xm_phy_write(hw, port, - C0hack[i].reg, C0hack[i].val); - - break; - case PHY_BCOM_ID1_A1: - /* - * Workaround BCOM Errata for the A1 type. - * Write magic patterns to reserved registers. - */ - for (i = 0; i < ARRAY_SIZE(A1hack); i++) - xm_phy_write(hw, port, - A1hack[i].reg, A1hack[i].val); - break; - } - - /* - * Workaround BCOM Errata (#10523) for all BCom PHYs. - * Disable Power Management after reset. - */ - r = xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL); - r |= PHY_B_AC_DIS_PM; - xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r); - - /* Dummy read */ - xm_read16(hw, port, XM_ISRC); - - ext = PHY_B_PEC_EN_LTR; /* enable tx led */ - ctl = PHY_CT_SP1000; /* always 1000mbit */ - - if (skge->autoneg == AUTONEG_ENABLE) { - /* - * Workaround BCOM Errata #1 for the C5 type. - * 1000Base-T Link Acquisition Failure in Slave Mode - * Set Repeater/DTE bit 10 of the 1000Base-T Control Register - */ - u16 adv = PHY_B_1000C_RD; - if (skge->advertising & ADVERTISED_1000baseT_Half) - adv |= PHY_B_1000C_AHD; - if (skge->advertising & ADVERTISED_1000baseT_Full) - adv |= PHY_B_1000C_AFD; - xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, adv); - - ctl |= PHY_CT_ANE | PHY_CT_RE_CFG; - } else { - if (skge->duplex == DUPLEX_FULL) - ctl |= PHY_CT_DUP_MD; - /* Force to slave */ - xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, PHY_B_1000C_MSE); - } - - /* Set autonegotiation pause parameters */ - xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV, - phy_pause_map[skge->flow_control] | PHY_AN_CSMA); - - /* Handle Jumbo frames */ - if (jumbo) { - xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, - PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK); - - ext |= PHY_B_PEC_HIGH_LA; - - } - - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ext); - xm_phy_write(hw, port, PHY_BCOM_CTRL, ctl); - - /* Use link status change interrrupt */ - xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); - - bcom_check_link(hw, port); -} - -static void genesis_mac_init(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - int jumbo = hw->dev[port]->mtu > ETH_DATA_LEN; - int i; - u32 r; - const u8 zero[6] = { 0 }; - - /* Clear MIB counters */ - xm_write16(hw, port, XM_STAT_CMD, - XM_SC_CLR_RXC | XM_SC_CLR_TXC); - /* Clear two times according to Errata #3 */ - xm_write16(hw, port, XM_STAT_CMD, - XM_SC_CLR_RXC | XM_SC_CLR_TXC); /* initialize Rx, Tx and Link LED */ - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); + skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_ON); + skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); + skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_START); + skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_START); /* Unreset the XMAC. */ - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); + skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); /* * Perform additional initialization for external PHYs, @@ -1210,56 +1059,67 @@ static void genesis_mac_init(struct skge_hw *hw, int port) * GMII mode. */ spin_lock_bh(&hw->phy_lock); - /* Take external Phy out of reset */ - r = skge_read32(hw, B2_GP_IO); - if (port == 0) - r |= GP_DIR_0|GP_IO_0; - else - r |= GP_DIR_2|GP_IO_2; - - skge_write32(hw, B2_GP_IO, r); - skge_read32(hw, B2_GP_IO); - spin_unlock_bh(&hw->phy_lock); - - /* Enable GMII interfac */ - xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); - - bcom_phy_init(skge, jumbo); - - /* Set Station Address */ - xm_outaddr(hw, port, XM_SA, dev->dev_addr); - - /* We don't use match addresses so clear */ - for (i = 1; i < 16; i++) - xm_outaddr(hw, port, XM_EXM(i), zero); - - /* configure Rx High Water Mark (XM_RX_HI_WM) */ - xm_write16(hw, port, XM_RX_HI_WM, 1450); - - /* We don't need the FCS appended to the packet. */ - r = XM_RX_LENERR_OK | XM_RX_STRIP_FCS; - if (jumbo) - r |= XM_RX_BIG_PK_OK; + if (hw->phy_type != SK_PHY_XMAC) { + /* Take PHY out of reset. */ + r = skge_read32(hw, B2_GP_IO); + if (port == 0) + r |= GP_DIR_0|GP_IO_0; + else + r |= GP_DIR_2|GP_IO_2; + + skge_write32(hw, B2_GP_IO, r); + skge_read32(hw, B2_GP_IO); + + /* Enable GMII mode on the XMAC. */ + skge_xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); + + id1 = skge_xm_phy_read(hw, port, PHY_XMAC_ID1); + + /* Optimize MDIO transfer by suppressing preamble. */ + skge_xm_write16(hw, port, XM_MMU_CMD, + skge_xm_read16(hw, port, XM_MMU_CMD) + | XM_MMU_NO_PRE); + + if (id1 == PHY_BCOM_ID1_C0) { + /* + * Workaround BCOM Errata for the C0 type. + * Write magic patterns to reserved registers. + */ + for (i = 0; i < ARRAY_SIZE(C0hack); i++) + skge_xm_phy_write(hw, port, + C0hack[i].reg, C0hack[i].val); + + } else if (id1 == PHY_BCOM_ID1_A1) { + /* + * Workaround BCOM Errata for the A1 type. + * Write magic patterns to reserved registers. + */ + for (i = 0; i < ARRAY_SIZE(A1hack); i++) + skge_xm_phy_write(hw, port, + A1hack[i].reg, A1hack[i].val); + } - if (skge->duplex == DUPLEX_HALF) { /* - * If in manual half duplex mode the other side might be in - * full duplex mode, so ignore if a carrier extension is not seen - * on frames received + * Workaround BCOM Errata (#10523) for all BCom PHYs. + * Disable Power Management after reset. */ - r |= XM_RX_DIS_CEXT; + r = skge_xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL); + skge_xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r | PHY_B_AC_DIS_PM); } - xm_write16(hw, port, XM_RX_CMD, r); + /* Dummy read */ + skge_xm_read16(hw, port, XM_ISRC); - /* We want short frames padded to 60 bytes. */ - xm_write16(hw, port, XM_TX_CMD, XM_TX_AUTO_PAD); + r = skge_xm_read32(hw, port, XM_MODE); + skge_xm_write32(hw, port, XM_MODE, r|XM_MD_CSA); - /* - * Bump up the transmit threshold. This helps hold off transmit - * underruns when we're blasting traffic from both ports at once. - */ - xm_write16(hw, port, XM_TX_THR, 512); + /* We don't need the FCS appended to the packet. */ + r = skge_xm_read16(hw, port, XM_RX_CMD); + skge_xm_write16(hw, port, XM_RX_CMD, r | XM_RX_STRIP_FCS); + + /* We want short frames padded to 60 bytes. */ + r = skge_xm_read16(hw, port, XM_TX_CMD); + skge_xm_write16(hw, port, XM_TX_CMD, r | XM_TX_AUTO_PAD); /* * Enable the reception of all error frames. This is is @@ -1275,22 +1135,19 @@ static void genesis_mac_init(struct skge_hw *hw, int port) * case the XMAC will start transfering frames out of the * RX FIFO as soon as the FIFO threshold is reached. */ - xm_write32(hw, port, XM_MODE, XM_DEF_MODE); + r = skge_xm_read32(hw, port, XM_MODE); + skge_xm_write32(hw, port, XM_MODE, + XM_MD_RX_CRCE|XM_MD_RX_LONG|XM_MD_RX_RUNT| + XM_MD_RX_ERR|XM_MD_RX_IRLE); + skge_xm_outaddr(hw, port, XM_SA, hw->dev[port]->dev_addr); + skge_xm_outaddr(hw, port, XM_EXM(0), hw->dev[port]->dev_addr); /* - * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK) - * - Enable all bits excepting 'Octets Rx OK Low CntOv' - * and 'Octets Rx OK Hi Cnt Ov'. - */ - xm_write32(hw, port, XM_RX_EV_MSK, XMR_DEF_MSK); - - /* - * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK) - * - Enable all bits excepting 'Octets Tx OK Low CntOv' - * and 'Octets Tx OK Hi Cnt Ov'. + * Bump up the transmit threshold. This helps hold off transmit + * underruns when we're blasting traffic from both ports at once. */ - xm_write32(hw, port, XM_TX_EV_MSK, XMT_DEF_MSK); + skge_xm_write16(hw, port, XM_TX_THR, 512); /* Configure MAC arbiter */ skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR); @@ -1307,30 +1164,137 @@ static void genesis_mac_init(struct skge_hw *hw, int port) skge_write8(hw, B3_MA_RCINI_TX2, 0); /* Configure Rx MAC FIFO */ - skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_CLR); - skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_TIM_PAT); - skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_ENA_OP_MD); + skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_RST_CLR); + skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_ENA_TIM_PAT); + skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_ENA_OP_MD); /* Configure Tx MAC FIFO */ - skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_CLR); - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); - skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD); + skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_RST_CLR); + skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); + skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD); - if (jumbo) { + if (hw->dev[port]->mtu > ETH_DATA_LEN) { /* Enable frame flushing if jumbo frames used */ - skge_write16(hw, SK_REG(port,RX_MFF_CTRL1), MFF_ENA_FLUSH); + skge_write16(hw, SKGEMAC_REG(port,RX_MFF_CTRL1), MFF_ENA_FLUSH); } else { /* enable timeout timers if normal frames */ skge_write16(hw, B3_PA_CTRL, - (port == 0) ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2); + port == 0 ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2); } + + + r = skge_xm_read16(hw, port, XM_RX_CMD); + if (hw->dev[port]->mtu > ETH_DATA_LEN) + skge_xm_write16(hw, port, XM_RX_CMD, r | XM_RX_BIG_PK_OK); + else + skge_xm_write16(hw, port, XM_RX_CMD, r & ~(XM_RX_BIG_PK_OK)); + + switch (hw->phy_type) { + case SK_PHY_XMAC: + if (skge->autoneg == AUTONEG_ENABLE) { + ctrl1 = PHY_X_AN_FD | PHY_X_AN_HD; + + switch (skge->flow_control) { + case FLOW_MODE_NONE: + ctrl1 |= PHY_X_P_NO_PAUSE; + break; + case FLOW_MODE_LOC_SEND: + ctrl1 |= PHY_X_P_ASYM_MD; + break; + case FLOW_MODE_SYMMETRIC: + ctrl1 |= PHY_X_P_SYM_MD; + break; + case FLOW_MODE_REM_SEND: + ctrl1 |= PHY_X_P_BOTH_MD; + break; + } + + skge_xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl1); + ctrl2 = PHY_CT_ANE | PHY_CT_RE_CFG; + } else { + ctrl2 = 0; + if (skge->duplex == DUPLEX_FULL) + ctrl2 |= PHY_CT_DUP_MD; + } + + skge_xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl2); + break; + + case SK_PHY_BCOM: + ctrl1 = PHY_CT_SP1000; + ctrl2 = 0; + ctrl3 = PHY_SEL_TYPE; + ctrl4 = PHY_B_PEC_EN_LTR; + ctrl5 = PHY_B_AC_TX_TST; + + if (skge->autoneg == AUTONEG_ENABLE) { + /* + * Workaround BCOM Errata #1 for the C5 type. + * 1000Base-T Link Acquisition Failure in Slave Mode + * Set Repeater/DTE bit 10 of the 1000Base-T Control Register + */ + ctrl2 |= PHY_B_1000C_RD; + if (skge->advertising & ADVERTISED_1000baseT_Half) + ctrl2 |= PHY_B_1000C_AHD; + if (skge->advertising & ADVERTISED_1000baseT_Full) + ctrl2 |= PHY_B_1000C_AFD; + + /* Set Flow-control capabilities */ + switch (skge->flow_control) { + case FLOW_MODE_NONE: + ctrl3 |= PHY_B_P_NO_PAUSE; + break; + case FLOW_MODE_LOC_SEND: + ctrl3 |= PHY_B_P_ASYM_MD; + break; + case FLOW_MODE_SYMMETRIC: + ctrl3 |= PHY_B_P_SYM_MD; + break; + case FLOW_MODE_REM_SEND: + ctrl3 |= PHY_B_P_BOTH_MD; + break; + } + + /* Restart Auto-negotiation */ + ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG; + } else { + if (skge->duplex == DUPLEX_FULL) + ctrl1 |= PHY_CT_DUP_MD; + + ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */ + } + + skge_xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, ctrl2); + skge_xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV, ctrl3); + + if (skge->netdev->mtu > ETH_DATA_LEN) { + ctrl4 |= PHY_B_PEC_HIGH_LA; + ctrl5 |= PHY_B_AC_LONG_PACK; + + skge_xm_phy_write(hw, port,PHY_BCOM_AUX_CTRL, ctrl5); + } + + skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ctrl4); + skge_xm_phy_write(hw, port, PHY_BCOM_CTRL, ctrl1); + break; + } + spin_unlock_bh(&hw->phy_lock); + + /* Clear MIB counters */ + skge_xm_write16(hw, port, XM_STAT_CMD, + XM_SC_CLR_RXC | XM_SC_CLR_TXC); + /* Clear two times according to Errata #3 */ + skge_xm_write16(hw, port, XM_STAT_CMD, + XM_SC_CLR_RXC | XM_SC_CLR_TXC); + + /* Start polling for link status */ + mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ); } static void genesis_stop(struct skge_port *skge) { struct skge_hw *hw = skge->hw; int port = skge->port; - u32 reg; /* Clear Tx packet arbiter timeout IRQ */ skge_write16(hw, B3_PA_CTRL, @@ -1340,30 +1304,33 @@ static void genesis_stop(struct skge_port *skge) * If the transfer stucks at the MAC the STOP command will not * terminate if we don't flush the XMAC's transmit FIFO ! */ - xm_write32(hw, port, XM_MODE, - xm_read32(hw, port, XM_MODE)|XM_MD_FTF); + skge_xm_write32(hw, port, XM_MODE, + skge_xm_read32(hw, port, XM_MODE)|XM_MD_FTF); /* Reset the MAC */ - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST); + skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST); /* For external PHYs there must be special handling */ - reg = skge_read32(hw, B2_GP_IO); - if (port == 0) { - reg |= GP_DIR_0; - reg &= ~GP_IO_0; - } else { - reg |= GP_DIR_2; - reg &= ~GP_IO_2; + if (hw->phy_type != SK_PHY_XMAC) { + u32 reg = skge_read32(hw, B2_GP_IO); + + if (port == 0) { + reg |= GP_DIR_0; + reg &= ~GP_IO_0; + } else { + reg |= GP_DIR_2; + reg &= ~GP_IO_2; + } + skge_write32(hw, B2_GP_IO, reg); + skge_read32(hw, B2_GP_IO); } - skge_write32(hw, B2_GP_IO, reg); - skge_read32(hw, B2_GP_IO); - xm_write16(hw, port, XM_MMU_CMD, - xm_read16(hw, port, XM_MMU_CMD) + skge_xm_write16(hw, port, XM_MMU_CMD, + skge_xm_read16(hw, port, XM_MMU_CMD) & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); - xm_read16(hw, port, XM_MMU_CMD); + skge_xm_read16(hw, port, XM_MMU_CMD); } @@ -1374,11 +1341,11 @@ static void genesis_get_stats(struct skge_port *skge, u64 *data) int i; unsigned long timeout = jiffies + HZ; - xm_write16(hw, port, + skge_xm_write16(hw, port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC); /* wait for update to complete */ - while (xm_read16(hw, port, XM_STAT_CMD) + while (skge_xm_read16(hw, port, XM_STAT_CMD) & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) { if (time_after(jiffies, timeout)) break; @@ -1386,60 +1353,68 @@ static void genesis_get_stats(struct skge_port *skge, u64 *data) } /* special case for 64 bit octet counter */ - data[0] = (u64) xm_read32(hw, port, XM_TXO_OK_HI) << 32 - | xm_read32(hw, port, XM_TXO_OK_LO); - data[1] = (u64) xm_read32(hw, port, XM_RXO_OK_HI) << 32 - | xm_read32(hw, port, XM_RXO_OK_LO); + data[0] = (u64) skge_xm_read32(hw, port, XM_TXO_OK_HI) << 32 + | skge_xm_read32(hw, port, XM_TXO_OK_LO); + data[1] = (u64) skge_xm_read32(hw, port, XM_RXO_OK_HI) << 32 + | skge_xm_read32(hw, port, XM_RXO_OK_LO); for (i = 2; i < ARRAY_SIZE(skge_stats); i++) - data[i] = xm_read32(hw, port, skge_stats[i].xmac_offset); + data[i] = skge_xm_read32(hw, port, skge_stats[i].xmac_offset); } static void genesis_mac_intr(struct skge_hw *hw, int port) { struct skge_port *skge = netdev_priv(hw->dev[port]); - u16 status = xm_read16(hw, port, XM_ISRC); - - if (netif_msg_intr(skge)) - printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", - skge->netdev->name, status); + u16 status = skge_xm_read16(hw, port, XM_ISRC); + + pr_debug("genesis_intr status %x\n", status); + if (hw->phy_type == SK_PHY_XMAC) { + /* LInk down, start polling for state change */ + if (status & XM_IS_INP_ASS) { + skge_xm_write16(hw, port, XM_IMSK, + skge_xm_read16(hw, port, XM_IMSK) | XM_IS_INP_ASS); + mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ); + } + else if (status & XM_IS_AND) + mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ); + } if (status & XM_IS_TXF_UR) { - xm_write32(hw, port, XM_MODE, XM_MD_FTF); + skge_xm_write32(hw, port, XM_MODE, XM_MD_FTF); ++skge->net_stats.tx_fifo_errors; } if (status & XM_IS_RXF_OV) { - xm_write32(hw, port, XM_MODE, XM_MD_FRF); + skge_xm_write32(hw, port, XM_MODE, XM_MD_FRF); ++skge->net_stats.rx_fifo_errors; } } -static void gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) +static void skge_gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) { int i; - gma_write16(hw, port, GM_SMI_DATA, val); - gma_write16(hw, port, GM_SMI_CTRL, + skge_gma_write16(hw, port, GM_SMI_DATA, val); + skge_gma_write16(hw, port, GM_SMI_CTRL, GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg)); for (i = 0; i < PHY_RETRIES; i++) { udelay(1); - if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) + if (!(skge_gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) break; } } -static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg) +static u16 skge_gm_phy_read(struct skge_hw *hw, int port, u16 reg) { int i; - gma_write16(hw, port, GM_SMI_CTRL, + skge_gma_write16(hw, port, GM_SMI_CTRL, GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); for (i = 0; i < PHY_RETRIES; i++) { udelay(1); - if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) + if (skge_gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) goto ready; } @@ -1447,7 +1422,24 @@ static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg) hw->dev[port]->name); return 0; ready: - return gma_read16(hw, port, GM_SMI_DATA); + return skge_gma_read16(hw, port, GM_SMI_DATA); +} + +static void genesis_link_down(struct skge_port *skge) +{ + struct skge_hw *hw = skge->hw; + int port = skge->port; + + pr_debug("genesis_link_down\n"); + + skge_xm_write16(hw, port, XM_MMU_CMD, + skge_xm_read16(hw, port, XM_MMU_CMD) + & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); + + /* dummy read to ensure writing */ + (void) skge_xm_read16(hw, port, XM_MMU_CMD); + + skge_link_down(skge); } static void genesis_link_up(struct skge_port *skge) @@ -1458,7 +1450,7 @@ static void genesis_link_up(struct skge_port *skge) u32 mode, msk; pr_debug("genesis_link_up\n"); - cmd = xm_read16(hw, port, XM_MMU_CMD); + cmd = skge_xm_read16(hw, port, XM_MMU_CMD); /* * enabling pause frame reception is required for 1000BT @@ -1466,15 +1458,14 @@ static void genesis_link_up(struct skge_port *skge) */ if (skge->flow_control == FLOW_MODE_NONE || skge->flow_control == FLOW_MODE_LOC_SEND) - /* Disable Pause Frame Reception */ cmd |= XM_MMU_IGN_PF; else /* Enable Pause Frame Reception */ cmd &= ~XM_MMU_IGN_PF; - xm_write16(hw, port, XM_MMU_CMD, cmd); + skge_xm_write16(hw, port, XM_MMU_CMD, cmd); - mode = xm_read32(hw, port, XM_MODE); + mode = skge_xm_read32(hw, port, XM_MODE); if (skge->flow_control == FLOW_MODE_SYMMETRIC || skge->flow_control == FLOW_MODE_LOC_SEND) { /* @@ -1488,10 +1479,10 @@ static void genesis_link_up(struct skge_port *skge) /* XM_PAUSE_DA = '010000C28001' (default) */ /* XM_MAC_PTIME = 0xffff (maximum) */ /* remember this value is defined in big endian (!) */ - xm_write16(hw, port, XM_MAC_PTIME, 0xffff); + skge_xm_write16(hw, port, XM_MAC_PTIME, 0xffff); mode |= XM_PAUSE_MODE; - skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_PAUSE); + skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_ENA_PAUSE); } else { /* * disable pause frame generation is required for 1000BT @@ -1500,68 +1491,125 @@ static void genesis_link_up(struct skge_port *skge) /* Disable Pause Mode in Mode Register */ mode &= ~XM_PAUSE_MODE; - skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_DIS_PAUSE); + skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_DIS_PAUSE); } - xm_write32(hw, port, XM_MODE, mode); + skge_xm_write32(hw, port, XM_MODE, mode); msk = XM_DEF_MSK; - /* disable GP0 interrupt bit for external Phy */ - msk |= XM_IS_INP_ASS; + if (hw->phy_type != SK_PHY_XMAC) + msk |= XM_IS_INP_ASS; /* disable GP0 interrupt bit */ - xm_write16(hw, port, XM_IMSK, msk); - xm_read16(hw, port, XM_ISRC); + skge_xm_write16(hw, port, XM_IMSK, msk); + skge_xm_read16(hw, port, XM_ISRC); /* get MMU Command Reg. */ - cmd = xm_read16(hw, port, XM_MMU_CMD); - if (skge->duplex == DUPLEX_FULL) + cmd = skge_xm_read16(hw, port, XM_MMU_CMD); + if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL) cmd |= XM_MMU_GMII_FD; - /* - * Workaround BCOM Errata (#10523) for all BCom Phys - * Enable Power Management after link up - */ - xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, - xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL) - & ~PHY_B_AC_DIS_PM); - xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); + if (hw->phy_type == SK_PHY_BCOM) { + /* + * Workaround BCOM Errata (#10523) for all BCom Phys + * Enable Power Management after link up + */ + skge_xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, + skge_xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL) + & ~PHY_B_AC_DIS_PM); + skge_xm_phy_write(hw, port, PHY_BCOM_INT_MASK, + PHY_B_DEF_MSK); + } /* enable Rx/Tx */ - xm_write16(hw, port, XM_MMU_CMD, + skge_xm_write16(hw, port, XM_MMU_CMD, cmd | XM_MMU_ENA_RX | XM_MMU_ENA_TX); skge_link_up(skge); } -static inline void bcom_phy_intr(struct skge_port *skge) +static void genesis_bcom_intr(struct skge_port *skge) { struct skge_hw *hw = skge->hw; int port = skge->port; - u16 isrc; - - isrc = xm_phy_read(hw, port, PHY_BCOM_INT_STAT); - if (netif_msg_intr(skge)) - printk(KERN_DEBUG PFX "%s: phy interrupt status 0x%x\n", - skge->netdev->name, isrc); + u16 stat = skge_xm_phy_read(hw, port, PHY_BCOM_INT_STAT); - if (isrc & PHY_B_IS_PSE) - printk(KERN_ERR PFX "%s: uncorrectable pair swap error\n", - hw->dev[port]->name); + pr_debug("genesis_bcom intr stat=%x\n", stat); /* Workaround BCom Errata: * enable and disable loopback mode if "NO HCD" occurs. */ - if (isrc & PHY_B_IS_NO_HDCL) { - u16 ctrl = xm_phy_read(hw, port, PHY_BCOM_CTRL); - xm_phy_write(hw, port, PHY_BCOM_CTRL, + if (stat & PHY_B_IS_NO_HDCL) { + u16 ctrl = skge_xm_phy_read(hw, port, PHY_BCOM_CTRL); + skge_xm_phy_write(hw, port, PHY_BCOM_CTRL, ctrl | PHY_CT_LOOP); - xm_phy_write(hw, port, PHY_BCOM_CTRL, + skge_xm_phy_write(hw, port, PHY_BCOM_CTRL, ctrl & ~PHY_CT_LOOP); } - if (isrc & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) - bcom_check_link(hw, port); + stat = skge_xm_phy_read(hw, port, PHY_BCOM_STAT); + if (stat & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) { + u16 aux = skge_xm_phy_read(hw, port, PHY_BCOM_AUX_STAT); + if ( !(aux & PHY_B_AS_LS) && netif_carrier_ok(skge->netdev)) + genesis_link_down(skge); + + else if (stat & PHY_B_IS_LST_CHANGE) { + if (aux & PHY_B_AS_AN_C) { + switch (aux & PHY_B_AS_AN_RES_MSK) { + case PHY_B_RES_1000FD: + skge->duplex = DUPLEX_FULL; + break; + case PHY_B_RES_1000HD: + skge->duplex = DUPLEX_HALF; + break; + } + + switch (aux & PHY_B_AS_PAUSE_MSK) { + case PHY_B_AS_PAUSE_MSK: + skge->flow_control = FLOW_MODE_SYMMETRIC; + break; + case PHY_B_AS_PRR: + skge->flow_control = FLOW_MODE_REM_SEND; + break; + case PHY_B_AS_PRT: + skge->flow_control = FLOW_MODE_LOC_SEND; + break; + default: + skge->flow_control = FLOW_MODE_NONE; + } + skge->speed = SPEED_1000; + } + genesis_link_up(skge); + } + else + mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ); + } +} +/* Perodic poll of phy status to check for link transistion */ +static void skge_link_timer(unsigned long __arg) +{ + struct skge_port *skge = (struct skge_port *) __arg; + struct skge_hw *hw = skge->hw; + int port = skge->port; + + if (hw->chip_id != CHIP_ID_GENESIS || !netif_running(skge->netdev)) + return; + + spin_lock_bh(&hw->phy_lock); + if (hw->phy_type == SK_PHY_BCOM) + genesis_bcom_intr(skge); + else { + int i; + for (i = 0; i < 3; i++) + if (skge_xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS) + break; + + if (i == 3) + mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ); + else + genesis_link_up(skge); + } + spin_unlock_bh(&hw->phy_lock); } /* Marvell Phy Initailization */ @@ -1573,27 +1621,31 @@ static void yukon_init(struct skge_hw *hw, int port) pr_debug("yukon_init\n"); if (skge->autoneg == AUTONEG_ENABLE) { - u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); + u16 ectrl = skge_gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | PHY_M_EC_MAC_S_MSK); ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); - ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1); + /* on PHY 88E1111 there is a change for downshift control */ + if (hw->chip_id == CHIP_ID_YUKON_EC) + ectrl |= PHY_M_EC_M_DSC_2(0) | PHY_M_EC_DOWN_S_ENA; + else + ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1); - gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl); + skge_gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl); } - ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); + ctrl = skge_gm_phy_read(hw, port, PHY_MARV_CTRL); if (skge->autoneg == AUTONEG_DISABLE) ctrl &= ~PHY_CT_ANE; ctrl |= PHY_CT_RESET; - gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); + skge_gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); ctrl = 0; ct1000 = 0; - adv = PHY_AN_CSMA; + adv = PHY_SEL_TYPE; if (skge->autoneg == AUTONEG_ENABLE) { if (iscopper(hw)) { @@ -1609,12 +1661,41 @@ static void yukon_init(struct skge_hw *hw, int port) adv |= PHY_M_AN_10_FD; if (skge->advertising & ADVERTISED_10baseT_Half) adv |= PHY_M_AN_10_HD; - } else /* special defines for FIBER (88E1011S only) */ - adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; - /* Set Flow-control capabilities */ - adv |= phy_pause_map[skge->flow_control]; + /* Set Flow-control capabilities */ + switch (skge->flow_control) { + case FLOW_MODE_NONE: + adv |= PHY_B_P_NO_PAUSE; + break; + case FLOW_MODE_LOC_SEND: + adv |= PHY_B_P_ASYM_MD; + break; + case FLOW_MODE_SYMMETRIC: + adv |= PHY_B_P_SYM_MD; + break; + case FLOW_MODE_REM_SEND: + adv |= PHY_B_P_BOTH_MD; + break; + } + } else { /* special defines for FIBER (88E1011S only) */ + adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; + /* Set Flow-control capabilities */ + switch (skge->flow_control) { + case FLOW_MODE_NONE: + adv |= PHY_M_P_NO_PAUSE_X; + break; + case FLOW_MODE_LOC_SEND: + adv |= PHY_M_P_ASYM_MD_X; + break; + case FLOW_MODE_SYMMETRIC: + adv |= PHY_M_P_SYM_MD_X; + break; + case FLOW_MODE_REM_SEND: + adv |= PHY_M_P_BOTH_MD_X; + break; + } + } /* Restart Auto-negotiation */ ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG; } else { @@ -1636,23 +1717,36 @@ static void yukon_init(struct skge_hw *hw, int port) ctrl |= PHY_CT_RESET; } - gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); + if (hw->chip_id != CHIP_ID_YUKON_FE) + skge_gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); - gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); - gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); + skge_gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); + skge_gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); /* Setup Phy LED's */ ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS); ledover = 0; - ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL; + if (hw->chip_id == CHIP_ID_YUKON_FE) { + /* on 88E3082 these bits are at 11..9 (shifted left) */ + ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1; + + skge_gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, + ((skge_gm_phy_read(hw, port, PHY_MARV_FE_LED_PAR) + + & ~PHY_M_FELP_LED1_MSK) + | PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL))); + } else { + /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */ + ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL; - /* turn off the Rx LED (LED_RX) */ - ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); + /* turn off the Rx LED (LED_RX) */ + ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); + } /* disable blink mode (LED_DUPLEX) on collisions */ ctrl |= PHY_M_LEDC_DP_CTRL; - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); + skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) { /* turn on 100 Mbps LED (LED_LINK100) */ @@ -1660,25 +1754,25 @@ static void yukon_init(struct skge_hw *hw, int port) } if (ledover) - gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); + skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); /* Enable phy interrupt on autonegotiation complete (or link up) */ if (skge->autoneg == AUTONEG_ENABLE) - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); + skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); else - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); + skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); } static void yukon_reset(struct skge_hw *hw, int port) { - gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);/* disable PHY IRQs */ - gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */ - gma_write16(hw, port, GM_MC_ADDR_H2, 0); - gma_write16(hw, port, GM_MC_ADDR_H3, 0); - gma_write16(hw, port, GM_MC_ADDR_H4, 0); + skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);/* disable PHY IRQs */ + skge_gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */ + skge_gma_write16(hw, port, GM_MC_ADDR_H2, 0); + skge_gma_write16(hw, port, GM_MC_ADDR_H3, 0); + skge_gma_write16(hw, port, GM_MC_ADDR_H4, 0); - gma_write16(hw, port, GM_RX_CTRL, - gma_read16(hw, port, GM_RX_CTRL) + skge_gma_write16(hw, port, GM_RX_CTRL, + skge_gma_read16(hw, port, GM_RX_CTRL) | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); } @@ -1691,17 +1785,17 @@ static void yukon_mac_init(struct skge_hw *hw, int port) /* WA code for COMA mode -- set PHY reset */ if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + chip_rev(hw) == CHIP_REV_YU_LITE_A3) skge_write32(hw, B2_GP_IO, (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9)); /* hard reset */ - skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); + skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), GPC_RST_SET); + skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_RST_SET); /* WA code for COMA mode -- clear PHY reset */ if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + chip_rev(hw) == CHIP_REV_YU_LITE_A3) skge_write32(hw, B2_GP_IO, (skge_read32(hw, B2_GP_IO) | GP_DIR_9) & ~GP_IO_9); @@ -1712,13 +1806,13 @@ static void yukon_mac_init(struct skge_hw *hw, int port) reg |= iscopper(hw) ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB; /* Clear GMC reset */ - skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET); - skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_CLR); - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); + skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), reg | GPC_RST_SET); + skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), reg | GPC_RST_CLR); + skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); if (skge->autoneg == AUTONEG_DISABLE) { reg = GM_GPCR_AU_ALL_DIS; - gma_write16(hw, port, GM_GP_CTRL, - gma_read16(hw, port, GM_GP_CTRL) | reg); + skge_gma_write16(hw, port, GM_GP_CTRL, + skge_gma_read16(hw, port, GM_GP_CTRL) | reg); switch (skge->speed) { case SPEED_1000: @@ -1734,7 +1828,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL; switch (skge->flow_control) { case FLOW_MODE_NONE: - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); + skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); reg |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; break; case FLOW_MODE_LOC_SEND: @@ -1742,7 +1836,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; } - gma_write16(hw, port, GM_GP_CTRL, reg); + skge_gma_write16(hw, port, GM_GP_CTRL, reg); skge_read16(hw, GMAC_IRQ_SRC); spin_lock_bh(&hw->phy_lock); @@ -1750,25 +1844,25 @@ static void yukon_mac_init(struct skge_hw *hw, int port) spin_unlock_bh(&hw->phy_lock); /* MIB clear */ - reg = gma_read16(hw, port, GM_PHY_ADDR); - gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR); + reg = skge_gma_read16(hw, port, GM_PHY_ADDR); + skge_gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR); for (i = 0; i < GM_MIB_CNT_SIZE; i++) - gma_read16(hw, port, GM_MIB_CNT_BASE + 8*i); - gma_write16(hw, port, GM_PHY_ADDR, reg); + skge_gma_read16(hw, port, GM_MIB_CNT_BASE + 8*i); + skge_gma_write16(hw, port, GM_PHY_ADDR, reg); /* transmit control */ - gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF)); + skge_gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF)); /* receive control reg: unicast + multicast + no FCS */ - gma_write16(hw, port, GM_RX_CTRL, + skge_gma_write16(hw, port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA); /* transmit flow control */ - gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff); + skge_gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff); /* transmit parameter */ - gma_write16(hw, port, GM_TX_PARAM, + skge_gma_write16(hw, port, GM_TX_PARAM, TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) | TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) | TX_IPG_JAM_DATA(TX_IPG_JAM_DEF)); @@ -1778,33 +1872,33 @@ static void yukon_mac_init(struct skge_hw *hw, int port) if (hw->dev[port]->mtu > 1500) reg |= GM_SMOD_JUMBO_ENA; - gma_write16(hw, port, GM_SERIAL_MODE, reg); + skge_gma_write16(hw, port, GM_SERIAL_MODE, reg); /* physical address: used for pause frames */ - gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr); + skge_gm_set_addr(hw, port, GM_SRC_ADDR_1L, addr); /* virtual address for data */ - gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr); + skge_gm_set_addr(hw, port, GM_SRC_ADDR_2L, addr); /* enable interrupt mask for counter overflows */ - gma_write16(hw, port, GM_TX_IRQ_MSK, 0); - gma_write16(hw, port, GM_RX_IRQ_MSK, 0); - gma_write16(hw, port, GM_TR_IRQ_MSK, 0); + skge_gma_write16(hw, port, GM_TX_IRQ_MSK, 0); + skge_gma_write16(hw, port, GM_RX_IRQ_MSK, 0); + skge_gma_write16(hw, port, GM_TR_IRQ_MSK, 0); /* Initialize Mac Fifo */ /* Configure Rx MAC FIFO */ - skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK); + skge_write16(hw, SKGEMAC_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK); reg = GMF_OPER_ON | GMF_RX_F_FL_ON; if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) + chip_rev(hw) == CHIP_REV_YU_LITE_A3) reg &= ~GMF_RX_F_FL_ON; - skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); - skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg); - skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF); + skge_write8(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); + skge_write16(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), reg); + skge_write16(hw, SKGEMAC_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF); /* Configure Tx MAC FIFO */ - skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); - skge_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); + skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); + skge_write16(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); } static void yukon_stop(struct skge_port *skge) @@ -1813,19 +1907,19 @@ static void yukon_stop(struct skge_port *skge) int port = skge->port; if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev == CHIP_REV_YU_LITE_A3) { + chip_rev(hw) == CHIP_REV_YU_LITE_A3) { skge_write32(hw, B2_GP_IO, skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9); } - gma_write16(hw, port, GM_GP_CTRL, - gma_read16(hw, port, GM_GP_CTRL) + skge_gma_write16(hw, port, GM_GP_CTRL, + skge_gma_read16(hw, port, GM_GP_CTRL) & ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA)); - gma_read16(hw, port, GM_GP_CTRL); + skge_gma_read16(hw, port, GM_GP_CTRL); /* set GPHY Control reset */ - gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET); - gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET); + skge_gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET); + skge_gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET); } static void yukon_get_stats(struct skge_port *skge, u64 *data) @@ -1834,40 +1928,39 @@ static void yukon_get_stats(struct skge_port *skge, u64 *data) int port = skge->port; int i; - data[0] = (u64) gma_read32(hw, port, GM_TXO_OK_HI) << 32 - | gma_read32(hw, port, GM_TXO_OK_LO); - data[1] = (u64) gma_read32(hw, port, GM_RXO_OK_HI) << 32 - | gma_read32(hw, port, GM_RXO_OK_LO); + data[0] = (u64) skge_gma_read32(hw, port, GM_TXO_OK_HI) << 32 + | skge_gma_read32(hw, port, GM_TXO_OK_LO); + data[1] = (u64) skge_gma_read32(hw, port, GM_RXO_OK_HI) << 32 + | skge_gma_read32(hw, port, GM_RXO_OK_LO); for (i = 2; i < ARRAY_SIZE(skge_stats); i++) - data[i] = gma_read32(hw, port, + data[i] = skge_gma_read32(hw, port, skge_stats[i].gma_offset); } static void yukon_mac_intr(struct skge_hw *hw, int port) { - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - u8 status = skge_read8(hw, SK_REG(port, GMAC_IRQ_SRC)); - - if (netif_msg_intr(skge)) - printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", - dev->name, status); + struct skge_port *skge = netdev_priv(hw->dev[port]); + u8 status = skge_read8(hw, SKGEMAC_REG(port, GMAC_IRQ_SRC)); + pr_debug("yukon_intr status %x\n", status); if (status & GM_IS_RX_FF_OR) { ++skge->net_stats.rx_fifo_errors; - gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO); + skge_gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO); } if (status & GM_IS_TX_FF_UR) { ++skge->net_stats.tx_fifo_errors; - gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU); + skge_gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU); } } static u16 yukon_speed(const struct skge_hw *hw, u16 aux) { - switch (aux & PHY_M_PS_SPEED_MSK) { + if (hw->chip_id == CHIP_ID_YUKON_FE) + return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10; + + switch(aux & PHY_M_PS_SPEED_MSK) { case PHY_M_PS_SPEED_1000: return SPEED_1000; case PHY_M_PS_SPEED_100: @@ -1888,15 +1981,15 @@ static void yukon_link_up(struct skge_port *skge) /* Enable Transmit FIFO Underrun */ skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK); - reg = gma_read16(hw, port, GM_GP_CTRL); + reg = skge_gma_read16(hw, port, GM_GP_CTRL); if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE) reg |= GM_GPCR_DUP_FULL; /* enable Rx/Tx */ reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; - gma_write16(hw, port, GM_GP_CTRL, reg); + skge_gma_write16(hw, port, GM_GP_CTRL, reg); - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); + skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); skge_link_up(skge); } @@ -1906,15 +1999,16 @@ static void yukon_link_down(struct skge_port *skge) int port = skge->port; pr_debug("yukon_link_down\n"); - gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); - gm_phy_write(hw, port, GM_GP_CTRL, - gm_phy_read(hw, port, GM_GP_CTRL) + skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); + skge_gm_phy_write(hw, port, GM_GP_CTRL, + skge_gm_phy_read(hw, port, GM_GP_CTRL) & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA)); - if (skge->flow_control == FLOW_MODE_REM_SEND) { + if (hw->chip_id != CHIP_ID_YUKON_FE && + skge->flow_control == FLOW_MODE_REM_SEND) { /* restore Asymmetric Pause bit */ - gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, - gm_phy_read(hw, port, + skge_gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, + skge_gm_phy_read(hw, port, PHY_MARV_AUNE_ADV) | PHY_M_AN_ASP); @@ -1933,21 +2027,20 @@ static void yukon_phy_intr(struct skge_port *skge) const char *reason = NULL; u16 istatus, phystat; - istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); - phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); - - if (netif_msg_intr(skge)) - printk(KERN_DEBUG PFX "%s: phy interrupt status 0x%x 0x%x\n", - skge->netdev->name, istatus, phystat); + istatus = skge_gm_phy_read(hw, port, PHY_MARV_INT_STAT); + phystat = skge_gm_phy_read(hw, port, PHY_MARV_PHY_STAT); + pr_debug("yukon phy intr istat=%x phy_stat=%x\n", istatus, phystat); if (istatus & PHY_M_IS_AN_COMPL) { - if (gm_phy_read(hw, port, PHY_MARV_AUNE_LP) + if (skge_gm_phy_read(hw, port, PHY_MARV_AUNE_LP) & PHY_M_AN_RF) { reason = "remote fault"; goto failed; } - if (gm_phy_read(hw, port, PHY_MARV_1000T_STAT) & PHY_B_1000S_MSF) { + if (!(hw->chip_id == CHIP_ID_YUKON_FE || hw->chip_id == CHIP_ID_YUKON_EC) + && (skge_gm_phy_read(hw, port, PHY_MARV_1000T_STAT) + & PHY_B_1000S_MSF)) { reason = "master/slave fault"; goto failed; } @@ -1961,6 +2054,10 @@ static void yukon_phy_intr(struct skge_port *skge) ? DUPLEX_FULL : DUPLEX_HALF; skge->speed = yukon_speed(hw, phystat); + /* Tx & Rx Pause Enabled bits are at 9..8 */ + if (hw->chip_id == CHIP_ID_YUKON_XL) + phystat >>= 6; + /* We are using IEEE 802.3z/D5.0 Table 37-4 */ switch (phystat & PHY_M_PS_PAUSE_MSK) { case PHY_M_PS_PAUSE_MSK: @@ -1978,9 +2075,9 @@ static void yukon_phy_intr(struct skge_port *skge) if (skge->flow_control == FLOW_MODE_NONE || (skge->speed < SPEED_1000 && skge->duplex == DUPLEX_HALF)) - skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); + skge_write8(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); else - skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); + skge_write8(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_ON); yukon_link_up(skge); return; } @@ -2064,12 +2161,6 @@ static int skge_up(struct net_device *dev) if (netif_msg_ifup(skge)) printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); - if (dev->mtu > RX_BUF_SIZE) - skge->rx_buf_size = dev->mtu + ETH_HLEN + NET_IP_ALIGN; - else - skge->rx_buf_size = RX_BUF_SIZE; - - rx_size = skge->rx_ring.count * sizeof(struct skge_rx_desc); tx_size = skge->tx_ring.count * sizeof(struct skge_tx_desc); skge->mem_size = tx_size + rx_size; @@ -2082,8 +2173,7 @@ static int skge_up(struct net_device *dev) if ((err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma))) goto free_pci_mem; - err = skge_rx_fill(skge); - if (err) + if (skge_rx_fill(skge)) goto free_rx_ring; if ((err = skge_ring_alloc(&skge->tx_ring, skge->mem + rx_size, @@ -2092,10 +2182,6 @@ static int skge_up(struct net_device *dev) skge->tx_avail = skge->tx_ring.count - 1; - /* Enable IRQ from port */ - hw->intr_mask |= portirqmask[port]; - skge_write32(hw, B0_IMSK, hw->intr_mask); - /* Initialze MAC */ if (hw->chip_id == CHIP_ID_GENESIS) genesis_mac_init(hw, port); @@ -2103,7 +2189,7 @@ static int skge_up(struct net_device *dev) yukon_mac_init(hw, port); /* Configure RAMbuffers */ - chunk = hw->ram_size / ((hw->ports + 1)*2); + chunk = hw->ram_size / (isdualport(hw) ? 4 : 2); ram_addr = hw->ram_offset + 2 * chunk * port; skge_ramset(hw, rxqaddr[port], ram_addr, chunk); @@ -2141,6 +2227,7 @@ static int skge_down(struct net_device *dev) netif_stop_queue(dev); del_timer_sync(&skge->led_blink); + del_timer_sync(&skge->link_check); /* Stop transmitter */ skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); @@ -2153,12 +2240,12 @@ static int skge_down(struct net_device *dev) yukon_stop(skge); /* Disable Force Sync bit and Enable Alloc bit */ - skge_write8(hw, SK_REG(port, TXA_CTRL), + skge_write8(hw, SKGEMAC_REG(port, TXA_CTRL), TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); /* Stop Interval Timer and Limit Counter of Tx Arbiter */ - skge_write32(hw, SK_REG(port, TXA_ITI_INI), 0L); - skge_write32(hw, SK_REG(port, TXA_LIM_INI), 0L); + skge_write32(hw, SKGEMAC_REG(port, TXA_ITI_INI), 0L); + skge_write32(hw, SKGEMAC_REG(port, TXA_LIM_INI), 0L); /* Reset PCI FIFO */ skge_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_SET_RESET); @@ -2173,13 +2260,13 @@ static int skge_down(struct net_device *dev) skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET); if (hw->chip_id == CHIP_ID_GENESIS) { - skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); - skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_STOP); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_STOP); + skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_RST_SET); + skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_RST_SET); + skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_STOP); + skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_STOP); } else { - skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); - skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); + skge_write8(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); + skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); } /* turn off led's */ @@ -2212,10 +2299,10 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) local_irq_save(flags); if (!spin_trylock(&skge->tx_lock)) { - /* Collision - tell upper layer to requeue */ - local_irq_restore(flags); - return NETDEV_TX_LOCKED; - } + /* Collision - tell upper layer to requeue */ + local_irq_restore(flags); + return NETDEV_TX_LOCKED; + } if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) { netif_stop_queue(dev); @@ -2246,7 +2333,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) * does. Looks like hardware is wrong? */ if (ip->protocol == IPPROTO_UDP - && hw->chip_rev == 0 && hw->chip_id == CHIP_ID_YUKON) + && chip_rev(hw) == 0 && hw->chip_id == CHIP_ID_YUKON) control = BMU_TCP_CHECK; else control = BMU_UDP_CHECK; @@ -2307,7 +2394,6 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) static inline void skge_tx_free(struct skge_hw *hw, struct skge_element *e) { - /* This ring element can be skb or fragment */ if (e->skb) { pci_unmap_single(hw->pdev, pci_unmap_addr(e, mapaddr), @@ -2352,17 +2438,16 @@ static void skge_tx_timeout(struct net_device *dev) static int skge_change_mtu(struct net_device *dev, int new_mtu) { int err = 0; - int running = netif_running(dev); - if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) + if(new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; + dev->mtu = new_mtu; - if (running) + if (netif_running(dev)) { skge_down(dev); - dev->mtu = new_mtu; - if (running) skge_up(dev); + } return err; } @@ -2377,9 +2462,7 @@ static void genesis_set_multicast(struct net_device *dev) u32 mode; u8 filter[8]; - pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count); - - mode = xm_read32(hw, port, XM_MODE); + mode = skge_xm_read32(hw, port, XM_MODE); mode |= XM_MD_ENA_HASH; if (dev->flags & IFF_PROMISC) mode |= XM_MD_ENA_PROM; @@ -2390,16 +2473,17 @@ static void genesis_set_multicast(struct net_device *dev) memset(filter, 0xff, sizeof(filter)); else { memset(filter, 0, sizeof(filter)); - for (i = 0; list && i < count; i++, list = list->next) { - u32 crc, bit; - crc = ether_crc_le(ETH_ALEN, list->dmi_addr); - bit = ~crc & 0x3f; + for(i = 0; list && i < count; i++, list = list->next) { + u32 crc = crc32_le(~0, list->dmi_addr, ETH_ALEN); + u8 bit = 63 - (crc & 63); + filter[bit/8] |= 1 << (bit%8); } } - xm_write32(hw, port, XM_MODE, mode); - xm_outhash(hw, port, XM_HSM, filter); + skge_xm_outhash(hw, port, XM_HSM, filter); + + skge_xm_write32(hw, port, XM_MODE, mode); } static void yukon_set_multicast(struct net_device *dev) @@ -2413,7 +2497,7 @@ static void yukon_set_multicast(struct net_device *dev) memset(filter, 0, sizeof(filter)); - reg = gma_read16(hw, port, GM_RX_CTRL); + reg = skge_gma_read16(hw, port, GM_RX_CTRL); reg |= GM_RXCR_UCF_ENA; if (dev->flags & IFF_PROMISC) /* promiscious */ @@ -2426,23 +2510,23 @@ static void yukon_set_multicast(struct net_device *dev) int i; reg |= GM_RXCR_MCF_ENA; - for (i = 0; list && i < dev->mc_count; i++, list = list->next) { + for(i = 0; list && i < dev->mc_count; i++, list = list->next) { u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f; filter[bit/8] |= 1 << (bit%8); } } - gma_write16(hw, port, GM_MC_ADDR_H1, + skge_gma_write16(hw, port, GM_MC_ADDR_H1, (u16)filter[0] | ((u16)filter[1] << 8)); - gma_write16(hw, port, GM_MC_ADDR_H2, + skge_gma_write16(hw, port, GM_MC_ADDR_H2, (u16)filter[2] | ((u16)filter[3] << 8)); - gma_write16(hw, port, GM_MC_ADDR_H3, + skge_gma_write16(hw, port, GM_MC_ADDR_H3, (u16)filter[4] | ((u16)filter[5] << 8)); - gma_write16(hw, port, GM_MC_ADDR_H4, + skge_gma_write16(hw, port, GM_MC_ADDR_H4, (u16)filter[6] | ((u16)filter[7] << 8)); - gma_write16(hw, port, GM_RX_CTRL, reg); + skge_gma_write16(hw, port, GM_RX_CTRL, reg); } static inline int bad_phy_status(const struct skge_hw *hw, u32 status) @@ -2461,76 +2545,28 @@ static void skge_rx_error(struct skge_port *skge, int slot, printk(KERN_DEBUG PFX "%s: rx err, slot %d control 0x%x status 0x%x\n", skge->netdev->name, slot, control, status); - if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)) + if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF) + || (control & BMU_BBC) > skge->netdev->mtu + VLAN_ETH_HLEN) skge->net_stats.rx_length_errors++; - else if (skge->hw->chip_id == CHIP_ID_GENESIS) { - if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR)) - skge->net_stats.rx_length_errors++; - if (status & XMR_FS_FRA_ERR) - skge->net_stats.rx_frame_errors++; - if (status & XMR_FS_FCS_ERR) - skge->net_stats.rx_crc_errors++; - } else { - if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE)) - skge->net_stats.rx_length_errors++; - if (status & GMR_FS_FRAGMENT) - skge->net_stats.rx_frame_errors++; - if (status & GMR_FS_CRC_ERR) - skge->net_stats.rx_crc_errors++; - } -} - -/* Get receive buffer from descriptor. - * Handles copy of small buffers and reallocation failures - */ -static inline struct sk_buff *skge_rx_get(struct skge_port *skge, - struct skge_element *e, - unsigned int len) -{ - struct sk_buff *nskb, *skb; - - if (len < RX_COPY_THRESHOLD) { - nskb = skge_rx_alloc(skge->netdev, len + NET_IP_ALIGN); - if (unlikely(!nskb)) - return NULL; - - pci_dma_sync_single_for_cpu(skge->hw->pdev, - pci_unmap_addr(e, mapaddr), - len, PCI_DMA_FROMDEVICE); - memcpy(nskb->data, e->skb->data, len); - pci_dma_sync_single_for_device(skge->hw->pdev, - pci_unmap_addr(e, mapaddr), - len, PCI_DMA_FROMDEVICE); - - if (skge->rx_csum) { - struct skge_rx_desc *rd = e->desc; - nskb->csum = le16_to_cpu(rd->csum2); - nskb->ip_summed = CHECKSUM_HW; - } - skge_rx_reuse(e, skge->rx_buf_size); - return nskb; - } else { - nskb = skge_rx_alloc(skge->netdev, skge->rx_buf_size); - if (unlikely(!nskb)) - return NULL; - - pci_unmap_single(skge->hw->pdev, - pci_unmap_addr(e, mapaddr), - pci_unmap_len(e, maplen), - PCI_DMA_FROMDEVICE); - skb = e->skb; - if (skge->rx_csum) { - struct skge_rx_desc *rd = e->desc; - skb->csum = le16_to_cpu(rd->csum2); - skb->ip_summed = CHECKSUM_HW; + else { + if (skge->hw->chip_id == CHIP_ID_GENESIS) { + if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR)) + skge->net_stats.rx_length_errors++; + if (status & XMR_FS_FRA_ERR) + skge->net_stats.rx_frame_errors++; + if (status & XMR_FS_FCS_ERR) + skge->net_stats.rx_crc_errors++; + } else { + if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE)) + skge->net_stats.rx_length_errors++; + if (status & GMR_FS_FRAGMENT) + skge->net_stats.rx_frame_errors++; + if (status & GMR_FS_CRC_ERR) + skge->net_stats.rx_crc_errors++; } - - skge_rx_setup(skge, e, nskb, skge->rx_buf_size); - return skb; } } - static int skge_poll(struct net_device *dev, int *budget) { struct skge_port *skge = netdev_priv(dev); @@ -2539,12 +2575,13 @@ static int skge_poll(struct net_device *dev, int *budget) struct skge_element *e; unsigned int to_do = min(dev->quota, *budget); unsigned int work_done = 0; + int done; + static const u32 irqmask[] = { IS_PORT_1, IS_PORT_2 }; - pr_debug("skge_poll\n"); - - for (e = ring->to_clean; work_done < to_do; e = e->next) { + for (e = ring->to_clean; e != ring->to_use && work_done < to_do; + e = e->next) { struct skge_rx_desc *rd = e->desc; - struct sk_buff *skb; + struct sk_buff *skb = e->skb; u32 control, len, status; rmb(); @@ -2553,12 +2590,19 @@ static int skge_poll(struct net_device *dev, int *budget) break; len = control & BMU_BBC; - status = rd->status; + e->skb = NULL; + + pci_unmap_single(hw->pdev, + pci_unmap_addr(e, mapaddr), + pci_unmap_len(e, maplen), + PCI_DMA_FROMDEVICE); - if (unlikely((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF) - || bad_phy_status(hw, status))) { + status = rd->status; + if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF) + || len > dev->mtu + VLAN_ETH_HLEN + || bad_phy_status(hw, status)) { skge_rx_error(skge, e - ring->start, control, status); - skge_rx_reuse(e, skge->rx_buf_size); + dev_kfree_skb(skb); continue; } @@ -2566,37 +2610,43 @@ static int skge_poll(struct net_device *dev, int *budget) printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n", dev->name, e - ring->start, rd->status, len); - skb = skge_rx_get(skge, e, len); - if (likely(skb)) { - skb_put(skb, len); - skb->protocol = eth_type_trans(skb, dev); + skb_put(skb, len); + skb->protocol = eth_type_trans(skb, dev); - dev->last_rx = jiffies; - netif_receive_skb(skb); + if (skge->rx_csum) { + skb->csum = le16_to_cpu(rd->csum2); + skb->ip_summed = CHECKSUM_HW; + } - ++work_done; - } else - skge_rx_reuse(e, skge->rx_buf_size); + dev->last_rx = jiffies; + netif_receive_skb(skb); + + ++work_done; } ring->to_clean = e; + *budget -= work_done; + dev->quota -= work_done; + done = work_done < to_do; + + if (skge_rx_fill(skge)) + done = 0; + /* restart receiver */ wmb(); skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_START | CSR_IRQ_CL_F); - *budget -= work_done; - dev->quota -= work_done; - - if (work_done >= to_do) - return 1; /* not done */ + if (done) { + local_irq_disable(); + hw->intr_mask |= irqmask[skge->port]; + /* Order is important since data can get interrupted */ + skge_write32(hw, B0_IMSK, hw->intr_mask); + __netif_rx_complete(dev); + local_irq_enable(); + } - local_irq_disable(); - __netif_rx_complete(dev); - hw->intr_mask |= portirqmask[skge->port]; - skge_write32(hw, B0_IMSK, hw->intr_mask); - local_irq_enable(); - return 0; + return !done; } static inline void skge_tx_intr(struct net_device *dev) @@ -2607,7 +2657,7 @@ static inline void skge_tx_intr(struct net_device *dev) struct skge_element *e; spin_lock(&skge->tx_lock); - for (e = ring->to_clean; e != ring->to_use; e = e->next) { + for(e = ring->to_clean; e != ring->to_use; e = e->next) { struct skge_tx_desc *td = e->desc; u32 control; @@ -2640,12 +2690,12 @@ static void skge_mac_parity(struct skge_hw *hw, int port) : (port == 0 ? "(port A)": "(port B")); if (hw->chip_id == CHIP_ID_GENESIS) - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), + skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_CLR_PERR); else /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ - skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), - (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0) + skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), + (hw->chip_id == CHIP_ID_YUKON && chip_rev(hw) == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE); } @@ -2653,16 +2703,16 @@ static void skge_pci_clear(struct skge_hw *hw) { u16 status; - pci_read_config_word(hw->pdev, PCI_STATUS, &status); + status = skge_read16(hw, SKGEPCI_REG(PCI_STATUS)); skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - pci_write_config_word(hw->pdev, PCI_STATUS, - status | PCI_STATUS_ERROR_BITS); + skge_write16(hw, SKGEPCI_REG(PCI_STATUS), + status | PCI_STATUS_ERROR_BITS); skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); } static void skge_mac_intr(struct skge_hw *hw, int port) { - if (hw->chip_id == CHIP_ID_GENESIS) + if (hw->chip_id == CHIP_ID_GENESIS) genesis_mac_intr(hw, port); else yukon_mac_intr(hw, port); @@ -2676,9 +2726,9 @@ static void skge_error_irq(struct skge_hw *hw) if (hw->chip_id == CHIP_ID_GENESIS) { /* clear xmac errors */ if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1)) - skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT); + skge_write16(hw, SKGEMAC_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT); if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2)) - skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT); + skge_write16(hw, SKGEMAC_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT); } else { /* Timestamp (unused) overflow */ if (hwstatus & IS_IRQ_TIST_OV) @@ -2753,8 +2803,8 @@ static void skge_extirq(unsigned long data) if (hw->chip_id != CHIP_ID_GENESIS) yukon_phy_intr(skge); - else - bcom_phy_intr(skge); + else if (hw->phy_type == SK_PHY_BCOM) + genesis_bcom_intr(skge); } } spin_unlock(&hw->phy_lock); @@ -2774,14 +2824,19 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) return IRQ_NONE; status &= hw->intr_mask; - if (status & IS_R1_F) { + + if ((status & IS_R1_F) && netif_rx_schedule_prep(hw->dev[0])) { + status &= ~IS_R1_F; hw->intr_mask &= ~IS_R1_F; - netif_rx_schedule(hw->dev[0]); + skge_write32(hw, B0_IMSK, hw->intr_mask); + __netif_rx_schedule(hw->dev[0]); } - if (status & IS_R2_F) { + if ((status & IS_R2_F) && netif_rx_schedule_prep(hw->dev[1])) { + status &= ~IS_R2_F; hw->intr_mask &= ~IS_R2_F; - netif_rx_schedule(hw->dev[1]); + skge_write32(hw, B0_IMSK, hw->intr_mask); + __netif_rx_schedule(hw->dev[1]); } if (status & IS_XA1_F) @@ -2790,27 +2845,9 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) if (status & IS_XA2_F) skge_tx_intr(hw->dev[1]); - if (status & IS_PA_TO_RX1) { - struct skge_port *skge = netdev_priv(hw->dev[0]); - ++skge->net_stats.rx_over_errors; - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1); - } - - if (status & IS_PA_TO_RX2) { - struct skge_port *skge = netdev_priv(hw->dev[1]); - ++skge->net_stats.rx_over_errors; - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2); - } - - if (status & IS_PA_TO_TX1) - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1); - - if (status & IS_PA_TO_TX2) - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2); - if (status & IS_MAC1) skge_mac_intr(hw, 0); - + if (status & IS_MAC2) skge_mac_intr(hw, 1); @@ -2822,7 +2859,8 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) tasklet_schedule(&hw->ext_tasklet); } - skge_write32(hw, B0_IMSK, hw->intr_mask); + if (status) + skge_write32(hw, B0_IMSK, hw->intr_mask); return IRQ_HANDLED; } @@ -2866,6 +2904,9 @@ static const struct { { CHIP_ID_YUKON, "Yukon" }, { CHIP_ID_YUKON_LITE, "Yukon-Lite"}, { CHIP_ID_YUKON_LP, "Yukon-LP"}, + { CHIP_ID_YUKON_XL, "Yukon-2 XL"}, + { CHIP_ID_YUKON_EC, "YUKON-2 EC"}, + { CHIP_ID_YUKON_FE, "YUKON-2 FE"}, }; static const char *skge_board_name(const struct skge_hw *hw) @@ -2889,8 +2930,8 @@ static const char *skge_board_name(const struct skge_hw *hw) static int skge_reset(struct skge_hw *hw) { u16 ctst; - u8 t8, mac_cfg; - int i; + u8 t8; + int i, ports; ctst = skge_read16(hw, B0_CTST); @@ -2911,9 +2952,12 @@ static int skge_reset(struct skge_hw *hw) hw->phy_type = skge_read8(hw, B2_E_1) & 0xf; hw->pmd_type = skge_read8(hw, B2_PMD_TYP); - switch (hw->chip_id) { + switch(hw->chip_id) { case CHIP_ID_GENESIS: switch (hw->phy_type) { + case SK_PHY_XMAC: + hw->phy_addr = PHY_ADDR_XMAC; + break; case SK_PHY_BCOM: hw->phy_addr = PHY_ADDR_BCOM; break; @@ -2942,9 +2986,8 @@ static int skge_reset(struct skge_hw *hw) return -EOPNOTSUPP; } - mac_cfg = skge_read8(hw, B2_MAC_CFG); - hw->ports = (mac_cfg & CFG_SNG_MAC) ? 1 : 2; - hw->chip_rev = (mac_cfg & CFG_CHIP_R_MSK) >> 4; + hw->mac_cfg = skge_read8(hw, B2_MAC_CFG); + ports = isdualport(hw) ? 2 : 1; /* read the adapters RAM size */ t8 = skge_read8(hw, B2_E_0); @@ -2967,9 +3010,9 @@ static int skge_reset(struct skge_hw *hw) /* switch power to VCC (WA for VAUX problem) */ skge_write8(hw, B0_POWER_CTRL, PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); - for (i = 0; i < hw->ports; i++) { - skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); - skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR); + for (i = 0; i < ports; i++) { + skge_write16(hw, SKGEMAC_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); + skge_write16(hw, SKGEMAC_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR); } } @@ -2979,8 +3022,8 @@ static int skge_reset(struct skge_hw *hw) skge_write8(hw, B0_LED, LED_STAT_ON); /* enable the Tx Arbiters */ - for (i = 0; i < hw->ports; i++) - skge_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB); + for (i = 0; i < ports; i++) + skge_write8(hw, SKGEMAC_REG(i, TXA_CTRL), TXA_ENA_ARB); /* Initialize ram interface */ skge_write16(hw, B3_RI_CTRL, RI_RST_CLR); @@ -3007,14 +3050,16 @@ static int skge_reset(struct skge_hw *hw) skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100)); skge_write32(hw, B2_IRQM_CTRL, TIM_START); - hw->intr_mask = IS_HW_ERR | IS_EXT_REG; + hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1; + if (isdualport(hw)) + hw->intr_mask |= IS_PORT_2; skge_write32(hw, B0_IMSK, hw->intr_mask); if (hw->chip_id != CHIP_ID_GENESIS) skge_write8(hw, GMAC_IRQ_MSK, 0); spin_lock_bh(&hw->phy_lock); - for (i = 0; i < hw->ports; i++) { + for (i = 0; i < ports; i++) { if (hw->chip_id == CHIP_ID_GENESIS) genesis_reset(hw, i); else @@ -3026,8 +3071,7 @@ static int skge_reset(struct skge_hw *hw) } /* Initialize network device */ -static struct net_device *skge_devinit(struct skge_hw *hw, int port, - int highmem) +static struct net_device *skge_devinit(struct skge_hw *hw, int port) { struct skge_port *skge; struct net_device *dev = alloc_etherdev(sizeof(*skge)); @@ -3060,8 +3104,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, #endif dev->irq = hw->pdev->irq; dev->features = NETIF_F_LLTX; - if (highmem) - dev->features |= NETIF_F_HIGHDMA; skge = netdev_priv(dev); skge->netdev = dev; @@ -3075,7 +3117,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->flow_control = FLOW_MODE_SYMMETRIC; skge->duplex = -1; skge->speed = -1; - skge->advertising = skge_supported_modes(hw); + skge->advertising = skge_modes(hw); hw->dev[port] = dev; @@ -3083,6 +3125,10 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, spin_lock_init(&skge->tx_lock); + init_timer(&skge->link_check); + skge->link_check.function = skge_link_timer; + skge->link_check.data = (unsigned long) skge; + init_timer(&skge->led_blink); skge->led_blink.function = skge_blink_timer; skge->led_blink.data = (unsigned long) skge; @@ -3186,11 +3232,14 @@ static int __devinit skge_probe(struct pci_dev *pdev, printk(KERN_INFO PFX "addr 0x%lx irq %d chip %s rev %d\n", pci_resource_start(pdev, 0), pdev->irq, - skge_board_name(hw), hw->chip_rev); + skge_board_name(hw), chip_rev(hw)); - if ((dev = skge_devinit(hw, 0, using_dac)) == NULL) + if ((dev = skge_devinit(hw, 0)) == NULL) goto err_out_led_off; + if (using_dac) + dev->features |= NETIF_F_HIGHDMA; + if ((err = register_netdev(dev))) { printk(KERN_ERR PFX "%s: cannot register net device\n", pci_name(pdev)); @@ -3199,7 +3248,10 @@ static int __devinit skge_probe(struct pci_dev *pdev, skge_show_addr(dev); - if (hw->ports > 1 && (dev1 = skge_devinit(hw, 1, using_dac))) { + if (isdualport(hw) && (dev1 = skge_devinit(hw, 1))) { + if (using_dac) + dev1->features |= NETIF_F_HIGHDMA; + if (register_netdev(dev1) == 0) skge_show_addr(dev1); else { @@ -3236,7 +3288,7 @@ static void __devexit skge_remove(struct pci_dev *pdev) struct skge_hw *hw = pci_get_drvdata(pdev); struct net_device *dev0, *dev1; - if (!hw) + if(!hw) return; if ((dev1 = hw->dev[1])) @@ -3264,7 +3316,7 @@ static int skge_suspend(struct pci_dev *pdev, u32 state) struct skge_hw *hw = pci_get_drvdata(pdev); int i, wol = 0; - for (i = 0; i < 2; i++) { + for(i = 0; i < 2; i++) { struct net_device *dev = hw->dev[i]; if (dev) { @@ -3297,11 +3349,11 @@ static int skge_resume(struct pci_dev *pdev) skge_reset(hw); - for (i = 0; i < 2; i++) { + for(i = 0; i < 2; i++) { struct net_device *dev = hw->dev[i]; if (dev) { netif_device_attach(dev); - if (netif_running(dev)) + if(netif_running(dev)) skge_up(dev); } } diff --git a/trunk/drivers/net/skge.h b/trunk/drivers/net/skge.h index 14d0cc01fb9a..36c62b68fab4 100644 --- a/trunk/drivers/net/skge.h +++ b/trunk/drivers/net/skge.h @@ -7,6 +7,31 @@ /* PCI config registers */ #define PCI_DEV_REG1 0x40 #define PCI_DEV_REG2 0x44 +#ifndef PCI_VPD +#define PCI_VPD 0x50 +#endif + +/* PCI_OUR_REG_2 32 bit Our Register 2 */ +enum { + PCI_VPD_WR_THR = 0xff<<24, /* Bit 31..24: VPD Write Threshold */ + PCI_DEV_SEL = 0x7f<<17, /* Bit 23..17: EEPROM Device Select */ + PCI_VPD_ROM_SZ = 7 <<14, /* Bit 16..14: VPD ROM Size */ + /* Bit 13..12: reserved */ + PCI_EN_DUMMY_RD = 1<<3, /* Enable Dummy Read */ + PCI_REV_DESC = 1<<2, /* Reverse Desc. Bytes */ + PCI_USEDATA64 = 1<<0, /* Use 64Bit Data bus ext */ +}; + +/* PCI_VPD_ADR_REG 16 bit VPD Address Register */ +enum { + PCI_VPD_FLAG = 1<<15, /* starts VPD rd/wr cycle */ + PCI_VPD_ADR_MSK =0x7fffL, /* Bit 14.. 0: VPD Address Mask */ + VPD_RES_ID = 0x82, + VPD_RES_READ = 0x90, + VPD_RES_WRITE = 0x81, + VPD_RES_END = 0x78, +}; + #define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ PCI_STATUS_SIG_SYSTEM_ERROR | \ @@ -14,6 +39,7 @@ PCI_STATUS_REC_TARGET_ABORT | \ PCI_STATUS_PARITY) + enum csr_regs { B0_RAP = 0x0000, B0_CTST = 0x0004, @@ -203,11 +229,8 @@ enum { IS_XA2_F = 1<<1, /* Q_XA2 End of Frame */ IS_XA2_C = 1<<0, /* Q_XA2 Encoding Error */ - IS_TO_PORT1 = IS_PA_TO_RX1 | IS_PA_TO_TX1, - IS_TO_PORT2 = IS_PA_TO_RX2 | IS_PA_TO_TX2, - - IS_PORT_1 = IS_XA1_F| IS_R1_F | IS_TO_PORT1 | IS_MAC1, - IS_PORT_2 = IS_XA2_F| IS_R2_F | IS_TO_PORT2 | IS_MAC2, + IS_PORT_1 = IS_XA1_F| IS_R1_F| IS_MAC1, + IS_PORT_2 = IS_XA2_F| IS_R2_F| IS_MAC2, }; @@ -265,6 +288,14 @@ enum { CHIP_REV_YU_LITE_A3 = 7, /* Chip Rev. for YUKON-Lite A3 */ }; +/* B2_LD_TEST 8 bit EPROM loader test register */ +enum { + LD_T_ON = 1<<3, /* Loader Test mode on */ + LD_T_OFF = 1<<2, /* Loader Test mode off */ + LD_T_STEP = 1<<1, /* Decrement FPROM addr. Counter */ + LD_START = 1<<0, /* Start loading FPROM */ +}; + /* B2_TI_CTRL 8 bit Timer control */ /* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */ enum { @@ -282,6 +313,16 @@ enum { TIM_T_STEP = 1<<0, /* Test step */ }; +/* B28_DPT_INI 32 bit Descriptor Poll Timer Init Val */ +/* B28_DPT_VAL 32 bit Descriptor Poll Timer Curr Val */ +/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */ +enum { + DPT_MSK = 0x00ffffffL, /* Bit 23.. 0: Desc Poll Timer Bits */ + + DPT_START = 1<<1, /* Start Descriptor Poll Timer */ + DPT_STOP = 1<<0, /* Stop Descriptor Poll Timer */ +}; + /* B2_GP_IO 32 bit General Purpose I/O Register */ enum { GP_DIR_9 = 1<<25, /* IO_9 direct, 0=In/1=Out */ @@ -307,6 +348,30 @@ enum { GP_IO_0 = 1<<0, /* IO_0 pin */ }; +/* Rx/Tx Path related Arbiter Test Registers */ +/* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */ +/* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */ +/* B3_PA_TEST 16 bit Packet Arbiter Test Register */ +/* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */ +enum { + TX2_T_EV = 1<<15,/* TX2 Timeout/Recv Event occured */ + TX2_T_ON = 1<<14,/* TX2 Timeout/Recv Timer Test On */ + TX2_T_OFF = 1<<13,/* TX2 Timeout/Recv Timer Tst Off */ + TX2_T_STEP = 1<<12,/* TX2 Timeout/Recv Timer Step */ + TX1_T_EV = 1<<11,/* TX1 Timeout/Recv Event occured */ + TX1_T_ON = 1<<10,/* TX1 Timeout/Recv Timer Test On */ + TX1_T_OFF = 1<<9, /* TX1 Timeout/Recv Timer Tst Off */ + TX1_T_STEP = 1<<8, /* TX1 Timeout/Recv Timer Step */ + RX2_T_EV = 1<<7, /* RX2 Timeout/Recv Event occured */ + RX2_T_ON = 1<<6, /* RX2 Timeout/Recv Timer Test On */ + RX2_T_OFF = 1<<5, /* RX2 Timeout/Recv Timer Tst Off */ + RX2_T_STEP = 1<<4, /* RX2 Timeout/Recv Timer Step */ + RX1_T_EV = 1<<3, /* RX1 Timeout/Recv Event occured */ + RX1_T_ON = 1<<2, /* RX1 Timeout/Recv Timer Test On */ + RX1_T_OFF = 1<<1, /* RX1 Timeout/Recv Timer Tst Off */ + RX1_T_STEP = 1<<0, /* RX1 Timeout/Recv Timer Step */ +}; + /* Descriptor Bit Definition */ /* TxCtrl Transmit Buffer Control Field */ /* RxCtrl Receive Buffer Control Field */ @@ -363,6 +428,14 @@ enum { RI_RST_SET = 1<<0, /* Set RAM Interface Reset */ }; +/* B3_RI_TEST 8 bit RAM Iface Test Register */ +enum { + RI_T_EV = 1<<3, /* Timeout Event occured */ + RI_T_ON = 1<<2, /* Timeout Timer Test On */ + RI_T_OFF = 1<<1, /* Timeout Timer Test Off */ + RI_T_STEP = 1<<0, /* Timeout Timer Step */ +}; + /* MAC Arbiter Registers */ /* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */ enum { @@ -379,6 +452,19 @@ enum { #define SK_PKT_TO_MAX 0xffff /* Maximum value */ #define SK_RI_TO_53 36 /* RAM interface timeout */ + +/* B3_MA_RC_CTRL 16 bit MAC Arbiter Recovery Ctrl Reg */ +enum { + MA_ENA_REC_TX2 = 1<<7, /* Enable Recovery Timer TX2 */ + MA_DIS_REC_TX2 = 1<<6, /* Disable Recovery Timer TX2 */ + MA_ENA_REC_TX1 = 1<<5, /* Enable Recovery Timer TX1 */ + MA_DIS_REC_TX1 = 1<<4, /* Disable Recovery Timer TX1 */ + MA_ENA_REC_RX2 = 1<<3, /* Enable Recovery Timer RX2 */ + MA_DIS_REC_RX2 = 1<<2, /* Disable Recovery Timer RX2 */ + MA_ENA_REC_RX1 = 1<<1, /* Enable Recovery Timer RX1 */ + MA_DIS_REC_RX1 = 1<<0, /* Disable Recovery Timer RX1 */ +}; + /* Packet Arbiter Registers */ /* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ enum { @@ -402,7 +488,7 @@ enum { PA_ENA_TO_TX1 | PA_ENA_TO_TX2) -/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */ +/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ /* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ /* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ /* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ @@ -425,7 +511,7 @@ enum { /* * Bank 4 - 5 */ -/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */ +/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ enum { TXA_ITI_INI = 0x0200,/* 32 bit Tx Arb Interval Timer Init Val*/ TXA_ITI_VAL = 0x0204,/* 32 bit Tx Arb Interval Timer Value */ @@ -451,7 +537,7 @@ enum { /* Queue Register Offsets, use Q_ADDR() to access */ enum { - B8_Q_REGS = 0x0400, /* base of Queue registers */ + B8_Q_REGS = 0x0400, /* base of Queue registers */ Q_D = 0x00, /* 8*32 bit Current Descriptor */ Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */ Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */ @@ -532,7 +618,8 @@ enum { enum { PHY_ADDR_XMAC = 0<<8, PHY_ADDR_BCOM = 1<<8, - + PHY_ADDR_LONE = 3<<8, + PHY_ADDR_NAT = 0<<8, /* GPHY address (bits 15..11 of SMI control reg) */ PHY_ADDR_MARV = 0, }; @@ -899,7 +986,7 @@ enum { LINKLED_BLINK_OFF = 0x10, LINKLED_BLINK_ON = 0x20, }; - + /* GMAC and GPHY Control Registers (YUKON only) */ enum { GMAC_CTRL = 0x0f00,/* 32 bit GMAC Control Reg */ @@ -1064,6 +1151,54 @@ enum { PHY_MARV_FE_SPEC_2 = 0x1c,/* 16 bit r/w Specific Control Reg. 2 */ }; +/* Level One-PHY Registers, indirect addressed over XMAC */ +enum { + PHY_LONE_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ + PHY_LONE_STAT = 0x01,/* 16 bit r/o PHY Status Register */ + PHY_LONE_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ + PHY_LONE_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ + PHY_LONE_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ + PHY_LONE_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */ + PHY_LONE_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ + PHY_LONE_NEPG = 0x07,/* 16 bit r/w Next Page Register */ + PHY_LONE_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */ + /* Level One-specific registers */ + PHY_LONE_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */ + PHY_LONE_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */ + PHY_LONE_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */ + PHY_LONE_PORT_CFG = 0x10,/* 16 bit r/w Port Configuration Reg*/ + PHY_LONE_Q_STAT = 0x11,/* 16 bit r/o Quick Status Reg */ + PHY_LONE_INT_ENAB = 0x12,/* 16 bit r/w Interrupt Enable Reg */ + PHY_LONE_INT_STAT = 0x13,/* 16 bit r/o Interrupt Status Reg */ + PHY_LONE_LED_CFG = 0x14,/* 16 bit r/w LED Configuration Reg */ + PHY_LONE_PORT_CTRL = 0x15,/* 16 bit r/w Port Control Reg */ + PHY_LONE_CIM = 0x16,/* 16 bit r/o CIM Reg */ +}; + +/* National-PHY Registers, indirect addressed over XMAC */ +enum { + PHY_NAT_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ + PHY_NAT_STAT = 0x01,/* 16 bit r/w PHY Status Register */ + PHY_NAT_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ + PHY_NAT_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ + PHY_NAT_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ + PHY_NAT_AUNE_LP = 0x05,/* 16 bit r/o Link Partner Ability Reg */ + PHY_NAT_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ + PHY_NAT_NEPG = 0x07,/* 16 bit r/w Next Page Register */ + PHY_NAT_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner Reg */ + /* National-specific registers */ + PHY_NAT_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */ + PHY_NAT_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */ + PHY_NAT_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Register */ + PHY_NAT_EXT_CTRL1 = 0x10,/* 16 bit r/o Extended Control Reg1 */ + PHY_NAT_Q_STAT1 = 0x11,/* 16 bit r/o Quick Status Reg1 */ + PHY_NAT_10B_OP = 0x12,/* 16 bit r/o 10Base-T Operations Reg */ + PHY_NAT_EXT_CTRL2 = 0x13,/* 16 bit r/o Extended Control Reg1 */ + PHY_NAT_Q_STAT2 = 0x14,/* 16 bit r/o Quick Status Reg2 */ + + PHY_NAT_PHY_ADDR = 0x19,/* 16 bit r/o PHY Address Register */ +}; + enum { PHY_CT_RESET = 1<<15, /* Bit 15: (sc) clear all PHY related regs */ PHY_CT_LOOP = 1<<14, /* Bit 14: enable Loopback over PHY */ @@ -1118,29 +1253,8 @@ enum { PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */ }; -/* Advertisement register bits */ enum { PHY_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */ - PHY_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */ - PHY_AN_RF = 1<<13, /* Bit 13: Remote Fault Bits */ - - PHY_AN_PAUSE_ASYM = 1<<11,/* Bit 11: Try for asymmetric */ - PHY_AN_PAUSE_CAP = 1<<10, /* Bit 10: Try for pause */ - PHY_AN_100BASE4 = 1<<9, /* Bit 9: Try for 100mbps 4k packets */ - PHY_AN_100FULL = 1<<8, /* Bit 8: Try for 100mbps full-duplex */ - PHY_AN_100HALF = 1<<7, /* Bit 7: Try for 100mbps half-duplex */ - PHY_AN_10FULL = 1<<6, /* Bit 6: Try for 10mbps full-duplex */ - PHY_AN_10HALF = 1<<5, /* Bit 5: Try for 10mbps half-duplex */ - PHY_AN_CSMA = 1<<0, /* Bit 0: Only selector supported */ - PHY_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/ - PHY_AN_FULL = PHY_AN_100FULL | PHY_AN_10FULL | PHY_AN_CSMA, - PHY_AN_ALL = PHY_AN_10HALF | PHY_AN_10FULL | - PHY_AN_100HALF | PHY_AN_100FULL, -}; - -/* Xmac Specific */ -enum { - PHY_X_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */ PHY_X_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */ PHY_X_AN_RFB = 3<<12,/* Bit 13..12: Remote Fault Bits */ @@ -1149,6 +1263,82 @@ enum { PHY_X_AN_FD = 1<<5, /* Bit 5: Full Duplex */ }; +enum { + PHY_B_AN_RF = 1<<13, /* Bit 13: Remote Fault */ + + PHY_B_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */ + PHY_B_AN_PC = 1<<10, /* Bit 10: Pause Capable */ + PHY_B_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/ +}; + +enum { + PHY_L_AN_RF = 1<<13, /* Bit 13: Remote Fault */ + /* Bit 12: reserved */ + PHY_L_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */ + PHY_L_AN_PC = 1<<10, /* Bit 10: Pause Capable */ + + PHY_L_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/ +}; + +/* PHY_NAT_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement */ +/* PHY_NAT_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ +/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ +enum { + PHY_N_AN_RF = 1<<13, /* Bit 13: Remote Fault */ + + PHY_N_AN_100F = 1<<11, /* Bit 11: 100Base-T2 FD Support */ + PHY_N_AN_100H = 1<<10, /* Bit 10: 100Base-T2 HD Support */ + + PHY_N_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/ +}; + +/* field type definition for PHY_x_AN_SEL */ +enum { + PHY_SEL_TYPE = 1, /* 00001 = Ethernet */ +}; + +enum { + PHY_ANE_LP_NP = 1<<3, /* Bit 3: Link Partner can Next Page */ + PHY_ANE_LOC_NP = 1<<2, /* Bit 2: Local PHY can Next Page */ + PHY_ANE_RX_PG = 1<<1, /* Bit 1: Page Received */ +}; + +enum { + PHY_ANE_PAR_DF = 1<<4, /* Bit 4: Parallel Detection Fault */ + + PHY_ANE_LP_CAP = 1<<0, /* Bit 0: Link Partner Auto-Neg. Cap. */ +}; + +enum { + PHY_NP_MORE = 1<<15, /* Bit 15: More, Next Pages to follow */ + PHY_NP_ACK1 = 1<<14, /* Bit 14: (ro) Ack1, for receiving a message */ + PHY_NP_MSG_VAL = 1<<13, /* Bit 13: Message Page valid */ + PHY_NP_ACK2 = 1<<12, /* Bit 12: Ack2, comply with msg content */ + PHY_NP_TOG = 1<<11, /* Bit 11: Toggle Bit, ensure sync */ + PHY_NP_MSG = 0x07ff, /* Bit 10..0: Message from/to Link Partner */ +}; + +enum { + PHY_X_EX_FD = 1<<15, /* Bit 15: Device Supports Full Duplex */ + PHY_X_EX_HD = 1<<14, /* Bit 14: Device Supports Half Duplex */ +}; + +enum { + PHY_X_RS_PAUSE = 3<<7,/* Bit 8..7: selected Pause Mode */ + PHY_X_RS_HD = 1<<6, /* Bit 6: Half Duplex Mode selected */ + PHY_X_RS_FD = 1<<5, /* Bit 5: Full Duplex Mode selected */ + PHY_X_RS_ABLMIS = 1<<4, /* Bit 4: duplex or pause cap mismatch */ + PHY_X_RS_PAUMIS = 1<<3, /* Bit 3: pause capability mismatch */ +}; + +/** Remote Fault Bits (PHY_X_AN_RFB) encoding */ +enum { + X_RFB_OK = 0<<12,/* Bit 13..12 No errors, Link OK */ + X_RFB_LF = 1<<12, /* Bit 13..12 Link Failure */ + X_RFB_OFF = 2<<12,/* Bit 13..12 Offline */ + X_RFB_AN_ERR = 3<<12,/* Bit 13..12 Auto-Negotiation Error */ +}; + /* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */ enum { PHY_X_P_NO_PAUSE = 0<<7,/* Bit 8..7: no Pause Mode */ @@ -1228,16 +1418,6 @@ enum { PHY_B_PES_MLT3_ER = 1<<0, /* Bit 0: MLT3 code Error */ }; -/* PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/* PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -enum { - PHY_B_AN_RF = 1<<13, /* Bit 13: Remote Fault */ - - PHY_B_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */ - PHY_B_AN_PC = 1<<10, /* Bit 10: Pause Capable */ -}; - - /***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/ enum { PHY_B_FC_CTR = 0xff, /* Bit 7..0: False Carrier Counter */ @@ -1298,9 +1478,7 @@ enum { PHY_B_IS_LST_CHANGE = 1<<1, /* Bit 1: Link Status Changed */ PHY_B_IS_CRC_ER = 1<<0, /* Bit 0: CRC Error */ }; -#define PHY_B_DEF_MSK \ - (~(PHY_B_IS_PSE | PHY_B_IS_AN_PR | PHY_B_IS_DUP_CHANGE | \ - PHY_B_IS_LSP_CHANGE | PHY_B_IS_LST_CHANGE)) +#define PHY_B_DEF_MSK (~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) /* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */ enum { @@ -1317,6 +1495,166 @@ enum { PHY_B_RES_1000HD = 6<<8,/* Bit 10..8: 1000Base-T Half Dup. */ }; +/* + * Level One-Specific + */ +/***** PHY_LONE_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ +enum { + PHY_L_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */ + PHY_L_1000C_MSE = 1<<12, /* Bit 12: Master/Slave Enable */ + PHY_L_1000C_MSC = 1<<11, /* Bit 11: M/S Configuration */ + PHY_L_1000C_RD = 1<<10, /* Bit 10: Repeater/DTE */ + PHY_L_1000C_AFD = 1<<9, /* Bit 9: Advertise Full Duplex */ + PHY_L_1000C_AHD = 1<<8, /* Bit 8: Advertise Half Duplex */ +}; + +/***** PHY_LONE_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ +enum { + PHY_L_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */ + PHY_L_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */ + PHY_L_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */ + PHY_L_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status */ + PHY_L_1000S_LP_FD = 1<<11, /* Bit 11: Link Partner can FD */ + PHY_L_1000S_LP_HD = 1<<10, /* Bit 10: Link Partner can HD */ + + PHY_L_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */ + +/***** PHY_LONE_EXT_STAT 16 bit r/o Extended Status Register *****/ + PHY_L_ES_X_FD_CAP = 1<<15, /* Bit 15: 1000Base-X FD capable */ + PHY_L_ES_X_HD_CAP = 1<<14, /* Bit 14: 1000Base-X HD capable */ + PHY_L_ES_T_FD_CAP = 1<<13, /* Bit 13: 1000Base-T FD capable */ + PHY_L_ES_T_HD_CAP = 1<<12, /* Bit 12: 1000Base-T HD capable */ +}; + +/***** PHY_LONE_PORT_CFG 16 bit r/w Port Configuration Reg *****/ +enum { + PHY_L_PC_REP_MODE = 1<<15, /* Bit 15: Repeater Mode */ + + PHY_L_PC_TX_DIS = 1<<13, /* Bit 13: Tx output Disabled */ + PHY_L_PC_BY_SCR = 1<<12, /* Bit 12: Bypass Scrambler */ + PHY_L_PC_BY_45 = 1<<11, /* Bit 11: Bypass 4B5B-Decoder */ + PHY_L_PC_JAB_DIS = 1<<10, /* Bit 10: Jabber Disabled */ + PHY_L_PC_SQE = 1<<9, /* Bit 9: Enable Heartbeat */ + PHY_L_PC_TP_LOOP = 1<<8, /* Bit 8: TP Loopback */ + PHY_L_PC_SSS = 1<<7, /* Bit 7: Smart Speed Selection */ + PHY_L_PC_FIFO_SIZE = 1<<6, /* Bit 6: FIFO Size */ + PHY_L_PC_PRE_EN = 1<<5, /* Bit 5: Preamble Enable */ + PHY_L_PC_CIM = 1<<4, /* Bit 4: Carrier Integrity Mon */ + PHY_L_PC_10_SER = 1<<3, /* Bit 3: Use Serial Output */ + PHY_L_PC_ANISOL = 1<<2, /* Bit 2: Unisolate Port */ + PHY_L_PC_TEN_BIT = 1<<1, /* Bit 1: 10bit iface mode on */ + PHY_L_PC_ALTCLOCK = 1<<0, /* Bit 0: (ro) ALTCLOCK Mode on */ +}; + +/***** PHY_LONE_Q_STAT 16 bit r/o Quick Status Reg *****/ +enum { + PHY_L_QS_D_RATE = 3<<14,/* Bit 15..14: Data Rate */ + PHY_L_QS_TX_STAT = 1<<13, /* Bit 13: Transmitting */ + PHY_L_QS_RX_STAT = 1<<12, /* Bit 12: Receiving */ + PHY_L_QS_COL_STAT = 1<<11, /* Bit 11: Collision */ + PHY_L_QS_L_STAT = 1<<10, /* Bit 10: Link is up */ + PHY_L_QS_DUP_MOD = 1<<9, /* Bit 9: Full/Half Duplex */ + PHY_L_QS_AN = 1<<8, /* Bit 8: AutoNeg is On */ + PHY_L_QS_AN_C = 1<<7, /* Bit 7: AN is Complete */ + PHY_L_QS_LLE = 7<<4,/* Bit 6..4: Line Length Estim. */ + PHY_L_QS_PAUSE = 1<<3, /* Bit 3: LP advertised Pause */ + PHY_L_QS_AS_PAUSE = 1<<2, /* Bit 2: LP adv. asym. Pause */ + PHY_L_QS_ISOLATE = 1<<1, /* Bit 1: CIM Isolated */ + PHY_L_QS_EVENT = 1<<0, /* Bit 0: Event has occurred */ +}; + +/***** PHY_LONE_INT_ENAB 16 bit r/w Interrupt Enable Reg *****/ +/***** PHY_LONE_INT_STAT 16 bit r/o Interrupt Status Reg *****/ +enum { + PHY_L_IS_AN_F = 1<<13, /* Bit 13: Auto-Negotiation fault */ + PHY_L_IS_CROSS = 1<<11, /* Bit 11: Crossover used */ + PHY_L_IS_POL = 1<<10, /* Bit 10: Polarity correct. used */ + PHY_L_IS_SS = 1<<9, /* Bit 9: Smart Speed Downgrade */ + PHY_L_IS_CFULL = 1<<8, /* Bit 8: Counter Full */ + PHY_L_IS_AN_C = 1<<7, /* Bit 7: AutoNeg Complete */ + PHY_L_IS_SPEED = 1<<6, /* Bit 6: Speed Changed */ + PHY_L_IS_DUP = 1<<5, /* Bit 5: Duplex Changed */ + PHY_L_IS_LS = 1<<4, /* Bit 4: Link Status Changed */ + PHY_L_IS_ISOL = 1<<3, /* Bit 3: Isolate Occured */ + PHY_L_IS_MDINT = 1<<2, /* Bit 2: (ro) STAT: MII Int Pending */ + PHY_L_IS_INTEN = 1<<1, /* Bit 1: ENAB: Enable IRQs */ + PHY_L_IS_FORCE = 1<<0, /* Bit 0: ENAB: Force Interrupt */ +}; + +/* int. mask */ +#define PHY_L_DEF_MSK (PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN) + +/***** PHY_LONE_LED_CFG 16 bit r/w LED Configuration Reg *****/ +enum { + PHY_L_LC_LEDC = 3<<14,/* Bit 15..14: Col/Blink/On/Off */ + PHY_L_LC_LEDR = 3<<12,/* Bit 13..12: Rx/Blink/On/Off */ + PHY_L_LC_LEDT = 3<<10,/* Bit 11..10: Tx/Blink/On/Off */ + PHY_L_LC_LEDG = 3<<8,/* Bit 9..8: Giga/Blink/On/Off */ + PHY_L_LC_LEDS = 3<<6,/* Bit 7..6: 10-100/Blink/On/Off */ + PHY_L_LC_LEDL = 3<<4,/* Bit 5..4: Link/Blink/On/Off */ + PHY_L_LC_LEDF = 3<<2,/* Bit 3..2: Duplex/Blink/On/Off */ + PHY_L_LC_PSTRECH= 1<<1, /* Bit 1: Strech LED Pulses */ + PHY_L_LC_FREQ = 1<<0, /* Bit 0: 30/100 ms */ +}; + +/***** PHY_LONE_PORT_CTRL 16 bit r/w Port Control Reg *****/ +enum { + PHY_L_PC_TX_TCLK = 1<<15, /* Bit 15: Enable TX_TCLK */ + PHY_L_PC_ALT_NP = 1<<13, /* Bit 14: Alternate Next Page */ + PHY_L_PC_GMII_ALT= 1<<12, /* Bit 13: Alternate GMII driver */ + PHY_L_PC_TEN_CRS = 1<<10, /* Bit 10: Extend CRS*/ +}; + +/***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/ +enum { + PHY_L_CIM_ISOL = 0xff<<8,/* Bit 15..8: Isolate Count */ + PHY_L_CIM_FALSE_CAR = 0xff, /* Bit 7..0: False Carrier Count */ +}; + +/* + * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding + */ +enum { + PHY_L_P_NO_PAUSE= 0<<10,/* Bit 11..10: no Pause Mode */ + PHY_L_P_SYM_MD = 1<<10, /* Bit 11..10: symmetric Pause Mode */ + PHY_L_P_ASYM_MD = 2<<10,/* Bit 11..10: asymmetric Pause Mode */ + PHY_L_P_BOTH_MD = 3<<10,/* Bit 11..10: both Pause Mode */ +}; + +/* + * National-Specific + */ +/***** PHY_NAT_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ +enum { + PHY_N_1000C_TEST= 7<<13,/* Bit 15..13: Test Modes */ + PHY_N_1000C_MSE = 1<<12, /* Bit 12: Master/Slave Enable */ + PHY_N_1000C_MSC = 1<<11, /* Bit 11: M/S Configuration */ + PHY_N_1000C_RD = 1<<10, /* Bit 10: Repeater/DTE */ + PHY_N_1000C_AFD = 1<<9, /* Bit 9: Advertise Full Duplex */ + PHY_N_1000C_AHD = 1<<8, /* Bit 8: Advertise Half Duplex */ + PHY_N_1000C_APC = 1<<7, /* Bit 7: Asymmetric Pause Cap. */}; + + +/***** PHY_NAT_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ +enum { + PHY_N_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */ + PHY_N_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */ + PHY_N_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */ + PHY_N_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status*/ + PHY_N_1000S_LP_FD= 1<<11, /* Bit 11: Link Partner can FD */ + PHY_N_1000S_LP_HD= 1<<10, /* Bit 10: Link Partner can HD */ + PHY_N_1000C_LP_APC= 1<<9, /* Bit 9: LP Asym. Pause Cap. */ + PHY_N_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */ +}; + +/***** PHY_NAT_EXT_STAT 16 bit r/o Extended Status Register *****/ +enum { + PHY_N_ES_X_FD_CAP= 1<<15, /* Bit 15: 1000Base-X FD capable */ + PHY_N_ES_X_HD_CAP= 1<<14, /* Bit 14: 1000Base-X HD capable */ + PHY_N_ES_T_FD_CAP= 1<<13, /* Bit 13: 1000Base-T FD capable */ + PHY_N_ES_T_HD_CAP= 1<<12, /* Bit 12: 1000Base-T HD capable */ +}; + /** Marvell-Specific */ enum { PHY_M_AN_NXT_PG = 1<<15, /* Request Next Page */ @@ -1380,7 +1718,7 @@ enum { PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */ }; -#define PHY_M_PC_MDI_XMODE(x) (((x)<<5) & PHY_M_PC_MDIX_MSK) +#define PHY_M_PC_MDI_XMODE(x) (((x)<<5) & PHY_M_PC_MDIX_MSK) enum { PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */ @@ -1767,7 +2105,7 @@ enum { GM_GPSR_FC_RX_DIS = 1<<2, /* Bit 2: Rx Flow-Control Mode Disabled */ GM_GPSR_PROM_EN = 1<<1, /* Bit 1: Promiscuous Mode Enabled */ }; - + /* GM_GP_CTRL 16 bit r/w General Purpose Control Register */ enum { GM_GPCR_PROM_ENA = 1<<14, /* Bit 14: Enable Promiscuous Mode */ @@ -1789,7 +2127,7 @@ enum { #define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100) #define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS) - + /* GM_TX_CTRL 16 bit r/w Transmit Control Register */ enum { GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */ @@ -1800,7 +2138,7 @@ enum { #define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK) #define TX_COL_DEF 0x04 - + /* GM_RX_CTRL 16 bit r/w Receive Control Register */ enum { GM_RXCR_UCF_ENA = 1<<15, /* Bit 15: Enable Unicast filtering */ @@ -1808,7 +2146,7 @@ enum { GM_RXCR_CRC_DIS = 1<<13, /* Bit 13: Remove 4-byte CRC */ GM_RXCR_PASS_FC = 1<<12, /* Bit 12: Pass FC packets to FIFO */ }; - + /* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */ enum { GM_TXPA_JAMLEN_MSK = 0x03<<14, /* Bit 15..14: Jam Length */ @@ -1833,7 +2171,7 @@ enum { GM_SMOD_JUMBO_ENA = 1<<8, /* Bit 8: Enable Jumbo (Max. Frame Len) */ GM_SMOD_IPG_MSK = 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */ }; - + #define DATA_BLIND_VAL(x) (((x)<<11) & GM_SMOD_DATABL_MSK) #define DATA_BLIND_DEF 0x04 @@ -1848,7 +2186,7 @@ enum { GM_SMI_CT_RD_VAL = 1<<4, /* Bit 4: Read Valid (Read completed) */ GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */ }; - + #define GM_SMI_CT_PHY_AD(x) (((x)<<11) & GM_SMI_CT_PHY_A_MSK) #define GM_SMI_CT_REG_AD(x) (((x)<<6) & GM_SMI_CT_REG_A_MSK) @@ -1857,7 +2195,7 @@ enum { GM_PAR_MIB_CLR = 1<<5, /* Bit 5: Set MIB Clear Counter Mode */ GM_PAR_MIB_TST = 1<<4, /* Bit 4: MIB Load Counter (Test Mode) */ }; - + /* Receive Frame Status Encoding */ enum { GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */ @@ -1879,12 +2217,12 @@ enum { /* * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR) */ - GMR_FS_ANY_ERR = GMR_FS_CRC_ERR | GMR_FS_LONG_ERR | - GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC | + GMR_FS_ANY_ERR = GMR_FS_CRC_ERR | GMR_FS_LONG_ERR | + GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC | GMR_FS_JABBER, /* Rx GMAC FIFO Flush Mask (default) */ RX_FF_FL_DEF_MSK = GMR_FS_CRC_ERR | GMR_FS_RX_FF_OV |GMR_FS_MII_ERR | - GMR_FS_BAD_FC | GMR_FS_GOOD_FC | GMR_FS_UN_SIZE | + GMR_FS_BAD_FC | GMR_FS_GOOD_FC | GMR_FS_UN_SIZE | GMR_FS_JABBER, }; @@ -2202,6 +2540,10 @@ enum { }; +/* XM_PHY_ADDR 16 bit r/w PHY Address Register */ +#define XM_PHY_ADDR_SZ 0x1f /* Bit 4..0: PHY Address bits */ + + /* XM_GP_PORT 32 bit r/w General Purpose Port Register */ enum { XM_GP_ANIP = 1<<6, /* Bit 6: (ro) Auto-Neg. in progress */ @@ -2320,8 +2662,8 @@ enum { }; #define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I) -#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\ - XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA) +#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\ + XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA) /* XM_STAT_CMD 16 bit r/w Statistics Command Register */ enum { @@ -2451,20 +2793,28 @@ struct skge_hw { u32 intr_mask; struct net_device *dev[2]; + u8 mac_cfg; u8 chip_id; - u8 chip_rev; u8 phy_type; u8 pmd_type; u16 phy_addr; - u8 ports; u32 ram_size; u32 ram_offset; - + struct tasklet_struct ext_tasklet; spinlock_t phy_lock; }; +static inline int isdualport(const struct skge_hw *hw) +{ + return !(hw->mac_cfg & CFG_SNG_MAC); +} + +static inline u8 chip_rev(const struct skge_hw *hw) +{ + return (hw->mac_cfg & CFG_CHIP_R_MSK) >> 4; +} static inline int iscopper(const struct skge_hw *hw) { @@ -2477,7 +2827,7 @@ enum { FLOW_MODE_REM_SEND = 2, /* Symmetric or just remote */ FLOW_MODE_SYMMETRIC = 3, /* Both stations may send PAUSE */ }; - + struct skge_port { u32 msg_enable; struct skge_hw *hw; @@ -2503,8 +2853,8 @@ struct skge_port { void *mem; /* PCI memory for rings */ dma_addr_t dma; unsigned long mem_size; - unsigned int rx_buf_size; + struct timer_list link_check; struct timer_list led_blink; }; @@ -2513,6 +2863,7 @@ struct skge_port { static inline u32 skge_read32(const struct skge_hw *hw, int reg) { return readl(hw->regs + reg); + } static inline u16 skge_read16(const struct skge_hw *hw, int reg) @@ -2541,87 +2892,114 @@ static inline void skge_write8(const struct skge_hw *hw, int reg, u8 val) } /* MAC Related Registers inside the device. */ -#define SK_REG(port,reg) (((port)<<7)+(reg)) -#define SK_XMAC_REG(port, reg) \ +#define SKGEMAC_REG(port,reg) (((port)<<7)+(reg)) + +/* PCI config space can be accessed via memory mapped space */ +#define SKGEPCI_REG(reg) ((reg)+ 0x380) + +#define SKGEXM_REG(port, reg) \ ((BASE_XMAC_1 + (port) * (BASE_XMAC_2 - BASE_XMAC_1)) | (reg) << 1) -static inline u32 xm_read32(const struct skge_hw *hw, int port, int reg) +static inline u32 skge_xm_read32(const struct skge_hw *hw, int port, int reg) +{ + return skge_read32(hw, SKGEXM_REG(port,reg)); +} + +static inline u16 skge_xm_read16(const struct skge_hw *hw, int port, int reg) { - u32 v; - v = skge_read16(hw, SK_XMAC_REG(port, reg)); - v |= (u32)skge_read16(hw, SK_XMAC_REG(port, reg+2)) << 16; - return v; + return skge_read16(hw, SKGEXM_REG(port,reg)); } -static inline u16 xm_read16(const struct skge_hw *hw, int port, int reg) +static inline u8 skge_xm_read8(const struct skge_hw *hw, int port, int reg) { - return skge_read16(hw, SK_XMAC_REG(port,reg)); + return skge_read8(hw, SKGEXM_REG(port,reg)); } -static inline void xm_write32(const struct skge_hw *hw, int port, int r, u32 v) +static inline void skge_xm_write32(const struct skge_hw *hw, int port, int r, u32 v) { - skge_write16(hw, SK_XMAC_REG(port,r), v & 0xffff); - skge_write16(hw, SK_XMAC_REG(port,r+2), v >> 16); + skge_write32(hw, SKGEXM_REG(port,r), v); } -static inline void xm_write16(const struct skge_hw *hw, int port, int r, u16 v) +static inline void skge_xm_write16(const struct skge_hw *hw, int port, int r, u16 v) { - skge_write16(hw, SK_XMAC_REG(port,r), v); + skge_write16(hw, SKGEXM_REG(port,r), v); } -static inline void xm_outhash(const struct skge_hw *hw, int port, int reg, +static inline void skge_xm_write8(const struct skge_hw *hw, int port, int r, u8 v) +{ + skge_write8(hw, SKGEXM_REG(port,r), v); +} + +static inline void skge_xm_outhash(const struct skge_hw *hw, int port, int reg, const u8 *hash) { - xm_write16(hw, port, reg, (u16)hash[0] | ((u16)hash[1] << 8)); - xm_write16(hw, port, reg+2, (u16)hash[2] | ((u16)hash[3] << 8)); - xm_write16(hw, port, reg+4, (u16)hash[4] | ((u16)hash[5] << 8)); - xm_write16(hw, port, reg+6, (u16)hash[6] | ((u16)hash[7] << 8)); + skge_xm_write16(hw, port, reg, + (u16)hash[0] | ((u16)hash[1] << 8)); + skge_xm_write16(hw, port, reg+2, + (u16)hash[2] | ((u16)hash[3] << 8)); + skge_xm_write16(hw, port, reg+4, + (u16)hash[4] | ((u16)hash[5] << 8)); + skge_xm_write16(hw, port, reg+6, + (u16)hash[6] | ((u16)hash[7] << 8)); } -static inline void xm_outaddr(const struct skge_hw *hw, int port, int reg, +static inline void skge_xm_outaddr(const struct skge_hw *hw, int port, int reg, const u8 *addr) { - xm_write16(hw, port, reg, (u16)addr[0] | ((u16)addr[1] << 8)); - xm_write16(hw, port, reg+2, (u16)addr[2] | ((u16)addr[3] << 8)); - xm_write16(hw, port, reg+4, (u16)addr[4] | ((u16)addr[5] << 8)); + skge_xm_write16(hw, port, reg, + (u16)addr[0] | ((u16)addr[1] << 8)); + skge_xm_write16(hw, port, reg, + (u16)addr[2] | ((u16)addr[3] << 8)); + skge_xm_write16(hw, port, reg, + (u16)addr[4] | ((u16)addr[5] << 8)); } -#define SK_GMAC_REG(port,reg) \ - (BASE_GMAC_1 + (port) * (BASE_GMAC_2-BASE_GMAC_1) + (reg)) -static inline u16 gma_read16(const struct skge_hw *hw, int port, int reg) +#define SKGEGMA_REG(port,reg) \ + ((reg) + BASE_GMAC_1 + \ + (port) * (BASE_GMAC_2-BASE_GMAC_1)) + +static inline u16 skge_gma_read16(const struct skge_hw *hw, int port, int reg) { - return skge_read16(hw, SK_GMAC_REG(port,reg)); + return skge_read16(hw, SKGEGMA_REG(port,reg)); } -static inline u32 gma_read32(const struct skge_hw *hw, int port, int reg) +static inline u32 skge_gma_read32(const struct skge_hw *hw, int port, int reg) { - return (u32) skge_read16(hw, SK_GMAC_REG(port,reg)) - | ((u32)skge_read16(hw, SK_GMAC_REG(port,reg+4)) << 16); + return (u32) skge_read16(hw, SKGEGMA_REG(port,reg)) + | ((u32)skge_read16(hw, SKGEGMA_REG(port,reg+4)) << 16); } -static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v) +static inline u8 skge_gma_read8(const struct skge_hw *hw, int port, int reg) { - skge_write16(hw, SK_GMAC_REG(port,r), v); + return skge_read8(hw, SKGEGMA_REG(port,reg)); } -static inline void gma_write32(const struct skge_hw *hw, int port, int r, u32 v) +static inline void skge_gma_write16(const struct skge_hw *hw, int port, int r, u16 v) { - skge_write16(hw, SK_GMAC_REG(port, r), (u16) v); - skge_write32(hw, SK_GMAC_REG(port, r+4), (u16)(v >> 16)); + skge_write16(hw, SKGEGMA_REG(port,r), v); } -static inline void gma_write8(const struct skge_hw *hw, int port, int r, u8 v) +static inline void skge_gma_write32(const struct skge_hw *hw, int port, int r, u32 v) { - skge_write8(hw, SK_GMAC_REG(port,r), v); + skge_write16(hw, SKGEGMA_REG(port, r), (u16) v); + skge_write32(hw, SKGEGMA_REG(port, r+4), (u16)(v >> 16)); } -static inline void gma_set_addr(struct skge_hw *hw, int port, int reg, - const u8 *addr) +static inline void skge_gma_write8(const struct skge_hw *hw, int port, int r, u8 v) { - gma_write16(hw, port, reg, (u16) addr[0] | ((u16) addr[1] << 8)); - gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8)); - gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8)); + skge_write8(hw, SKGEGMA_REG(port,r), v); } +static inline void skge_gm_set_addr(struct skge_hw *hw, int port, int reg, + const u8 *addr) +{ + skge_gma_write16(hw, port, reg, + (u16) addr[0] | ((u16) addr[1] << 8)); + skge_gma_write16(hw, port, reg+4, + (u16) addr[2] | ((u16) addr[3] << 8)); + skge_gma_write16(hw, port, reg+8, + (u16) addr[4] | ((u16) addr[5] << 8)); +} + #endif diff --git a/trunk/drivers/net/smc91x.c b/trunk/drivers/net/smc91x.c index 1438fdd20826..cfb9d3cdb04a 100644 --- a/trunk/drivers/net/smc91x.c +++ b/trunk/drivers/net/smc91x.c @@ -1998,7 +1998,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr) if (retval) goto err_out; - set_irq_type(dev->irq, SMC_IRQ_TRIGGER_TYPE); + set_irq_type(dev->irq, IRQT_RISING); #ifdef SMC_USE_PXA_DMA { diff --git a/trunk/drivers/net/smc91x.h b/trunk/drivers/net/smc91x.h index 7089d86e857a..946528e6b742 100644 --- a/trunk/drivers/net/smc91x.h +++ b/trunk/drivers/net/smc91x.h @@ -182,16 +182,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) #define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) -#include -#include - -#define SMC_IRQ_TRIGGER_TYPE (( \ - machine_is_omap_h2() \ - || machine_is_omap_h3() \ - || (machine_is_omap_innovator() && !cpu_is_omap150()) \ - ) ? IRQT_FALLING : IRQT_RISING) - - #elif defined(CONFIG_SH_SH4202_MICRODEV) #define SMC_CAN_USE_8BIT 0 @@ -310,9 +300,6 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) #endif -#ifndef SMC_IRQ_TRIGGER_TYPE -#define SMC_IRQ_TRIGGER_TYPE IRQT_RISING -#endif #ifdef SMC_USE_PXA_DMA /* diff --git a/trunk/drivers/net/wireless/airo_cs.c b/trunk/drivers/net/wireless/airo_cs.c index f10a9523034a..fbf53af6cda4 100644 --- a/trunk/drivers/net/wireless/airo_cs.c +++ b/trunk/drivers/net/wireless/airo_cs.c @@ -559,15 +559,6 @@ static int airo_event(event_t event, int priority, return 0; } /* airo_event */ -static struct pcmcia_device_id airo_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a), - PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0005), - PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0007), - PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0007), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, airo_ids); - static struct pcmcia_driver airo_driver = { .owner = THIS_MODULE, .drv = { @@ -575,7 +566,6 @@ static struct pcmcia_driver airo_driver = { }, .attach = airo_attach, .detach = airo_detach, - .id_table = airo_ids, }; static int airo_cs_init(void) diff --git a/trunk/drivers/net/wireless/atmel_cs.c b/trunk/drivers/net/wireless/atmel_cs.c index 86379d4998ac..a4ed28d9c783 100644 --- a/trunk/drivers/net/wireless/atmel_cs.c +++ b/trunk/drivers/net/wireless/atmel_cs.c @@ -646,27 +646,6 @@ static int atmel_event(event_t event, int priority, } /* atmel_event */ /*====================================================================*/ -static struct pcmcia_device_id atmel_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0620), - PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0696), - PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x3302), - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0007), - PCMCIA_DEVICE_PROD_ID12("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9), - PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f), - PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504", 0xabda4164, 0x5040670a), - PCMCIA_DEVICE_PROD_ID12("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f), - PCMCIA_DEVICE_PROD_ID12("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5), - PCMCIA_DEVICE_PROD_ID12("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b), - PCMCIA_DEVICE_PROD_ID12("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6), - PCMCIA_DEVICE_PROD_ID12("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68), - PCMCIA_DEVICE_PROD_ID12("SMC", "2632W", 0xc4f8b18b, 0x30f38774), - PCMCIA_DEVICE_PROD_ID12("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377), - PCMCIA_DEVICE_PROD_ID12("Wireless", "PC", 0xa407ecdd, 0x556e4d7e), - PCMCIA_DEVICE_PROD_ID12("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, atmel_ids); - static struct pcmcia_driver atmel_driver = { .owner = THIS_MODULE, .drv = { @@ -674,7 +653,6 @@ static struct pcmcia_driver atmel_driver = { }, .attach = atmel_attach, .detach = atmel_detach, - .id_table = atmel_ids, }; static int atmel_cs_init(void) diff --git a/trunk/drivers/net/wireless/netwave_cs.c b/trunk/drivers/net/wireless/netwave_cs.c index e12bd75b2694..382241e7edbb 100644 --- a/trunk/drivers/net/wireless/netwave_cs.c +++ b/trunk/drivers/net/wireless/netwave_cs.c @@ -1668,12 +1668,6 @@ static int netwave_close(struct net_device *dev) { return 0; } -static struct pcmcia_device_id netwave_ids[] = { - PCMCIA_DEVICE_PROD_ID12("Xircom", "CreditCard Netwave", 0x2e3ee845, 0x54e28a28), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, netwave_ids); - static struct pcmcia_driver netwave_driver = { .owner = THIS_MODULE, .drv = { @@ -1681,7 +1675,6 @@ static struct pcmcia_driver netwave_driver = { }, .attach = netwave_attach, .detach = netwave_detach, - .id_table = netwave_ids, }; static int __init init_netwave_cs(void) diff --git a/trunk/drivers/net/wireless/orinoco_cs.c b/trunk/drivers/net/wireless/orinoco_cs.c index 597c4586d049..74a8227256aa 100644 --- a/trunk/drivers/net/wireless/orinoco_cs.c +++ b/trunk/drivers/net/wireless/orinoco_cs.c @@ -608,56 +608,6 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION " (David Gibson , " "Pavel Roskin , et al)"; -static struct pcmcia_device_id orinoco_cs_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), - PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), - PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), - PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), - PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), - PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), - PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), - PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), - PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), - PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), - PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), - PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), - PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), - PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169), - PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3), - PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), - PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), - PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), - PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac), - PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab), - PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3), - PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c), - PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), - PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), - PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410), - PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3), - PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01), - PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a), - PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1), - PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), - PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), - PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26), - PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b), - PCMCIA_DEVICE_PROD_ID1("Symbol Technologies", 0x3f02b4d6), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); - static struct pcmcia_driver orinoco_driver = { .owner = THIS_MODULE, .drv = { @@ -665,7 +615,6 @@ static struct pcmcia_driver orinoco_driver = { }, .attach = orinoco_cs_attach, .detach = orinoco_cs_detach, - .id_table = orinoco_cs_ids, }; static int __init diff --git a/trunk/drivers/net/wireless/ray_cs.c b/trunk/drivers/net/wireless/ray_cs.c index 31652af52eac..6e5bda56b8f8 100644 --- a/trunk/drivers/net/wireless/ray_cs.c +++ b/trunk/drivers/net/wireless/ray_cs.c @@ -2904,12 +2904,6 @@ static int write_int(struct file *file, const char __user *buffer, unsigned long } #endif -static struct pcmcia_device_id ray_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x01a6, 0x0000), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, ray_ids); - static struct pcmcia_driver ray_driver = { .owner = THIS_MODULE, .drv = { @@ -2917,7 +2911,6 @@ static struct pcmcia_driver ray_driver = { }, .attach = ray_attach, .detach = ray_detach, - .id_table = ray_ids, }; static int __init init_ray_cs(void) diff --git a/trunk/drivers/net/wireless/wavelan_cs.c b/trunk/drivers/net/wireless/wavelan_cs.c index 89532fd92941..ec8329788e49 100644 --- a/trunk/drivers/net/wireless/wavelan_cs.c +++ b/trunk/drivers/net/wireless/wavelan_cs.c @@ -4889,15 +4889,6 @@ wavelan_event(event_t event, /* The event received */ return 0; } -static struct pcmcia_device_id wavelan_ids[] = { - PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975), - PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06), - PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/PCMCIA", 0x23eb9949, 0x1bc50975), - PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/PCMCIA", 0x24358cd4, 0x1bc50975), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, wavelan_ids); - static struct pcmcia_driver wavelan_driver = { .owner = THIS_MODULE, .drv = { @@ -4905,7 +4896,6 @@ static struct pcmcia_driver wavelan_driver = { }, .attach = wavelan_attach, .detach = wavelan_detach, - .id_table = wavelan_ids, }; static int __init diff --git a/trunk/drivers/net/wireless/wl3501_cs.c b/trunk/drivers/net/wireless/wl3501_cs.c index e3a900482d92..1433e5aaf1b4 100644 --- a/trunk/drivers/net/wireless/wl3501_cs.c +++ b/trunk/drivers/net/wireless/wl3501_cs.c @@ -2239,12 +2239,6 @@ static int wl3501_event(event_t event, int pri, event_callback_args_t *args) return 0; } -static struct pcmcia_device_id wl3501_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, wl3501_ids); - static struct pcmcia_driver wl3501_driver = { .owner = THIS_MODULE, .drv = { @@ -2252,7 +2246,6 @@ static struct pcmcia_driver wl3501_driver = { }, .attach = wl3501_attach, .detach = wl3501_detach, - .id_table = wl3501_ids, }; static int __init wl3501_init_module(void) diff --git a/trunk/drivers/parport/parport_cs.c b/trunk/drivers/parport/parport_cs.c index ff45662c4f7c..a3fa8185af2a 100644 --- a/trunk/drivers/parport/parport_cs.c +++ b/trunk/drivers/parport/parport_cs.c @@ -373,13 +373,6 @@ int parport_event(event_t event, int priority, return 0; } /* parport_event */ -static struct pcmcia_device_id parport_ids[] = { - PCMCIA_DEVICE_FUNC_ID(3), - PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, parport_ids); - static struct pcmcia_driver parport_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -387,8 +380,6 @@ static struct pcmcia_driver parport_cs_driver = { }, .attach = parport_attach, .detach = parport_detach, - .id_table = parport_ids, - }; static int __init init_parport_cs(void) diff --git a/trunk/drivers/pcmcia/Kconfig b/trunk/drivers/pcmcia/Kconfig index 52ea34594363..14e4124e1523 100644 --- a/trunk/drivers/pcmcia/Kconfig +++ b/trunk/drivers/pcmcia/Kconfig @@ -14,8 +14,8 @@ config PCCARD Say Y here if you want to attach PCMCIA- or PC-cards to your Linux computer. These are credit-card size devices such as network cards, modems or hard drives often used with laptops computers. There are - actually two varieties of these cards: 16 bit PCMCIA and 32 bit - CardBus cards. + actually two varieties of these cards: the older 16 bit PCMCIA cards + and the newer 32 bit CardBus cards. To compile this driver as modules, choose M here: the module will be called pcmcia_core. @@ -42,51 +42,22 @@ config PCMCIA_DEBUG config PCMCIA tristate "16-bit PCMCIA support" - select CRC32 default y ---help--- This option enables support for 16-bit PCMCIA cards. Most older PC-cards are such 16-bit PCMCIA cards, so unless you know you're only using 32-bit CardBus cards, say Y or M here. - To use 16-bit PCMCIA cards, you will need supporting software in - most cases. (see the file for - location and details). + To use 16-bit PCMCIA cards, you will need supporting software from + David Hinds' pcmcia-cs package (see the file + for location). Please also read the PCMCIA-HOWTO, available from + . To compile this driver as modules, choose M here: the module will be called pcmcia. If unsure, say Y. -config PCMCIA_LOAD_CIS - bool "Load CIS updates from userspace (EXPERIMENTAL)" - depends on PCMCIA && EXPERIMENTAL - select FW_LOADER - default y - help - Some PCMCIA cards require an updated Card Information Structure (CIS) - to be loaded from userspace to work correctly. If you say Y here, - and your userspace is arranged correctly, this will be loaded - automatically using the in-kernel firmware loader and the hotplug - subsystem, instead of relying on cardmgr from pcmcia-cs to do so. - - If unsure, say Y. - -config PCMCIA_IOCTL - bool - depends on PCMCIA - default y - help - If you say Y here, the deprecated ioctl interface to the PCMCIA - subsystem will be built. It is needed by cardmgr and cardctl - (pcmcia-cs) to function properly. - - If you do not use the new pcmciautils package, and have a - yenta, Cirrus PD6729, i82092, i82365 or tcic compatible bridge, - you need to say Y here to be able to use 16-bit PCMCIA cards. - - If unsure, say Y. - config CARDBUS bool "32-bit CardBus support" depends on PCI @@ -106,6 +77,8 @@ comment "PC-card bridges" config YENTA tristate "CardBus yenta-compatible bridge support" + depends on PCI +#fixme: remove dependendcy on CARDBUS depends on CARDBUS select PCCARD_NONSTATIC ---help--- diff --git a/trunk/drivers/pcmcia/Makefile b/trunk/drivers/pcmcia/Makefile index ef694c74dfb7..50c29361bc5f 100644 --- a/trunk/drivers/pcmcia/Makefile +++ b/trunk/drivers/pcmcia/Makefile @@ -10,8 +10,7 @@ pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o obj-$(CONFIG_PCCARD) += pcmcia_core.o -pcmcia-y += ds.o pcmcia_compat.o pcmcia_resource.o -pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o +pcmcia-y += ds.o pcmcia_compat.o obj-$(CONFIG_PCMCIA) += pcmcia.o obj-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o diff --git a/trunk/drivers/pcmcia/cistpl.c b/trunk/drivers/pcmcia/cistpl.c index dd7651ff5b43..e29a6ddf2fd7 100644 --- a/trunk/drivers/pcmcia/cistpl.c +++ b/trunk/drivers/pcmcia/cistpl.c @@ -89,10 +89,8 @@ static void __iomem * set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags) { pccard_mem_map *mem = &s->cis_mem; - int ret; - if (!(s->features & SS_CAP_STATIC_MAP) && mem->res == NULL) { - mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s); + mem->res = find_mem_region(0, s->map_size, s->map_size, 0, s); if (mem->res == NULL) { printk(KERN_NOTICE "cs: unable to map card memory!\n"); return NULL; @@ -101,12 +99,7 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag } mem->card_start = card_offset; mem->flags = flags; - ret = s->ops->set_mem_map(s, mem); - if (ret) { - iounmap(s->cis_virt); - return NULL; - } - + s->ops->set_mem_map(s, mem); if (s->features & SS_CAP_STATIC_MAP) { if (s->cis_virt) iounmap(s->cis_virt); @@ -126,13 +119,13 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag #define IS_ATTR 1 #define IS_INDIRECT 8 -int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, +int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr) { void __iomem *sys, *end; unsigned char *buf = ptr; - cs_dbg(s, 3, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len); + cs_dbg(s, 3, "read_cis_mem(%d, %#x, %u)\n", attr, addr, len); if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed @@ -189,16 +182,14 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, *(u_char *)(ptr+2), *(u_char *)(ptr+3)); return 0; } -EXPORT_SYMBOL(pcmcia_read_cis_mem); - -void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, +void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr) { void __iomem *sys, *end; unsigned char *buf = ptr; - cs_dbg(s, 3, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len); + cs_dbg(s, 3, "write_cis_mem(%d, %#x, %u)\n", attr, addr, len); if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed @@ -248,8 +239,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, } } } -EXPORT_SYMBOL(pcmcia_write_cis_mem); - /*====================================================================== @@ -285,7 +274,7 @@ static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, ret = read_cb_mem(s, attr, addr, len, ptr); else #endif - ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr); + ret = read_cis_mem(s, attr, addr, len, ptr); if (ret == 0) { /* Copy data into the cache */ @@ -359,7 +348,7 @@ int verify_cis_cache(struct pcmcia_socket *s) read_cb_mem(s, cis->attr, cis->addr, len, buf); else #endif - pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf); + read_cis_mem(s, cis->attr, cis->addr, len, buf); if (memcmp(buf, cis->cache, len) != 0) { kfree(buf); @@ -392,7 +381,6 @@ int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis) memcpy(s->fake_cis, cis->Data, cis->Length); return CS_SUCCESS; } -EXPORT_SYMBOL(pcmcia_replace_cis); /*====================================================================== diff --git a/trunk/drivers/pcmcia/cs.c b/trunk/drivers/pcmcia/cs.c index e82859d3227a..48e4f04530d8 100644 --- a/trunk/drivers/pcmcia/cs.c +++ b/trunk/drivers/pcmcia/cs.c @@ -43,11 +43,36 @@ #include #include "cs_internal.h" +#ifdef CONFIG_PCI +#define PCI_OPT " [pci]" +#else +#define PCI_OPT "" +#endif +#ifdef CONFIG_CARDBUS +#define CB_OPT " [cardbus]" +#else +#define CB_OPT "" +#endif +#ifdef CONFIG_PM +#define PM_OPT " [pm]" +#else +#define PM_OPT "" +#endif +#if !defined(CONFIG_CARDBUS) && !defined(CONFIG_PCI) && !defined(CONFIG_PM) +#define OPTIONS " none" +#else +#define OPTIONS PCI_OPT CB_OPT PM_OPT +#endif + +static const char *release = "Linux Kernel Card Services"; +static const char *options = "options: " OPTIONS; + +/*====================================================================*/ /* Module parameters */ MODULE_AUTHOR("David Hinds "); -MODULE_DESCRIPTION("Linux Kernel Card Services"); +MODULE_DESCRIPTION("Linux Kernel Card Services\noptions:" OPTIONS); MODULE_LICENSE("GPL"); #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444) @@ -64,6 +89,9 @@ INT_MODULE_PARM(unreset_limit, 30); /* unreset_check's */ /* Access speed for attribute memory windows */ INT_MODULE_PARM(cis_speed, 300); /* ns */ +/* Access speed for IO windows */ +INT_MODULE_PARM(io_speed, 0); /* ns */ + #ifdef DEBUG static int pc_debug; @@ -75,26 +103,34 @@ int cs_debug_level(int level) } #endif +/*====================================================================*/ socket_state_t dead_socket = { .csc_mask = SS_DETECT, }; -EXPORT_SYMBOL(dead_socket); /* List of all sockets, protected by a rwsem */ LIST_HEAD(pcmcia_socket_list); -EXPORT_SYMBOL(pcmcia_socket_list); - DECLARE_RWSEM(pcmcia_socket_list_rwsem); +EXPORT_SYMBOL(pcmcia_socket_list); EXPORT_SYMBOL(pcmcia_socket_list_rwsem); +#ifdef CONFIG_PCMCIA_PROBE +/* mask ofIRQs already reserved by other cards, we should avoid using them */ +static u8 pcmcia_used_irq[NR_IRQS]; +#endif + +/*==================================================================== + + Low-level PC Card interface drivers need to register with Card + Services using these calls. + +======================================================================*/ + /** - * Low-level PCMCIA socket drivers need to register with the PCCard - * core using pcmcia_register_socket. - * - * socket drivers are expected to use the following callbacks in their + * socket drivers are expected to use the following callbacks in their * .drv struct: * - pcmcia_socket_dev_suspend * - pcmcia_socket_dev_resume @@ -194,8 +230,8 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) } /* try to obtain a socket number [yes, it gets ugly if we - * register more than 2^sizeof(unsigned int) pcmcia - * sockets... but the socket number is deprecated + * register more than 2^sizeof(unsigned int) pcmcia + * sockets... but the socket number is deprecated * anyways, so I don't care] */ down_write(&pcmcia_socket_list_rwsem); if (list_empty(&pcmcia_socket_list)) @@ -304,49 +340,54 @@ struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr) EXPORT_SYMBOL(pcmcia_get_socket_by_nr); -/** - * socket_setup() and shutdown_socket() are called by the main event - * handler when card insertion and removal events are received. - * socket_setup() turns on socket power and resets the socket, in two stages. - * shutdown_socket() unconfigures a socket and turns off socket power. - */ +/*====================================================================== + + socket_setup() and shutdown_socket() are called by the main event + handler when card insertion and removal events are received. + socket_setup() turns on socket power and resets the socket, in two stages. + shutdown_socket() unconfigures a socket and turns off socket power. + +======================================================================*/ + static void shutdown_socket(struct pcmcia_socket *s) { - cs_dbg(s, 1, "shutdown_socket\n"); - - /* Blank out the socket state */ - s->socket = dead_socket; - s->ops->init(s); - s->ops->set_socket(s, &s->socket); - s->irq.AssignedIRQ = s->irq.Config = 0; - s->lock_count = 0; - destroy_cis_cache(s); + cs_dbg(s, 1, "shutdown_socket\n"); + + /* Blank out the socket state */ + s->socket = dead_socket; + s->ops->init(s); + s->ops->set_socket(s, &s->socket); + s->irq.AssignedIRQ = s->irq.Config = 0; + s->lock_count = 0; + destroy_cis_cache(s); #ifdef CONFIG_CARDBUS - cb_free(s); + cb_free(s); #endif - s->functions = 0; - if (s->config) { - kfree(s->config); - s->config = NULL; - } - - { - int status; - s->ops->get_status(s, &status); - if (status & SS_POWERON) { - printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s); - } + s->functions = 0; + if (s->config) { + kfree(s->config); + s->config = NULL; + } + + { + int status; + s->ops->get_status(s, &status); + if (status & SS_POWERON) { + printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s); } + } } /* shutdown_socket */ +/*====================================================================== + + The central event handler. Send_event() sends an event to the + 16-bit subsystem, which then calls the relevant device drivers. + Parse_events() interprets the event bits from + a card status change report. Do_shutdown() handles the high + priority stuff associated with a card removal. + +======================================================================*/ -/** - * The central event handler. Send_event() sends an event to the - * 16-bit subsystem, which then calls the relevant device drivers. - * Parse_events() interprets the event bits from - * a card status change report. Do_shutdown() handles the high - * priority stuff associated with a card removal. - */ /* NOTE: send_event needs to be called with skt->sem held. */ @@ -705,9 +746,420 @@ void pcmcia_parse_events(struct pcmcia_socket *s, u_int events) wake_up(&s->thread_wait); } } /* pcmcia_parse_events */ -EXPORT_SYMBOL(pcmcia_parse_events); +/*====================================================================== + + Special stuff for managing IO windows, because they are scarce. + +======================================================================*/ + +static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base, + ioaddr_t num, u_int lines) +{ + int i; + kio_addr_t try, align; + + align = (*base) ? (lines ? 1<features & SS_CAP_STATIC_MAP) && s->io_offset) { + *base = s->io_offset | (*base & 0x0fff); + return 0; + } + /* Check for an already-allocated window that must conflict with + what was asked for. It is a hack because it does not catch all + potential conflicts, just the most obvious ones. */ + for (i = 0; i < MAX_IO_WIN; i++) + if ((s->io[i].NumPorts != 0) && + ((s->io[i].BasePort & (align-1)) == *base)) + return 1; + for (i = 0; i < MAX_IO_WIN; i++) { + if (s->io[i].NumPorts == 0) { + s->io[i].res = find_io_region(*base, num, align, s); + if (s->io[i].res) { + s->io[i].Attributes = attr; + s->io[i].BasePort = *base = s->io[i].res->start; + s->io[i].NumPorts = s->io[i].InUse = num; + break; + } else + return 1; + } else if (s->io[i].Attributes != attr) + continue; + /* Try to extend top of window */ + try = s->io[i].BasePort + s->io[i].NumPorts; + if ((*base == 0) || (*base == try)) + if (adjust_io_region(s->io[i].res, s->io[i].res->start, + s->io[i].res->end + num, s) == 0) { + *base = try; + s->io[i].NumPorts += num; + s->io[i].InUse += num; + break; + } + /* Try to extend bottom of window */ + try = s->io[i].BasePort - num; + if ((*base == 0) || (*base == try)) + if (adjust_io_region(s->io[i].res, s->io[i].res->start - num, + s->io[i].res->end, s) == 0) { + s->io[i].BasePort = *base = try; + s->io[i].NumPorts += num; + s->io[i].InUse += num; + break; + } + } + return (i == MAX_IO_WIN); +} /* alloc_io_space */ + +static void release_io_space(struct pcmcia_socket *s, ioaddr_t base, + ioaddr_t num) +{ + int i; + + for (i = 0; i < MAX_IO_WIN; i++) { + if ((s->io[i].BasePort <= base) && + (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) { + s->io[i].InUse -= num; + /* Free the window if no one else is using it */ + if (s->io[i].InUse == 0) { + s->io[i].NumPorts = 0; + release_resource(s->io[i].res); + kfree(s->io[i].res); + s->io[i].res = NULL; + } + } + } +} + +/*====================================================================== + + Access_configuration_register() reads and writes configuration + registers in attribute memory. Memory window 0 is reserved for + this and the tuple reading services. + +======================================================================*/ + +int pccard_access_configuration_register(struct pcmcia_socket *s, + unsigned int function, + conf_reg_t *reg) +{ + config_t *c; + int addr; + u_char val; + + if (!s || !s->config) + return CS_NO_CARD; + + c = &s->config[function]; + + if (c == NULL) + return CS_NO_CARD; + + if (!(c->state & CONFIG_LOCKED)) + return CS_CONFIGURATION_LOCKED; + + addr = (c->ConfigBase + reg->Offset) >> 1; + + switch (reg->Action) { + case CS_READ: + read_cis_mem(s, 1, addr, 1, &val); + reg->Value = val; + break; + case CS_WRITE: + val = reg->Value; + write_cis_mem(s, 1, addr, 1, &val); + break; + default: + return CS_BAD_ARGS; + break; + } + return CS_SUCCESS; +} /* access_configuration_register */ +EXPORT_SYMBOL(pccard_access_configuration_register); + + +/*====================================================================*/ + +int pccard_get_configuration_info(struct pcmcia_socket *s, + unsigned int function, + config_info_t *config) +{ + config_t *c; + + if (!(s->state & SOCKET_PRESENT)) + return CS_NO_CARD; + + config->Function = function; + +#ifdef CONFIG_CARDBUS + if (s->state & SOCKET_CARDBUS) { + memset(config, 0, sizeof(config_info_t)); + config->Vcc = s->socket.Vcc; + config->Vpp1 = config->Vpp2 = s->socket.Vpp; + config->Option = s->cb_dev->subordinate->number; + if (s->state & SOCKET_CARDBUS_CONFIG) { + config->Attributes = CONF_VALID_CLIENT; + config->IntType = INT_CARDBUS; + config->AssignedIRQ = s->irq.AssignedIRQ; + if (config->AssignedIRQ) + config->Attributes |= CONF_ENABLE_IRQ; + config->BasePort1 = s->io[0].BasePort; + config->NumPorts1 = s->io[0].NumPorts; + } + return CS_SUCCESS; + } +#endif + + c = (s->config != NULL) ? &s->config[function] : NULL; + + if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { + config->Attributes = 0; + config->Vcc = s->socket.Vcc; + config->Vpp1 = config->Vpp2 = s->socket.Vpp; + return CS_SUCCESS; + } + + /* !!! This is a hack !!! */ + memcpy(&config->Attributes, &c->Attributes, sizeof(config_t)); + config->Attributes |= CONF_VALID_CLIENT; + config->CardValues = c->CardValues; + config->IRQAttributes = c->irq.Attributes; + config->AssignedIRQ = s->irq.AssignedIRQ; + config->BasePort1 = c->io.BasePort1; + config->NumPorts1 = c->io.NumPorts1; + config->Attributes1 = c->io.Attributes1; + config->BasePort2 = c->io.BasePort2; + config->NumPorts2 = c->io.NumPorts2; + config->Attributes2 = c->io.Attributes2; + config->IOAddrLines = c->io.IOAddrLines; + + return CS_SUCCESS; +} /* get_configuration_info */ +EXPORT_SYMBOL(pccard_get_configuration_info); + +/*====================================================================== + + Return information about this version of Card Services. + +======================================================================*/ + +int pcmcia_get_card_services_info(servinfo_t *info) +{ + unsigned int socket_count = 0; + struct list_head *tmp; + info->Signature[0] = 'C'; + info->Signature[1] = 'S'; + down_read(&pcmcia_socket_list_rwsem); + list_for_each(tmp, &pcmcia_socket_list) + socket_count++; + up_read(&pcmcia_socket_list_rwsem); + info->Count = socket_count; + info->Revision = CS_RELEASE_CODE; + info->CSLevel = 0x0210; + info->VendorString = (char *)release; + return CS_SUCCESS; +} /* get_card_services_info */ + + +/*====================================================================*/ + +int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req) +{ + window_t *win; + int w; + + if (!s || !(s->state & SOCKET_PRESENT)) + return CS_NO_CARD; + for (w = idx; w < MAX_WIN; w++) + if (s->state & SOCKET_WIN_REQ(w)) break; + if (w == MAX_WIN) + return CS_NO_MORE_ITEMS; + win = &s->win[w]; + req->Base = win->ctl.res->start; + req->Size = win->ctl.res->end - win->ctl.res->start + 1; + req->AccessSpeed = win->ctl.speed; + req->Attributes = 0; + if (win->ctl.flags & MAP_ATTRIB) + req->Attributes |= WIN_MEMORY_TYPE_AM; + if (win->ctl.flags & MAP_ACTIVE) + req->Attributes |= WIN_ENABLE; + if (win->ctl.flags & MAP_16BIT) + req->Attributes |= WIN_DATA_WIDTH_16; + if (win->ctl.flags & MAP_USE_WAIT) + req->Attributes |= WIN_USE_WAIT; + *handle = win; + return CS_SUCCESS; +} /* get_window */ +EXPORT_SYMBOL(pcmcia_get_window); + +/*===================================================================== + + Return the PCI device associated with a card.. + +======================================================================*/ + +#ifdef CONFIG_CARDBUS + +struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s) +{ + if (!s || !(s->state & SOCKET_CARDBUS)) + return NULL; + + return s->cb_dev->subordinate; +} + +EXPORT_SYMBOL(pcmcia_lookup_bus); + +#endif + +/*====================================================================== + + Get the current socket state bits. We don't support the latched + SocketState yet: I haven't seen any point for it. + +======================================================================*/ + +int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status) +{ + config_t *c; + int val; + + s->ops->get_status(s, &val); + status->CardState = status->SocketState = 0; + status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0; + status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0; + status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0; + status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0; + if (s->state & SOCKET_SUSPEND) + status->CardState |= CS_EVENT_PM_SUSPEND; + if (!(s->state & SOCKET_PRESENT)) + return CS_NO_CARD; + + c = (s->config != NULL) ? &s->config[function] : NULL; + if ((c != NULL) && (c->state & CONFIG_LOCKED) && + (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { + u_char reg; + if (c->Present & PRESENT_PIN_REPLACE) { + read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); + status->CardState |= + (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; + status->CardState |= + (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0; + status->CardState |= + (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0; + status->CardState |= + (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0; + } else { + /* No PRR? Then assume we're always ready */ + status->CardState |= CS_EVENT_READY_CHANGE; + } + if (c->Present & PRESENT_EXT_STATUS) { + read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); + status->CardState |= + (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; + } + return CS_SUCCESS; + } + status->CardState |= + (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0; + status->CardState |= + (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0; + status->CardState |= + (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0; + status->CardState |= + (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0; + return CS_SUCCESS; +} /* get_status */ +EXPORT_SYMBOL(pccard_get_status); + +/*====================================================================== + + Change the card address of an already open memory window. + +======================================================================*/ + +int pcmcia_get_mem_page(window_handle_t win, memreq_t *req) +{ + if ((win == NULL) || (win->magic != WINDOW_MAGIC)) + return CS_BAD_HANDLE; + req->Page = 0; + req->CardOffset = win->ctl.card_start; + return CS_SUCCESS; +} /* get_mem_page */ + +int pcmcia_map_mem_page(window_handle_t win, memreq_t *req) +{ + struct pcmcia_socket *s; + if ((win == NULL) || (win->magic != WINDOW_MAGIC)) + return CS_BAD_HANDLE; + if (req->Page != 0) + return CS_BAD_PAGE; + s = win->sock; + win->ctl.card_start = req->CardOffset; + if (s->ops->set_mem_map(s, &win->ctl) != 0) + return CS_BAD_OFFSET; + return CS_SUCCESS; +} /* map_mem_page */ + +/*====================================================================== + + Modify a locked socket configuration + +======================================================================*/ + +int pcmcia_modify_configuration(client_handle_t handle, + modconf_t *mod) +{ + struct pcmcia_socket *s; + config_t *c; + + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + s = SOCKET(handle); c = CONFIG(handle); + if (!(s->state & SOCKET_PRESENT)) + return CS_NO_CARD; + if (!(c->state & CONFIG_LOCKED)) + return CS_CONFIGURATION_LOCKED; + + if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { + if (mod->Attributes & CONF_ENABLE_IRQ) { + c->Attributes |= CONF_ENABLE_IRQ; + s->socket.io_irq = s->irq.AssignedIRQ; + } else { + c->Attributes &= ~CONF_ENABLE_IRQ; + s->socket.io_irq = 0; + } + s->ops->set_socket(s, &s->socket); + } + + if (mod->Attributes & CONF_VCC_CHANGE_VALID) + return CS_BAD_VCC; + + /* We only allow changing Vpp1 and Vpp2 to the same value */ + if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && + (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { + if (mod->Vpp1 != mod->Vpp2) + return CS_BAD_VPP; + c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1; + if (s->ops->set_socket(s, &s->socket)) + return CS_BAD_VPP; + } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || + (mod->Attributes & CONF_VPP2_CHANGE_VALID)) + return CS_BAD_VPP; + + return CS_SUCCESS; +} /* modify_configuration */ + /* register pcmcia_callback */ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) { @@ -736,16 +1188,543 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) } EXPORT_SYMBOL(pccard_register_pcmcia); +/*====================================================================*/ -/* I'm not sure which "reset" function this is supposed to use, - * but for now, it uses the low-level interface's reset, not the - * CIS register. - */ +int pcmcia_release_configuration(client_handle_t handle) +{ + pccard_io_map io = { 0, 0, 0, 0, 1 }; + struct pcmcia_socket *s; + int i; + + if (CHECK_HANDLE(handle) || + !(handle->state & CLIENT_CONFIG_LOCKED)) + return CS_BAD_HANDLE; + handle->state &= ~CLIENT_CONFIG_LOCKED; + s = SOCKET(handle); + +#ifdef CONFIG_CARDBUS + if (handle->state & CLIENT_CARDBUS) + return CS_SUCCESS; +#endif + + if (!(handle->state & CLIENT_STALE)) { + config_t *c = CONFIG(handle); + if (--(s->lock_count) == 0) { + s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ + s->socket.Vpp = 0; + s->socket.io_irq = 0; + s->ops->set_socket(s, &s->socket); + } + if (c->state & CONFIG_IO_REQ) + for (i = 0; i < MAX_IO_WIN; i++) { + if (s->io[i].NumPorts == 0) + continue; + s->io[i].Config--; + if (s->io[i].Config != 0) + continue; + io.map = i; + s->ops->set_io_map(s, &io); + } + c->state &= ~CONFIG_LOCKED; + } + + return CS_SUCCESS; +} /* release_configuration */ + +/*====================================================================== + + Release_io() releases the I/O ranges allocated by a client. This + may be invoked some time after a card ejection has already dumped + the actual socket configuration, so if the client is "stale", we + don't bother checking the port ranges against the current socket + values. + +======================================================================*/ + +int pcmcia_release_io(client_handle_t handle, io_req_t *req) +{ + struct pcmcia_socket *s; + + if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ)) + return CS_BAD_HANDLE; + handle->state &= ~CLIENT_IO_REQ; + s = SOCKET(handle); + +#ifdef CONFIG_CARDBUS + if (handle->state & CLIENT_CARDBUS) + return CS_SUCCESS; +#endif + + if (!(handle->state & CLIENT_STALE)) { + config_t *c = CONFIG(handle); + if (c->state & CONFIG_LOCKED) + return CS_CONFIGURATION_LOCKED; + if ((c->io.BasePort1 != req->BasePort1) || + (c->io.NumPorts1 != req->NumPorts1) || + (c->io.BasePort2 != req->BasePort2) || + (c->io.NumPorts2 != req->NumPorts2)) + return CS_BAD_ARGS; + c->state &= ~CONFIG_IO_REQ; + } + + release_io_space(s, req->BasePort1, req->NumPorts1); + if (req->NumPorts2) + release_io_space(s, req->BasePort2, req->NumPorts2); + + return CS_SUCCESS; +} /* release_io */ + +/*====================================================================*/ + +int pcmcia_release_irq(client_handle_t handle, irq_req_t *req) +{ + struct pcmcia_socket *s; + if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ)) + return CS_BAD_HANDLE; + handle->state &= ~CLIENT_IRQ_REQ; + s = SOCKET(handle); + + if (!(handle->state & CLIENT_STALE)) { + config_t *c = CONFIG(handle); + if (c->state & CONFIG_LOCKED) + return CS_CONFIGURATION_LOCKED; + if (c->irq.Attributes != req->Attributes) + return CS_BAD_ATTRIBUTE; + if (s->irq.AssignedIRQ != req->AssignedIRQ) + return CS_BAD_IRQ; + if (--s->irq.Config == 0) { + c->state &= ~CONFIG_IRQ_REQ; + s->irq.AssignedIRQ = 0; + } + } + + if (req->Attributes & IRQ_HANDLE_PRESENT) { + free_irq(req->AssignedIRQ, req->Instance); + } + +#ifdef CONFIG_PCMCIA_PROBE + pcmcia_used_irq[req->AssignedIRQ]--; +#endif + + return CS_SUCCESS; +} /* cs_release_irq */ + +/*====================================================================*/ + +int pcmcia_release_window(window_handle_t win) +{ + struct pcmcia_socket *s; + + if ((win == NULL) || (win->magic != WINDOW_MAGIC)) + return CS_BAD_HANDLE; + s = win->sock; + if (!(win->handle->state & CLIENT_WIN_REQ(win->index))) + return CS_BAD_HANDLE; + + /* Shut down memory window */ + win->ctl.flags &= ~MAP_ACTIVE; + s->ops->set_mem_map(s, &win->ctl); + s->state &= ~SOCKET_WIN_REQ(win->index); + + /* Release system memory */ + if (win->ctl.res) { + release_resource(win->ctl.res); + kfree(win->ctl.res); + win->ctl.res = NULL; + } + win->handle->state &= ~CLIENT_WIN_REQ(win->index); + + win->magic = 0; + + return CS_SUCCESS; +} /* release_window */ + +/*====================================================================*/ + +int pcmcia_request_configuration(client_handle_t handle, + config_req_t *req) +{ + int i; + u_int base; + struct pcmcia_socket *s; + config_t *c; + pccard_io_map iomap; + + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + s = SOCKET(handle); + if (!(s->state & SOCKET_PRESENT)) + return CS_NO_CARD; + +#ifdef CONFIG_CARDBUS + if (handle->state & CLIENT_CARDBUS) + return CS_UNSUPPORTED_MODE; +#endif + + if (req->IntType & INT_CARDBUS) + return CS_UNSUPPORTED_MODE; + c = CONFIG(handle); + if (c->state & CONFIG_LOCKED) + return CS_CONFIGURATION_LOCKED; + + /* Do power control. We don't allow changes in Vcc. */ + if (s->socket.Vcc != req->Vcc) + return CS_BAD_VCC; + if (req->Vpp1 != req->Vpp2) + return CS_BAD_VPP; + s->socket.Vpp = req->Vpp1; + if (s->ops->set_socket(s, &s->socket)) + return CS_BAD_VPP; + + c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1; + + /* Pick memory or I/O card, DMA mode, interrupt */ + c->IntType = req->IntType; + c->Attributes = req->Attributes; + if (req->IntType & INT_MEMORY_AND_IO) + s->socket.flags |= SS_IOCARD; + if (req->IntType & INT_ZOOMED_VIDEO) + s->socket.flags |= SS_ZVCARD | SS_IOCARD; + if (req->Attributes & CONF_ENABLE_DMA) + s->socket.flags |= SS_DMA_MODE; + if (req->Attributes & CONF_ENABLE_SPKR) + s->socket.flags |= SS_SPKR_ENA; + if (req->Attributes & CONF_ENABLE_IRQ) + s->socket.io_irq = s->irq.AssignedIRQ; + else + s->socket.io_irq = 0; + s->ops->set_socket(s, &s->socket); + s->lock_count++; + + /* Set up CIS configuration registers */ + base = c->ConfigBase = req->ConfigBase; + c->Present = c->CardValues = req->Present; + if (req->Present & PRESENT_COPY) { + c->Copy = req->Copy; + write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); + } + if (req->Present & PRESENT_OPTION) { + if (s->functions == 1) { + c->Option = req->ConfigIndex & COR_CONFIG_MASK; + } else { + c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK; + c->Option |= COR_FUNC_ENA|COR_IREQ_ENA; + if (req->Present & PRESENT_IOBASE_0) + c->Option |= COR_ADDR_DECODE; + } + if (c->state & CONFIG_IRQ_REQ) + if (!(c->irq.Attributes & IRQ_FORCED_PULSE)) + c->Option |= COR_LEVEL_REQ; + write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); + mdelay(40); + } + if (req->Present & PRESENT_STATUS) { + c->Status = req->Status; + write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status); + } + if (req->Present & PRESENT_PIN_REPLACE) { + c->Pin = req->Pin; + write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin); + } + if (req->Present & PRESENT_EXT_STATUS) { + c->ExtStatus = req->ExtStatus; + write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus); + } + if (req->Present & PRESENT_IOBASE_0) { + u_char b = c->io.BasePort1 & 0xff; + write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b); + b = (c->io.BasePort1 >> 8) & 0xff; + write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b); + } + if (req->Present & PRESENT_IOSIZE) { + u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1; + write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b); + } + + /* Configure I/O windows */ + if (c->state & CONFIG_IO_REQ) { + iomap.speed = io_speed; + for (i = 0; i < MAX_IO_WIN; i++) + if (s->io[i].NumPorts != 0) { + iomap.map = i; + iomap.flags = MAP_ACTIVE; + switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) { + case IO_DATA_PATH_WIDTH_16: + iomap.flags |= MAP_16BIT; break; + case IO_DATA_PATH_WIDTH_AUTO: + iomap.flags |= MAP_AUTOSZ; break; + default: + break; + } + iomap.start = s->io[i].BasePort; + iomap.stop = iomap.start + s->io[i].NumPorts - 1; + s->ops->set_io_map(s, &iomap); + s->io[i].Config++; + } + } + + c->state |= CONFIG_LOCKED; + handle->state |= CLIENT_CONFIG_LOCKED; + return CS_SUCCESS; +} /* request_configuration */ + +/*====================================================================== + + Request_io() reserves ranges of port addresses for a socket. + I have not implemented range sharing or alias addressing. + +======================================================================*/ + +int pcmcia_request_io(client_handle_t handle, io_req_t *req) +{ + struct pcmcia_socket *s; + config_t *c; + + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + s = SOCKET(handle); + if (!(s->state & SOCKET_PRESENT)) + return CS_NO_CARD; + + if (handle->state & CLIENT_CARDBUS) { +#ifdef CONFIG_CARDBUS + handle->state |= CLIENT_IO_REQ; + return CS_SUCCESS; +#else + return CS_UNSUPPORTED_FUNCTION; +#endif + } + + if (!req) + return CS_UNSUPPORTED_MODE; + c = CONFIG(handle); + if (c->state & CONFIG_LOCKED) + return CS_CONFIGURATION_LOCKED; + if (c->state & CONFIG_IO_REQ) + return CS_IN_USE; + if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) + return CS_BAD_ATTRIBUTE; + if ((req->NumPorts2 > 0) && + (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) + return CS_BAD_ATTRIBUTE; + + if (alloc_io_space(s, req->Attributes1, &req->BasePort1, + req->NumPorts1, req->IOAddrLines)) + return CS_IN_USE; + + if (req->NumPorts2) { + if (alloc_io_space(s, req->Attributes2, &req->BasePort2, + req->NumPorts2, req->IOAddrLines)) { + release_io_space(s, req->BasePort1, req->NumPorts1); + return CS_IN_USE; + } + } + + c->io = *req; + c->state |= CONFIG_IO_REQ; + handle->state |= CLIENT_IO_REQ; + return CS_SUCCESS; +} /* request_io */ + +/*====================================================================== + + Request_irq() reserves an irq for this client. + + Also, since Linux only reserves irq's when they are actually + hooked, we don't guarantee that an irq will still be available + when the configuration is locked. Now that I think about it, + there might be a way to fix this using a dummy handler. + +======================================================================*/ + +#ifdef CONFIG_PCMCIA_PROBE +static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs) +{ + return IRQ_NONE; +} +#endif + +int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) +{ + struct pcmcia_socket *s; + config_t *c; + int ret = CS_IN_USE, irq = 0; + struct pcmcia_device *p_dev = handle_to_pdev(handle); + + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + s = SOCKET(handle); + if (!(s->state & SOCKET_PRESENT)) + return CS_NO_CARD; + c = CONFIG(handle); + if (c->state & CONFIG_LOCKED) + return CS_CONFIGURATION_LOCKED; + if (c->state & CONFIG_IRQ_REQ) + return CS_IN_USE; + +#ifdef CONFIG_PCMCIA_PROBE + if (s->irq.AssignedIRQ != 0) { + /* If the interrupt is already assigned, it must be the same */ + irq = s->irq.AssignedIRQ; + } else { + int try; + u32 mask = s->irq_mask; + void *data = NULL; + + for (try = 0; try < 64; try++) { + irq = try % 32; + + /* marked as available by driver, and not blocked by userspace? */ + if (!((mask >> irq) & 1)) + continue; + + /* avoid an IRQ which is already used by a PCMCIA card */ + if ((try < 32) && pcmcia_used_irq[irq]) + continue; + + /* register the correct driver, if possible, of check whether + * registering a dummy handle works, i.e. if the IRQ isn't + * marked as used by the kernel resource management core */ + ret = request_irq(irq, + (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action, + ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || + (s->functions > 1) || + (irq == s->pci_irq)) ? SA_SHIRQ : 0, + p_dev->dev.bus_id, + (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data); + if (!ret) { + if (!(req->Attributes & IRQ_HANDLE_PRESENT)) + free_irq(irq, data); + break; + } + } + } +#endif + if (ret) { + if (!s->pci_irq) + return ret; + irq = s->pci_irq; + } + + if (ret && req->Attributes & IRQ_HANDLE_PRESENT) { + if (request_irq(irq, req->Handler, + ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || + (s->functions > 1) || + (irq == s->pci_irq)) ? SA_SHIRQ : 0, + p_dev->dev.bus_id, req->Instance)) + return CS_IN_USE; + } + + c->irq.Attributes = req->Attributes; + s->irq.AssignedIRQ = req->AssignedIRQ = irq; + s->irq.Config++; + + c->state |= CONFIG_IRQ_REQ; + handle->state |= CLIENT_IRQ_REQ; + +#ifdef CONFIG_PCMCIA_PROBE + pcmcia_used_irq[irq]++; +#endif + + return CS_SUCCESS; +} /* pcmcia_request_irq */ + +/*====================================================================== + + Request_window() establishes a mapping between card memory space + and system memory space. + +======================================================================*/ + +int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh) +{ + struct pcmcia_socket *s; + window_t *win; + u_long align; + int w; + + if (CHECK_HANDLE(*handle)) + return CS_BAD_HANDLE; + s = (*handle)->Socket; + if (!(s->state & SOCKET_PRESENT)) + return CS_NO_CARD; + if (req->Attributes & (WIN_PAGED | WIN_SHARED)) + return CS_BAD_ATTRIBUTE; + + /* Window size defaults to smallest available */ + if (req->Size == 0) + req->Size = s->map_size; + align = (((s->features & SS_CAP_MEM_ALIGN) || + (req->Attributes & WIN_STRICT_ALIGN)) ? + req->Size : s->map_size); + if (req->Size & (s->map_size-1)) + return CS_BAD_SIZE; + if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || + (req->Base & (align-1))) + return CS_BAD_BASE; + if (req->Base) + align = 0; + + /* Allocate system memory window */ + for (w = 0; w < MAX_WIN; w++) + if (!(s->state & SOCKET_WIN_REQ(w))) break; + if (w == MAX_WIN) + return CS_OUT_OF_RESOURCE; + + win = &s->win[w]; + win->magic = WINDOW_MAGIC; + win->index = w; + win->handle = *handle; + win->sock = s; + + if (!(s->features & SS_CAP_STATIC_MAP)) { + win->ctl.res = find_mem_region(req->Base, req->Size, align, + (req->Attributes & WIN_MAP_BELOW_1MB), s); + if (!win->ctl.res) + return CS_IN_USE; + } + (*handle)->state |= CLIENT_WIN_REQ(w); + + /* Configure the socket controller */ + win->ctl.map = w+1; + win->ctl.flags = 0; + win->ctl.speed = req->AccessSpeed; + if (req->Attributes & WIN_MEMORY_TYPE) + win->ctl.flags |= MAP_ATTRIB; + if (req->Attributes & WIN_ENABLE) + win->ctl.flags |= MAP_ACTIVE; + if (req->Attributes & WIN_DATA_WIDTH_16) + win->ctl.flags |= MAP_16BIT; + if (req->Attributes & WIN_USE_WAIT) + win->ctl.flags |= MAP_USE_WAIT; + win->ctl.card_start = 0; + if (s->ops->set_mem_map(s, &win->ctl) != 0) + return CS_BAD_ARGS; + s->state |= SOCKET_WIN_REQ(w); + + /* Return window handle */ + if (s->features & SS_CAP_STATIC_MAP) { + req->Base = win->ctl.static_start; + } else { + req->Base = win->ctl.res->start; + } + *wh = win; + + return CS_SUCCESS; +} /* request_window */ + +/*====================================================================== + + I'm not sure which "reset" function this is supposed to use, + but for now, it uses the low-level interface's reset, not the + CIS register. + +======================================================================*/ int pccard_reset_card(struct pcmcia_socket *skt) { int ret; - + cs_dbg(skt, 1, "resetting socket\n"); down(&skt->skt_sem); @@ -778,14 +1757,17 @@ int pccard_reset_card(struct pcmcia_socket *skt) } /* reset_card */ EXPORT_SYMBOL(pccard_reset_card); +/*====================================================================== + + These shut down or wake up a socket. They are sort of user + initiated versions of the APM suspend and resume actions. + +======================================================================*/ -/* These shut down or wake up a socket. They are sort of user - * initiated versions of the APM suspend and resume actions. - */ int pcmcia_suspend_card(struct pcmcia_socket *skt) { int ret; - + cs_dbg(skt, 1, "suspending socket\n"); down(&skt->skt_sem); @@ -804,8 +1786,6 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt) return ret; } /* suspend_card */ -EXPORT_SYMBOL(pcmcia_suspend_card); - int pcmcia_resume_card(struct pcmcia_socket *skt) { @@ -829,10 +1809,13 @@ int pcmcia_resume_card(struct pcmcia_socket *skt) return ret; } /* resume_card */ -EXPORT_SYMBOL(pcmcia_resume_card); +/*====================================================================== + + These handle user requests to eject or insert a card. + +======================================================================*/ -/* These handle user requests to eject or insert a card. */ int pcmcia_eject_card(struct pcmcia_socket *skt) { int ret; @@ -859,8 +1842,6 @@ int pcmcia_eject_card(struct pcmcia_socket *skt) return ret; } /* eject_card */ -EXPORT_SYMBOL(pcmcia_eject_card); - int pcmcia_insert_card(struct pcmcia_socket *skt) { @@ -884,38 +1865,37 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) return ret; } /* insert_card */ -EXPORT_SYMBOL(pcmcia_insert_card); - - -static int pcmcia_socket_hotplug(struct class_device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) -{ - struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev); - int i = 0, length = 0; - - if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, - &length, "SOCKET_NO=%u", s->sock)) - return -ENOMEM; - - envp[i] = NULL; - return 0; -} - - -static struct completion pcmcia_unload; +/*====================================================================== -static void pcmcia_release_socket_class(struct class *data) -{ - complete(&pcmcia_unload); -} + OS-specific module glue goes here + +======================================================================*/ +/* in alpha order */ +EXPORT_SYMBOL(pcmcia_eject_card); +EXPORT_SYMBOL(pcmcia_get_card_services_info); +EXPORT_SYMBOL(pcmcia_get_mem_page); +EXPORT_SYMBOL(pcmcia_insert_card); +EXPORT_SYMBOL(pcmcia_map_mem_page); +EXPORT_SYMBOL(pcmcia_modify_configuration); +EXPORT_SYMBOL(pcmcia_release_configuration); +EXPORT_SYMBOL(pcmcia_release_io); +EXPORT_SYMBOL(pcmcia_release_irq); +EXPORT_SYMBOL(pcmcia_release_window); +EXPORT_SYMBOL(pcmcia_replace_cis); +EXPORT_SYMBOL(pcmcia_request_configuration); +EXPORT_SYMBOL(pcmcia_request_io); +EXPORT_SYMBOL(pcmcia_request_irq); +EXPORT_SYMBOL(pcmcia_request_window); +EXPORT_SYMBOL(pcmcia_resume_card); +EXPORT_SYMBOL(pcmcia_suspend_card); +EXPORT_SYMBOL(dead_socket); +EXPORT_SYMBOL(pcmcia_parse_events); struct class pcmcia_socket_class = { .name = "pcmcia_socket", - .hotplug = pcmcia_socket_hotplug, .release = pcmcia_release_socket, - .class_release = pcmcia_release_socket_class, }; EXPORT_SYMBOL(pcmcia_socket_class); @@ -923,8 +1903,9 @@ EXPORT_SYMBOL(pcmcia_socket_class); static int __init init_pcmcia_cs(void) { int ret; + printk(KERN_INFO "%s\n", release); + printk(KERN_INFO " %s\n", options); - init_completion(&pcmcia_unload); ret = class_register(&pcmcia_socket_class); if (ret) return (ret); @@ -933,12 +1914,13 @@ static int __init init_pcmcia_cs(void) static void __exit exit_pcmcia_cs(void) { - class_interface_unregister(&pccard_sysfs_interface); - class_unregister(&pcmcia_socket_class); - - wait_for_completion(&pcmcia_unload); + printk(KERN_INFO "unloading Kernel Card Services\n"); + class_interface_unregister(&pccard_sysfs_interface); + class_unregister(&pcmcia_socket_class); } subsys_initcall(init_pcmcia_cs); module_exit(exit_pcmcia_cs); +/*====================================================================*/ + diff --git a/trunk/drivers/pcmcia/cs_internal.h b/trunk/drivers/pcmcia/cs_internal.h index 0b4c18edfa49..7933a7db49d3 100644 --- a/trunk/drivers/pcmcia/cs_internal.h +++ b/trunk/drivers/pcmcia/cs_internal.h @@ -123,9 +123,9 @@ void cb_free(struct pcmcia_socket *s); int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len, void *ptr); /* In cistpl.c */ -int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, +int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr); -void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, +void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr); void release_cis_mem(struct pcmcia_socket *s); void destroy_cis_cache(struct pcmcia_socket *s); @@ -134,12 +134,13 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t /* In rsrc_mgr */ void pcmcia_validate_mem(struct pcmcia_socket *s); -struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align, +struct resource *find_io_region(unsigned long base, int num, unsigned long align, struct pcmcia_socket *s); -int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start, +int adjust_io_region(struct resource *res, unsigned long r_start, unsigned long r_end, struct pcmcia_socket *s); -struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, +struct resource *find_mem_region(u_long base, u_long num, u_long align, int low, struct pcmcia_socket *s); +int adjust_resource_info(client_handle_t handle, adjust_t *adj); void release_resource_db(struct pcmcia_socket *s); /* In socket_sysfs.c */ @@ -158,7 +159,7 @@ int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int f struct pcmcia_callback{ struct module *owner; int (*event) (struct pcmcia_socket *s, event_t event, int priority); - void (*requery) (struct pcmcia_socket *s); + int (*resources_done) (struct pcmcia_socket *s); }; int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); diff --git a/trunk/drivers/pcmcia/ds.c b/trunk/drivers/pcmcia/ds.c index cabddd49f6ff..569e55feecfd 100644 --- a/trunk/drivers/pcmcia/ds.c +++ b/trunk/drivers/pcmcia/ds.c @@ -10,29 +10,44 @@ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * (C) 1999 David A. Hinds - * (C) 2003 - 2005 Dominik Brodowski + * (C) 2003 - 2004 Dominik Brodowski */ #include -#include #include +#include #include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include #include -#include -#include + +#include #define IN_CARD_SERVICES +#include #include #include +#include #include #include #include #include "cs_internal.h" -#include "ds_internal.h" /*====================================================================*/ @@ -55,9 +70,49 @@ module_param_named(pc_debug, ds_pc_debug, int, 0644); #define ds_dbg(lvl, fmt, arg...) do { } while (0) #endif -spinlock_t pcmcia_dev_list_lock; +/*====================================================================*/ -static int unbind_request(struct pcmcia_socket *s); +/* Device user information */ +#define MAX_EVENTS 32 +#define USER_MAGIC 0x7ea4 +#define CHECK_USER(u) \ + (((u) == NULL) || ((u)->user_magic != USER_MAGIC)) +typedef struct user_info_t { + u_int user_magic; + int event_head, event_tail; + event_t event[MAX_EVENTS]; + struct user_info_t *next; + struct pcmcia_bus_socket *socket; +} user_info_t; + +/* Socket state information */ +struct pcmcia_bus_socket { + struct kref refcount; + struct pcmcia_callback callback; + int state; + user_info_t *user; + wait_queue_head_t queue; + struct pcmcia_socket *parent; + + /* the PCMCIA devices connected to this socket (normally one, more + * for multifunction devices: */ + struct list_head devices_list; + u8 device_count; /* the number of devices, used + * only internally and subject + * to incorrectness and change */ +}; +static spinlock_t pcmcia_dev_list_lock; + +#define DS_SOCKET_PRESENT 0x01 +#define DS_SOCKET_BUSY 0x02 +#define DS_SOCKET_REMOVAL_PENDING 0x10 +#define DS_SOCKET_DEAD 0x80 + +/*====================================================================*/ + +static int major_dev = -1; + +static int unbind_request(struct pcmcia_bus_socket *s); /*====================================================================*/ @@ -158,7 +213,7 @@ static const lookup_t service_table[] = { }; -static int pcmcia_report_error(client_handle_t handle, error_info_t *err) +int pcmcia_report_error(client_handle_t handle, error_info_t *err) { int i; char *serv; @@ -188,6 +243,7 @@ static int pcmcia_report_error(client_handle_t handle, error_info_t *err) return CS_SUCCESS; } /* report_error */ +EXPORT_SYMBOL(pcmcia_report_error); /* end of code which was in cs.c before */ @@ -200,101 +256,29 @@ void cs_error(client_handle_t handle, int func, int ret) } EXPORT_SYMBOL(cs_error); +/*======================================================================*/ -static void pcmcia_check_driver(struct pcmcia_driver *p_drv) -{ - struct pcmcia_device_id *did = p_drv->id_table; - unsigned int i; - u32 hash; - - while (did && did->match_flags) { - for (i=0; i<4; i++) { - if (!did->prod_id[i]) - continue; - - hash = crc32(0, did->prod_id[i], strlen(did->prod_id[i])); - if (hash == did->prod_id_hash[i]) - continue; - - printk(KERN_DEBUG "pcmcia: %s: invalid hash for " - "product string \"%s\": is 0x%x, should " - "be 0x%x\n", p_drv->drv.name, did->prod_id[i], - did->prod_id_hash[i], hash); - printk(KERN_DEBUG "pcmcia: see " - "Documentation/pcmcia/devicetable.txt for " - "details\n"); - } - did++; - } +static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info); +static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr); - return; +static void pcmcia_release_bus_socket(struct kref *refcount) +{ + struct pcmcia_bus_socket *s = container_of(refcount, struct pcmcia_bus_socket, refcount); + pcmcia_put_socket(s->parent); + kfree(s); } - -#ifdef CONFIG_PCMCIA_LOAD_CIS - -/** - * pcmcia_load_firmware - load CIS from userspace if device-provided is broken - * @dev - the pcmcia device which needs a CIS override - * @filename - requested filename in /lib/firmware/cis/ - * - * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if - * the one provided by the card is broken. The firmware files reside in - * /lib/firmware/cis/ in userspace. - */ -static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) +static void pcmcia_put_bus_socket(struct pcmcia_bus_socket *s) { - struct pcmcia_socket *s = dev->socket; - const struct firmware *fw; - char path[20]; - int ret=-ENOMEM; - cisdump_t *cis; - - if (!filename) - return -EINVAL; - - ds_dbg(1, "trying to load firmware %s\n", filename); - - if (strlen(filename) > 14) - return -EINVAL; - - snprintf(path, 20, "%s", filename); - - if (request_firmware(&fw, path, &dev->dev) == 0) { - if (fw->size >= CISTPL_MAX_CIS_SIZE) - goto release; - - cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL); - if (!cis) - goto release; - - memset(cis, 0, sizeof(cisdump_t)); - - cis->Length = fw->size + 1; - memcpy(cis->Data, fw->data, fw->size); - - if (!pcmcia_replace_cis(s, cis)) - ret = 0; - } - release: - release_firmware(fw); - - return (ret); + kref_put(&s->refcount, pcmcia_release_bus_socket); } -#else /* !CONFIG_PCMCIA_LOAD_CIS */ - -static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) +static struct pcmcia_bus_socket *pcmcia_get_bus_socket(struct pcmcia_bus_socket *s) { - return -ENODEV; + kref_get(&s->refcount); + return (s); } -#endif - - -/*======================================================================*/ - - /** * pcmcia_register_driver - register a PCMCIA driver with the bus core * @@ -308,8 +292,6 @@ int pcmcia_register_driver(struct pcmcia_driver *driver) if (!driver) return -EINVAL; - pcmcia_check_driver(driver); - /* initialize common fields */ driver->drv.bus = &pcmcia_bus_type; driver->drv.owner = driver->owner; @@ -329,10 +311,42 @@ void pcmcia_unregister_driver(struct pcmcia_driver *driver) } EXPORT_SYMBOL(pcmcia_unregister_driver); +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *proc_pccard = NULL; + +static int proc_read_drivers_callback(struct device_driver *driver, void *d) +{ + char **p = d; + struct pcmcia_driver *p_drv = container_of(driver, + struct pcmcia_driver, drv); + + *p += sprintf(*p, "%-24.24s 1 %d\n", p_drv->drv.name, +#ifdef CONFIG_MODULE_UNLOAD + (p_drv->owner) ? module_refcount(p_drv->owner) : 1 +#else + 1 +#endif + ); + d = (void *) p; + + return 0; +} + +static int proc_read_drivers(char *buf, char **start, off_t pos, + int count, int *eof, void *data) +{ + char *p = buf; + + bus_for_each_drv(&pcmcia_bus_type, NULL, + (void *) &p, proc_read_drivers_callback); + + return (p - buf); +} +#endif /* pcmcia_device handling */ -struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev) +static struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev) { struct device *tmp_dev; tmp_dev = get_device(&p_dev->dev); @@ -341,7 +355,7 @@ struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev) return to_pcmcia_dev(tmp_dev); } -void pcmcia_put_dev(struct pcmcia_device *p_dev) +static void pcmcia_put_dev(struct pcmcia_device *p_dev) { if (p_dev) put_device(&p_dev->dev); @@ -351,7 +365,7 @@ static void pcmcia_release_dev(struct device *dev) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); ds_dbg(1, "releasing dev %p\n", p_dev); - pcmcia_put_socket(p_dev->socket); + pcmcia_put_bus_socket(p_dev->socket->pcmcia); kfree(p_dev); } @@ -486,38 +500,34 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) */ static DECLARE_MUTEX(device_add_lock); -struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) +static struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, unsigned int function) { struct pcmcia_device *p_dev; unsigned long flags; - s = pcmcia_get_socket(s); + s = pcmcia_get_bus_socket(s); if (!s) return NULL; down(&device_add_lock); - /* max of 2 devices per card */ - if (s->device_count == 2) - goto err_put; - p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL); if (!p_dev) goto err_put; memset(p_dev, 0, sizeof(struct pcmcia_device)); - p_dev->socket = s; + p_dev->socket = s->parent; p_dev->device_no = (s->device_count++); p_dev->func = function; p_dev->dev.bus = &pcmcia_bus_type; - p_dev->dev.parent = s->dev.dev; + p_dev->dev.parent = s->parent->dev.dev; p_dev->dev.release = pcmcia_release_dev; sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); /* compat */ p_dev->client.client_magic = CLIENT_MAGIC; - p_dev->client.Socket = s; + p_dev->client.Socket = s->parent; p_dev->client.Function = function; p_dev->client.state = CLIENT_UNBOUND; @@ -526,8 +536,6 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f list_add_tail(&p_dev->socket_device_list, &s->devices_list); spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - pcmcia_device_query(p_dev); - if (device_register(&p_dev->dev)) { spin_lock_irqsave(&pcmcia_dev_list_lock, flags); list_del(&p_dev->socket_device_list); @@ -545,7 +553,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f s->device_count--; err_put: up(&device_add_lock); - pcmcia_put_socket(s); + pcmcia_put_bus_socket(s); return NULL; } @@ -576,252 +584,23 @@ static int pcmcia_card_add(struct pcmcia_socket *s) /* this doesn't handle multifunction devices on one pcmcia function * yet. */ for (i=0; i < no_funcs; i++) - pcmcia_device_add(s, i); + pcmcia_device_add(s->pcmcia, i); return (ret); } -static void pcmcia_delayed_add_pseudo_device(void *data) -{ - struct pcmcia_socket *s = data; - pcmcia_device_add(s, 0); - s->pcmcia_state.device_add_pending = 0; -} - -static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) -{ - if (!s->pcmcia_state.device_add_pending) { - schedule_work(&s->device_add); - s->pcmcia_state.device_add_pending = 1; - } - return; -} - -static int pcmcia_requery(struct device *dev, void * _data) -{ - struct pcmcia_device *p_dev = to_pcmcia_dev(dev); - if (!p_dev->dev.driver) - pcmcia_device_query(p_dev); - - return 0; -} - -static void pcmcia_bus_rescan(struct pcmcia_socket *skt) -{ - int no_devices=0; - unsigned long flags; - - /* must be called with skt_sem held */ - spin_lock_irqsave(&pcmcia_dev_list_lock, flags); - if (list_empty(&skt->devices_list)) - no_devices=1; - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - - /* if no devices were added for this socket yet because of - * missing resource information or other trouble, we need to - * do this now. */ - if (no_devices) { - int ret = pcmcia_card_add(skt); - if (ret) - return; - } - - /* some device information might have changed because of a CIS - * update or because we can finally read it correctly... so - * determine it again, overwriting old values if necessary. */ - bus_for_each_dev(&pcmcia_bus_type, NULL, NULL, pcmcia_requery); - - /* we re-scan all devices, not just the ones connected to this - * socket. This does not matter, though. */ - bus_rescan_devices(&pcmcia_bus_type); -} - -static inline int pcmcia_devmatch(struct pcmcia_device *dev, - struct pcmcia_device_id *did) -{ - if (did->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID) { - if ((!dev->has_manf_id) || (dev->manf_id != did->manf_id)) - return 0; - } - - if (did->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID) { - if ((!dev->has_card_id) || (dev->card_id != did->card_id)) - return 0; - } - - if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION) { - if (dev->func != did->function) - return 0; - } - - if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1) { - if (!dev->prod_id[0]) - return 0; - if (strcmp(did->prod_id[0], dev->prod_id[0])) - return 0; - } - - if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2) { - if (!dev->prod_id[1]) - return 0; - if (strcmp(did->prod_id[1], dev->prod_id[1])) - return 0; - } - - if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3) { - if (!dev->prod_id[2]) - return 0; - if (strcmp(did->prod_id[2], dev->prod_id[2])) - return 0; - } - - if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4) { - if (!dev->prod_id[3]) - return 0; - if (strcmp(did->prod_id[3], dev->prod_id[3])) - return 0; - } - - if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { - /* handle pseudo multifunction devices: - * there are at most two pseudo multifunction devices. - * if we're matching against the first, schedule a - * call which will then check whether there are two - * pseudo devices, and if not, add the second one. - */ - if (dev->device_no == 0) - pcmcia_add_pseudo_device(dev->socket); - - if (dev->device_no != did->device_no) - return 0; - } - - if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { - if ((!dev->has_func_id) || (dev->func_id != did->func_id)) - return 0; - - /* if this is a pseudo-multi-function device, - * we need explicit matches */ - if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) - return 0; - if (dev->device_no) - return 0; - - /* also, FUNC_ID matching needs to be activated by userspace - * after it has re-checked that there is no possible module - * with a prod_id/manf_id/card_id match. - */ - if (!dev->allow_func_id_match) - return 0; - } - - if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { - if (!dev->socket->fake_cis) - pcmcia_load_firmware(dev, did->cisfile); - - if (!dev->socket->fake_cis) - return 0; - } - - if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) { - int i; - for (i=0; i<4; i++) - if (dev->prod_id[i]) - return 0; - if (dev->has_manf_id || dev->has_card_id || dev->has_func_id) - return 0; - } - - dev->dev.driver_data = (void *) did; - - return 1; -} - - static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { struct pcmcia_device * p_dev = to_pcmcia_dev(dev); struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); - struct pcmcia_device_id *did = p_drv->id_table; /* matching by cardmgr */ if (p_dev->cardmgr == p_drv) return 1; - while (did && did->match_flags) { - if (pcmcia_devmatch(p_dev, did)) - return 1; - did++; - } - return 0; } -#ifdef CONFIG_HOTPLUG - -static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) -{ - struct pcmcia_device *p_dev; - int i, length = 0; - u32 hash[4] = { 0, 0, 0, 0}; - - if (!dev) - return -ENODEV; - - p_dev = to_pcmcia_dev(dev); - - /* calculate hashes */ - for (i=0; i<4; i++) { - if (!p_dev->prod_id[i]) - continue; - hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i])); - } - - i = 0; - - if (add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "SOCKET_NO=%u", - p_dev->socket->sock)) - return -ENOMEM; - - if (add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "DEVICE_NO=%02X", - p_dev->device_no)) - return -ENOMEM; - - if (add_hotplug_env_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" - "pa%08Xpb%08Xpc%08Xpd%08X", - p_dev->has_manf_id ? p_dev->manf_id : 0, - p_dev->has_card_id ? p_dev->card_id : 0, - p_dev->has_func_id ? p_dev->func_id : 0, - p_dev->func, - p_dev->device_no, - hash[0], - hash[1], - hash[2], - hash[3])) - return -ENOMEM; - - envp[i] = NULL; - - return 0; -} - -#else - -static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) -{ - return -ENODEV; -} - -#endif - /************************ per-device sysfs output ***************************/ #define pcmcia_device_attr(field, test, format) \ @@ -847,43 +626,6 @@ pcmcia_device_stringattr(prod_id2, prod_id[1]); pcmcia_device_stringattr(prod_id3, prod_id[2]); pcmcia_device_stringattr(prod_id4, prod_id[3]); -static ssize_t modalias_show(struct device *dev, char *buf) -{ - struct pcmcia_device *p_dev = to_pcmcia_dev(dev); - int i; - u32 hash[4] = { 0, 0, 0, 0}; - - /* calculate hashes */ - for (i=0; i<4; i++) { - if (!p_dev->prod_id[i]) - continue; - hash[i] = crc32(0,p_dev->prod_id[i],strlen(p_dev->prod_id[i])); - } - return sprintf(buf, "pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" - "pa%08Xpb%08Xpc%08Xpd%08X\n", - p_dev->has_manf_id ? p_dev->manf_id : 0, - p_dev->has_card_id ? p_dev->card_id : 0, - p_dev->has_func_id ? p_dev->func_id : 0, - p_dev->func, p_dev->device_no, - hash[0], hash[1], hash[2], hash[3]); -} - -static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct pcmcia_device *p_dev = to_pcmcia_dev(dev); - if (!count) - return -EINVAL; - - down(&p_dev->socket->skt_sem); - p_dev->allow_func_id_match = 1; - up(&p_dev->socket->skt_sem); - - bus_rescan_devices(&pcmcia_bus_type); - - return count; -} - static struct device_attribute pcmcia_dev_attrs[] = { __ATTR(function, 0444, func_show, NULL), __ATTR_RO(func_id), @@ -893,12 +635,44 @@ static struct device_attribute pcmcia_dev_attrs[] = { __ATTR_RO(prod_id2), __ATTR_RO(prod_id3), __ATTR_RO(prod_id4), - __ATTR_RO(modalias), - __ATTR(allow_func_id_match, 0200, NULL, pcmcia_store_allow_func_id_match), __ATTR_NULL, }; +/*====================================================================== + + These manage a ring buffer of events pending for one user process + +======================================================================*/ + +static int queue_empty(user_info_t *user) +{ + return (user->event_head == user->event_tail); +} + +static event_t get_queued_event(user_info_t *user) +{ + user->event_tail = (user->event_tail+1) % MAX_EVENTS; + return user->event[user->event_tail]; +} + +static void queue_event(user_info_t *user, event_t event) +{ + user->event_head = (user->event_head+1) % MAX_EVENTS; + if (user->event_head == user->event_tail) + user->event_tail = (user->event_tail+1) % MAX_EVENTS; + user->event[user->event_head] = event; +} + +static void handle_event(struct pcmcia_bus_socket *s, event_t event) +{ + user_info_t *user; + for (user = s->user; user; user = user->next) + queue_event(user, event); + wake_up_interruptible(&s->queue); +} + + /*====================================================================== The card status event handler. @@ -932,13 +706,21 @@ static int send_event_callback(struct device *dev, void * _data) static int send_event(struct pcmcia_socket *s, event_t event, int priority) { + int ret = 0; struct send_event_data private; + struct pcmcia_bus_socket *skt = pcmcia_get_bus_socket(s->pcmcia); + + if (!skt) + return 0; private.skt = s; private.event = event; private.priority = priority; - return bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback); + ret = bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback); + + pcmcia_put_bus_socket(skt); + return ret; } /* send_event */ @@ -949,25 +731,25 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority) static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) { - struct pcmcia_socket *s = pcmcia_get_socket(skt); + struct pcmcia_bus_socket *s = skt->pcmcia; int ret = 0; ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n", - event, priority, skt); + event, priority, s); switch (event) { case CS_EVENT_CARD_REMOVAL: - s->pcmcia_state.present = 0; + s->state &= ~DS_SOCKET_PRESENT; send_event(skt, event, priority); - unbind_request(skt); - handle_event(skt, event); + unbind_request(s); + handle_event(s, event); break; case CS_EVENT_CARD_INSERTION: - s->pcmcia_state.present = 1; + s->state |= DS_SOCKET_PRESENT; pcmcia_card_add(skt); - handle_event(skt, event); + handle_event(s, event); break; case CS_EVENT_EJECTION_REQUEST: @@ -975,22 +757,137 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) break; default: - handle_event(skt, event); + handle_event(s, event); send_event(skt, event, priority); break; } - pcmcia_put_socket(s); - return 0; } /* ds_event */ +/*====================================================================== + + bind_request() and bind_device() are merged by now. Register_client() + is called right at the end of bind_request(), during the driver's + ->attach() call. Individual descriptions: + + bind_request() connects a socket to a particular client driver. + It looks up the specified device ID in the list of registered + drivers, binds it to the socket, and tries to create an instance + of the device. unbind_request() deletes a driver instance. + + Bind_device() associates a device driver with a particular socket. + It is normally called by Driver Services after it has identified + a newly inserted card. An instance of that driver will then be + eligible to register as a client of this socket. + + Register_client() uses the dev_info_t handle to match the + caller with a socket. The driver must have already been bound + to a socket with bind_device() -- in fact, bind_device() + allocates the client structure that will be used. + +======================================================================*/ + +static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info) +{ + struct pcmcia_driver *p_drv; + struct pcmcia_device *p_dev; + int ret = 0; + unsigned long flags; + + s = pcmcia_get_bus_socket(s); + if (!s) + return -EINVAL; + + ds_dbg(2, "bind_request(%d, '%s')\n", s->parent->sock, + (char *)bind_info->dev_info); + + p_drv = get_pcmcia_driver(&bind_info->dev_info); + if (!p_drv) { + ret = -EINVAL; + goto err_put; + } + + if (!try_module_get(p_drv->owner)) { + ret = -EINVAL; + goto err_put_driver; + } + + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { + if (p_dev->func == bind_info->function) { + if ((p_dev->dev.driver == &p_drv->drv)) { + if (p_dev->cardmgr) { + /* if there's already a device + * registered, and it was registered + * by userspace before, we need to + * return the "instance". */ + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + bind_info->instance = p_dev->instance; + ret = -EBUSY; + goto err_put_module; + } else { + /* the correct driver managed to bind + * itself magically to the correct + * device. */ + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + p_dev->cardmgr = p_drv; + ret = 0; + goto err_put_module; + } + } else if (!p_dev->dev.driver) { + /* there's already a device available where + * no device has been bound to yet. So we don't + * need to register a device! */ + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + goto rescan; + } + } + } + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + + p_dev = pcmcia_device_add(s, bind_info->function); + if (!p_dev) { + ret = -EIO; + goto err_put_module; + } + +rescan: + p_dev->cardmgr = p_drv; + + pcmcia_device_query(p_dev); + + /* + * Prevent this racing with a card insertion. + */ + down(&s->parent->skt_sem); + bus_rescan_devices(&pcmcia_bus_type); + up(&s->parent->skt_sem); + + /* check whether the driver indeed matched. I don't care if this + * is racy or not, because it can only happen on cardmgr access + * paths... + */ + if (!(p_dev->dev.driver == &p_drv->drv)) + p_dev->cardmgr = NULL; + + err_put_module: + module_put(p_drv->owner); + err_put_driver: + put_driver(&p_drv->drv); + err_put: + pcmcia_put_bus_socket(s); + + return (ret); +} /* bind_request */ + int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) { client_t *client = NULL; - struct pcmcia_socket *s = NULL; + struct pcmcia_socket *s; + struct pcmcia_bus_socket *skt = NULL; struct pcmcia_device *p_dev = NULL; /* Look for unbound client with matching dev_info */ @@ -1001,11 +898,14 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) if (s->state & SOCKET_CARDBUS) continue; - s = pcmcia_get_socket(s); - if (!s) + skt = s->pcmcia; + if (!skt) + continue; + skt = pcmcia_get_bus_socket(skt); + if (!skt) continue; spin_lock_irqsave(&pcmcia_dev_list_lock, flags); - list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { + list_for_each_entry(p_dev, &skt->devices_list, socket_device_list) { struct pcmcia_driver *p_drv; p_dev = pcmcia_get_dev(p_dev); if (!p_dev) @@ -1024,14 +924,14 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) pcmcia_put_dev(p_dev); } spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - pcmcia_put_socket(s); + pcmcia_put_bus_socket(skt); } found: up_read(&pcmcia_socket_list_rwsem); if (!p_dev || !client) return -ENODEV; - pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */ + pcmcia_put_bus_socket(skt); /* safe, as we already hold a reference from bind_device */ *handle = client; client->state &= ~CLIENT_UNBOUND; @@ -1078,15 +978,106 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req) EXPORT_SYMBOL(pcmcia_register_client); +/*====================================================================*/ + +extern struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s); + +static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info, int first) +{ + dev_node_t *node; + struct pcmcia_device *p_dev; + unsigned long flags; + int ret = 0; + +#ifdef CONFIG_CARDBUS + /* + * Some unbelievably ugly code to associate the PCI cardbus + * device and its driver with the PCMCIA "bind" information. + */ + { + struct pci_bus *bus; + + bus = pcmcia_lookup_bus(s->parent); + if (bus) { + struct list_head *list; + struct pci_dev *dev = NULL; + + list = bus->devices.next; + while (list != &bus->devices) { + struct pci_dev *pdev = pci_dev_b(list); + list = list->next; + + if (first) { + dev = pdev; + break; + } + + /* Try to handle "next" here some way? */ + } + if (dev && dev->driver) { + strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN); + bind_info->major = 0; + bind_info->minor = 0; + bind_info->next = NULL; + return 0; + } + } + } +#endif + + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { + if (p_dev->func == bind_info->function) { + p_dev = pcmcia_get_dev(p_dev); + if (!p_dev) + continue; + goto found; + } + } + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + return -ENODEV; + + found: + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + + if ((!p_dev->instance) || + (p_dev->instance->state & DEV_CONFIG_PENDING)) { + ret = -EAGAIN; + goto err_put; + } + + if (first) + node = p_dev->instance->dev; + else + for (node = p_dev->instance->dev; node; node = node->next) + if (node == bind_info->next) + break; + if (!node) { + ret = -ENODEV; + goto err_put; + } + + strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN); + bind_info->major = node->major; + bind_info->minor = node->minor; + bind_info->next = node->next; + + err_put: + pcmcia_put_dev(p_dev); + return (ret); +} /* get_device_info */ + +/*====================================================================*/ + /* unbind _all_ devices attached to a given pcmcia_bus_socket. The * drivers have been called with EVENT_CARD_REMOVAL before. */ -static int unbind_request(struct pcmcia_socket *s) +static int unbind_request(struct pcmcia_bus_socket *s) { struct pcmcia_device *p_dev; unsigned long flags; - ds_dbg(2, "unbind_request(%d)\n", s->sock); + ds_dbg(2, "unbind_request(%d)\n", s->parent->sock); s->device_count = 0; @@ -1142,58 +1133,433 @@ int pcmcia_deregister_client(client_handle_t handle) } /* deregister_client */ EXPORT_SYMBOL(pcmcia_deregister_client); -static struct pcmcia_callback pcmcia_bus_callback = { - .owner = THIS_MODULE, - .event = ds_event, - .requery = pcmcia_bus_rescan, + +/*====================================================================== + + The user-mode PC Card device interface + +======================================================================*/ + +static int ds_open(struct inode *inode, struct file *file) +{ + socket_t i = iminor(inode); + struct pcmcia_bus_socket *s; + user_info_t *user; + + ds_dbg(0, "ds_open(socket %d)\n", i); + + s = get_socket_info_by_nr(i); + if (!s) + return -ENODEV; + s = pcmcia_get_bus_socket(s); + if (!s) + return -ENODEV; + + if ((file->f_flags & O_ACCMODE) != O_RDONLY) { + if (s->state & DS_SOCKET_BUSY) { + pcmcia_put_bus_socket(s); + return -EBUSY; + } + else + s->state |= DS_SOCKET_BUSY; + } + + user = kmalloc(sizeof(user_info_t), GFP_KERNEL); + if (!user) { + pcmcia_put_bus_socket(s); + return -ENOMEM; + } + user->event_tail = user->event_head = 0; + user->next = s->user; + user->user_magic = USER_MAGIC; + user->socket = s; + s->user = user; + file->private_data = user; + + if (s->state & DS_SOCKET_PRESENT) + queue_event(user, CS_EVENT_CARD_INSERTION); + return 0; +} /* ds_open */ + +/*====================================================================*/ + +static int ds_release(struct inode *inode, struct file *file) +{ + struct pcmcia_bus_socket *s; + user_info_t *user, **link; + + ds_dbg(0, "ds_release(socket %d)\n", iminor(inode)); + + user = file->private_data; + if (CHECK_USER(user)) + goto out; + + s = user->socket; + + /* Unlink user data structure */ + if ((file->f_flags & O_ACCMODE) != O_RDONLY) { + s->state &= ~DS_SOCKET_BUSY; + } + file->private_data = NULL; + for (link = &s->user; *link; link = &(*link)->next) + if (*link == user) break; + if (link == NULL) + goto out; + *link = user->next; + user->user_magic = 0; + kfree(user); + pcmcia_put_bus_socket(s); +out: + return 0; +} /* ds_release */ + +/*====================================================================*/ + +static ssize_t ds_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct pcmcia_bus_socket *s; + user_info_t *user; + int ret; + + ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode)); + + if (count < 4) + return -EINVAL; + + user = file->private_data; + if (CHECK_USER(user)) + return -EIO; + + s = user->socket; + if (s->state & DS_SOCKET_DEAD) + return -EIO; + + ret = wait_event_interruptible(s->queue, !queue_empty(user)); + if (ret == 0) + ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4; + + return ret; +} /* ds_read */ + +/*====================================================================*/ + +static ssize_t ds_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode)); + + if (count != 4) + return -EINVAL; + if ((file->f_flags & O_ACCMODE) == O_RDONLY) + return -EBADF; + + return -EIO; +} /* ds_write */ + +/*====================================================================*/ + +/* No kernel lock - fine */ +static u_int ds_poll(struct file *file, poll_table *wait) +{ + struct pcmcia_bus_socket *s; + user_info_t *user; + + ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode)); + + user = file->private_data; + if (CHECK_USER(user)) + return POLLERR; + s = user->socket; + /* + * We don't check for a dead socket here since that + * will send cardmgr into an endless spin. + */ + poll_wait(file, &s->queue, wait); + if (!queue_empty(user)) + return POLLIN | POLLRDNORM; + return 0; +} /* ds_poll */ + +/*====================================================================*/ + +extern int pcmcia_adjust_resource_info(adjust_t *adj); + +static int ds_ioctl(struct inode * inode, struct file * file, + u_int cmd, u_long arg) +{ + struct pcmcia_bus_socket *s; + void __user *uarg = (char __user *)arg; + u_int size; + int ret, err; + ds_ioctl_arg_t *buf; + user_info_t *user; + + ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg); + + user = file->private_data; + if (CHECK_USER(user)) + return -EIO; + + s = user->socket; + if (s->state & DS_SOCKET_DEAD) + return -EIO; + + size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; + if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; + + /* Permission check */ + if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (cmd & IOC_IN) { + if (!access_ok(VERIFY_READ, uarg, size)) { + ds_dbg(3, "ds_ioctl(): verify_read = %d\n", -EFAULT); + return -EFAULT; + } + } + if (cmd & IOC_OUT) { + if (!access_ok(VERIFY_WRITE, uarg, size)) { + ds_dbg(3, "ds_ioctl(): verify_write = %d\n", -EFAULT); + return -EFAULT; + } + } + buf = kmalloc(sizeof(ds_ioctl_arg_t), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + err = ret = 0; + + if (cmd & IOC_IN) __copy_from_user((char *)buf, uarg, size); + + switch (cmd) { + case DS_ADJUST_RESOURCE_INFO: + ret = pcmcia_adjust_resource_info(&buf->adjust); + break; + case DS_GET_CARD_SERVICES_INFO: + ret = pcmcia_get_card_services_info(&buf->servinfo); + break; + case DS_GET_CONFIGURATION_INFO: + if (buf->config.Function && + (buf->config.Function >= s->parent->functions)) + ret = CS_BAD_ARGS; + else + ret = pccard_get_configuration_info(s->parent, + buf->config.Function, &buf->config); + break; + case DS_GET_FIRST_TUPLE: + down(&s->parent->skt_sem); + pcmcia_validate_mem(s->parent); + up(&s->parent->skt_sem); + ret = pccard_get_first_tuple(s->parent, BIND_FN_ALL, &buf->tuple); + break; + case DS_GET_NEXT_TUPLE: + ret = pccard_get_next_tuple(s->parent, BIND_FN_ALL, &buf->tuple); + break; + case DS_GET_TUPLE_DATA: + buf->tuple.TupleData = buf->tuple_parse.data; + buf->tuple.TupleDataMax = sizeof(buf->tuple_parse.data); + ret = pccard_get_tuple_data(s->parent, &buf->tuple); + break; + case DS_PARSE_TUPLE: + buf->tuple.TupleData = buf->tuple_parse.data; + ret = pccard_parse_tuple(&buf->tuple, &buf->tuple_parse.parse); + break; + case DS_RESET_CARD: + ret = pccard_reset_card(s->parent); + break; + case DS_GET_STATUS: + if (buf->status.Function && + (buf->status.Function >= s->parent->functions)) + ret = CS_BAD_ARGS; + else + ret = pccard_get_status(s->parent, buf->status.Function, &buf->status); + break; + case DS_VALIDATE_CIS: + down(&s->parent->skt_sem); + pcmcia_validate_mem(s->parent); + up(&s->parent->skt_sem); + ret = pccard_validate_cis(s->parent, BIND_FN_ALL, &buf->cisinfo); + break; + case DS_SUSPEND_CARD: + ret = pcmcia_suspend_card(s->parent); + break; + case DS_RESUME_CARD: + ret = pcmcia_resume_card(s->parent); + break; + case DS_EJECT_CARD: + err = pcmcia_eject_card(s->parent); + break; + case DS_INSERT_CARD: + err = pcmcia_insert_card(s->parent); + break; + case DS_ACCESS_CONFIGURATION_REGISTER: + if ((buf->conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) { + err = -EPERM; + goto free_out; + } + if (buf->conf_reg.Function && + (buf->conf_reg.Function >= s->parent->functions)) + ret = CS_BAD_ARGS; + else + ret = pccard_access_configuration_register(s->parent, + buf->conf_reg.Function, &buf->conf_reg); + break; + case DS_GET_FIRST_REGION: + case DS_GET_NEXT_REGION: + case DS_BIND_MTD: + if (!capable(CAP_SYS_ADMIN)) { + err = -EPERM; + goto free_out; + } else { + static int printed = 0; + if (!printed) { + printk(KERN_WARNING "2.6. kernels use pcmciamtd instead of memory_cs.c and do not require special\n"); + printk(KERN_WARNING "MTD handling any more.\n"); + printed++; + } + } + err = -EINVAL; + goto free_out; + break; + case DS_GET_FIRST_WINDOW: + ret = pcmcia_get_window(s->parent, &buf->win_info.handle, 0, + &buf->win_info.window); + break; + case DS_GET_NEXT_WINDOW: + ret = pcmcia_get_window(s->parent, &buf->win_info.handle, + buf->win_info.handle->index + 1, &buf->win_info.window); + break; + case DS_GET_MEM_PAGE: + ret = pcmcia_get_mem_page(buf->win_info.handle, + &buf->win_info.map); + break; + case DS_REPLACE_CIS: + ret = pcmcia_replace_cis(s->parent, &buf->cisdump); + break; + case DS_BIND_REQUEST: + if (!capable(CAP_SYS_ADMIN)) { + err = -EPERM; + goto free_out; + } + err = bind_request(s, &buf->bind_info); + break; + case DS_GET_DEVICE_INFO: + err = get_device_info(s, &buf->bind_info, 1); + break; + case DS_GET_NEXT_DEVICE: + err = get_device_info(s, &buf->bind_info, 0); + break; + case DS_UNBIND_REQUEST: + err = 0; + break; + default: + err = -EINVAL; + } + + if ((err == 0) && (ret != CS_SUCCESS)) { + ds_dbg(2, "ds_ioctl: ret = %d\n", ret); + switch (ret) { + case CS_BAD_SOCKET: case CS_NO_CARD: + err = -ENODEV; break; + case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ: + case CS_BAD_TUPLE: + err = -EINVAL; break; + case CS_IN_USE: + err = -EBUSY; break; + case CS_OUT_OF_RESOURCE: + err = -ENOSPC; break; + case CS_NO_MORE_ITEMS: + err = -ENODATA; break; + case CS_UNSUPPORTED_FUNCTION: + err = -ENOSYS; break; + default: + err = -EIO; break; + } + } + + if (cmd & IOC_OUT) { + if (__copy_to_user(uarg, (char *)buf, size)) + err = -EFAULT; + } + +free_out: + kfree(buf); + return err; +} /* ds_ioctl */ + +/*====================================================================*/ + +static struct file_operations ds_fops = { + .owner = THIS_MODULE, + .open = ds_open, + .release = ds_release, + .ioctl = ds_ioctl, + .read = ds_read, + .write = ds_write, + .poll = ds_poll, }; static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev) { struct pcmcia_socket *socket = class_get_devdata(class_dev); + struct pcmcia_bus_socket *s; int ret; - socket = pcmcia_get_socket(socket); - if (!socket) { + s = kmalloc(sizeof(struct pcmcia_bus_socket), GFP_KERNEL); + if(!s) + return -ENOMEM; + memset(s, 0, sizeof(struct pcmcia_bus_socket)); + + /* get reference to parent socket */ + s->parent = pcmcia_get_socket(socket); + if (!s->parent) { printk(KERN_ERR "PCMCIA obtaining reference to socket %p failed\n", socket); + kfree (s); return -ENODEV; } + kref_init(&s->refcount); + /* * Ugly. But we want to wait for the socket threads to have started up. * We really should let the drivers themselves drive some of this.. */ msleep(250); -#ifdef CONFIG_PCMCIA_IOCTL - init_waitqueue_head(&socket->queue); -#endif - INIT_LIST_HEAD(&socket->devices_list); - INIT_WORK(&socket->device_add, pcmcia_delayed_add_pseudo_device, socket); - memset(&socket->pcmcia_state, 0, sizeof(u8)); - socket->device_count = 0; + init_waitqueue_head(&s->queue); + INIT_LIST_HEAD(&s->devices_list); + + /* Set up hotline to Card Services */ + s->callback.owner = THIS_MODULE; + s->callback.event = &ds_event; + s->callback.resources_done = &pcmcia_card_add; + socket->pcmcia = s; - ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback); + ret = pccard_register_pcmcia(socket, &s->callback); if (ret) { printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket); - pcmcia_put_socket(socket); + pcmcia_put_bus_socket(s); + socket->pcmcia = NULL; return (ret); } return 0; } + static void pcmcia_bus_remove_socket(struct class_device *class_dev) { struct pcmcia_socket *socket = class_get_devdata(class_dev); - if (!socket) + if (!socket || !socket->pcmcia) return; - socket->pcmcia_state.dead = 1; pccard_register_pcmcia(socket, NULL); - pcmcia_put_socket(socket); + socket->pcmcia->state |= DS_SOCKET_DEAD; + pcmcia_put_bus_socket(socket->pcmcia); + socket->pcmcia = NULL; return; } @@ -1209,20 +1575,34 @@ static struct class_interface pcmcia_bus_interface = { struct bus_type pcmcia_bus_type = { .name = "pcmcia", - .hotplug = pcmcia_bus_hotplug, .match = pcmcia_bus_match, .dev_attrs = pcmcia_dev_attrs, }; +EXPORT_SYMBOL(pcmcia_bus_type); static int __init init_pcmcia_bus(void) { + int i; + spin_lock_init(&pcmcia_dev_list_lock); bus_register(&pcmcia_bus_type); class_interface_register(&pcmcia_bus_interface); - pcmcia_setup_ioctl(); + /* Set up character device for user mode clients */ + i = register_chrdev(0, "pcmcia", &ds_fops); + if (i < 0) + printk(KERN_NOTICE "unable to find a free device # for " + "Driver Services (error=%d)\n", i); + else + major_dev = i; + +#ifdef CONFIG_PROC_FS + proc_pccard = proc_mkdir("pccard", proc_bus); + if (proc_pccard) + create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL); +#endif return 0; } @@ -1232,13 +1612,48 @@ fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that static void __exit exit_pcmcia_bus(void) { - pcmcia_cleanup_ioctl(); - class_interface_unregister(&pcmcia_bus_interface); +#ifdef CONFIG_PROC_FS + if (proc_pccard) { + remove_proc_entry("drivers", proc_pccard); + remove_proc_entry("pccard", proc_bus); + } +#endif + if (major_dev != -1) + unregister_chrdev(major_dev, "pcmcia"); + bus_unregister(&pcmcia_bus_type); } module_exit(exit_pcmcia_bus); + +/* helpers for backwards-compatible functions */ + +static struct pcmcia_bus_socket * get_socket_info_by_nr(unsigned int nr) +{ + struct pcmcia_socket * s = pcmcia_get_socket_by_nr(nr); + if (s && s->pcmcia) + return s->pcmcia; + else + return NULL; +} + +/* backwards-compatible accessing of driver --- by name! */ + +static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info) +{ + struct device_driver *drv; + struct pcmcia_driver *p_drv; + + drv = driver_find((char *) dev_info, &pcmcia_bus_type); + if (!drv) + return NULL; + + p_drv = container_of(drv, struct pcmcia_driver, drv); + + return (p_drv); +} + MODULE_ALIAS("ds"); diff --git a/trunk/drivers/pcmcia/ds_internal.h b/trunk/drivers/pcmcia/ds_internal.h deleted file mode 100644 index d359bd25a51c..000000000000 --- a/trunk/drivers/pcmcia/ds_internal.h +++ /dev/null @@ -1,21 +0,0 @@ -/* ds_internal.h - internal header for 16-bit PCMCIA devices management */ - -extern spinlock_t pcmcia_dev_list_lock; -extern struct bus_type pcmcia_bus_type; - -extern struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev); -extern void pcmcia_put_dev(struct pcmcia_device *p_dev); - -struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function); - -#ifdef CONFIG_PCMCIA_IOCTL -extern void __init pcmcia_setup_ioctl(void); -extern void __exit pcmcia_cleanup_ioctl(void); -extern void handle_event(struct pcmcia_socket *s, event_t event); -extern int handle_request(struct pcmcia_socket *s, event_t event); -#else -static inline void __init pcmcia_setup_ioctl(void) { return; } -static inline void __init pcmcia_cleanup_ioctl(void) { return; } -static inline void handle_event(struct pcmcia_socket *s, event_t event) { return; } -static inline int handle_request(struct pcmcia_socket *s, event_t event) { return CS_SUCCESS; } -#endif diff --git a/trunk/drivers/pcmcia/i82365.c b/trunk/drivers/pcmcia/i82365.c index d72f9a35c8bd..90a335a5d9fa 100644 --- a/trunk/drivers/pcmcia/i82365.c +++ b/trunk/drivers/pcmcia/i82365.c @@ -669,13 +669,11 @@ static int __init is_alive(u_short sock) if ((stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) && (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) && (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(0)) && - ((start & 0xfeef) != 0x02e8)) { - if (!request_region(start, stop-start+1, "i82365")) - return 1; - release_region(start, stop-start+1); - } - - return 0; + (check_region(start, stop-start+1) != 0) && + ((start & 0xfeef) != 0x02e8)) + return 1; + else + return 0; } /*====================================================================*/ @@ -698,13 +696,7 @@ static void __init add_pcic(int ns, int type) struct i82365_socket *t = &socket[sockets-ns]; base = sockets-ns; - if (t->ioaddr > 0) { - if (!request_region(t->ioaddr, 2, "i82365")) { - printk(KERN_ERR "i82365: IO region conflict at %#lx, not available\n", - t->ioaddr); - return; - } - } + if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365"); if (base == 0) printk("\n"); printk(KERN_INFO " %s", pcic[type].name); @@ -811,7 +803,7 @@ static void __init isa_probe(void) } #endif - if (!request_region(i365_base, 2, "i82365")) { + if (check_region(i365_base, 2) != 0) { if (sockets == 0) printk("port conflict at %#lx\n", i365_base); return; @@ -1449,7 +1441,6 @@ static void __exit exit_i82365(void) i365_set(i, I365_CSCINT, 0); release_region(socket[i].ioaddr, 2); } - release_region(i365_base, 2); #ifdef CONFIG_PNP if (i82365_pnpdev) pnp_disable_dev(i82365_pnpdev); diff --git a/trunk/drivers/pcmcia/pcmcia_compat.c b/trunk/drivers/pcmcia/pcmcia_compat.c index 1cc83317e7e3..68b80084f83f 100644 --- a/trunk/drivers/pcmcia/pcmcia_compat.c +++ b/trunk/drivers/pcmcia/pcmcia_compat.c @@ -74,6 +74,19 @@ int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info) } EXPORT_SYMBOL(pcmcia_validate_cis); +int pcmcia_get_configuration_info(client_handle_t handle, + config_info_t *config) +{ + struct pcmcia_socket *s; + + if ((CHECK_HANDLE(handle)) || !config) + return CS_BAD_HANDLE; + s = SOCKET(handle); + if (!s) + return CS_BAD_HANDLE; + return pccard_get_configuration_info(s, handle->Function, config); +} +EXPORT_SYMBOL(pcmcia_get_configuration_info); int pcmcia_reset_card(client_handle_t handle, client_req_t *req) { @@ -89,3 +102,24 @@ int pcmcia_reset_card(client_handle_t handle, client_req_t *req) } EXPORT_SYMBOL(pcmcia_reset_card); +int pcmcia_get_status(client_handle_t handle, cs_status_t *status) +{ + struct pcmcia_socket *s; + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + s = SOCKET(handle); + return pccard_get_status(s, handle->Function, status); +} +EXPORT_SYMBOL(pcmcia_get_status); + +int pcmcia_access_configuration_register(client_handle_t handle, + conf_reg_t *reg) +{ + struct pcmcia_socket *s; + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + s = SOCKET(handle); + return pccard_access_configuration_register(s, handle->Function, reg); +} +EXPORT_SYMBOL(pcmcia_access_configuration_register); + diff --git a/trunk/drivers/pcmcia/pcmcia_ioctl.c b/trunk/drivers/pcmcia/pcmcia_ioctl.c deleted file mode 100644 index b883bc151ed0..000000000000 --- a/trunk/drivers/pcmcia/pcmcia_ioctl.c +++ /dev/null @@ -1,786 +0,0 @@ -/* - * pcmcia_ioctl.c -- ioctl interface for cardmgr and cardctl - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds - * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - * - * (C) 1999 David A. Hinds - * (C) 2003 - 2004 Dominik Brodowski - */ - -/* - * This file will go away soon. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IN_CARD_SERVICES -#include -#include -#include -#include -#include -#include - -#include "cs_internal.h" -#include "ds_internal.h" - -static int major_dev = -1; - - -/* Device user information */ -#define MAX_EVENTS 32 -#define USER_MAGIC 0x7ea4 -#define CHECK_USER(u) \ - (((u) == NULL) || ((u)->user_magic != USER_MAGIC)) - -typedef struct user_info_t { - u_int user_magic; - int event_head, event_tail; - event_t event[MAX_EVENTS]; - struct user_info_t *next; - struct pcmcia_socket *socket; -} user_info_t; - - -#ifdef DEBUG -extern int ds_pc_debug; -#define cs_socket_name(skt) ((skt)->dev.class_id) - -#define ds_dbg(lvl, fmt, arg...) do { \ - if (ds_pc_debug >= lvl) \ - printk(KERN_DEBUG "ds: " fmt , ## arg); \ -} while (0) -#else -#define ds_dbg(lvl, fmt, arg...) do { } while (0) -#endif - -static const char *release = "Linux Kernel Card Services"; - -/** pcmcia_get_card_services_info - * - * Return information about this version of Card Services - */ -static int pcmcia_get_card_services_info(servinfo_t *info) -{ - unsigned int socket_count = 0; - struct list_head *tmp; - info->Signature[0] = 'C'; - info->Signature[1] = 'S'; - down_read(&pcmcia_socket_list_rwsem); - list_for_each(tmp, &pcmcia_socket_list) - socket_count++; - up_read(&pcmcia_socket_list_rwsem); - info->Count = socket_count; - info->Revision = CS_RELEASE_CODE; - info->CSLevel = 0x0210; - info->VendorString = (char *)release; - return CS_SUCCESS; -} /* get_card_services_info */ - - -/* backwards-compatible accessing of driver --- by name! */ - -static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info) -{ - struct device_driver *drv; - struct pcmcia_driver *p_drv; - - drv = driver_find((char *) dev_info, &pcmcia_bus_type); - if (!drv) - return NULL; - - p_drv = container_of(drv, struct pcmcia_driver, drv); - - return (p_drv); -} - - -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *proc_pccard = NULL; - -static int proc_read_drivers_callback(struct device_driver *driver, void *d) -{ - char **p = d; - struct pcmcia_driver *p_drv = container_of(driver, - struct pcmcia_driver, drv); - - *p += sprintf(*p, "%-24.24s 1 %d\n", p_drv->drv.name, -#ifdef CONFIG_MODULE_UNLOAD - (p_drv->owner) ? module_refcount(p_drv->owner) : 1 -#else - 1 -#endif - ); - d = (void *) p; - - return 0; -} - -static int proc_read_drivers(char *buf, char **start, off_t pos, - int count, int *eof, void *data) -{ - char *p = buf; - - bus_for_each_drv(&pcmcia_bus_type, NULL, - (void *) &p, proc_read_drivers_callback); - - return (p - buf); -} -#endif - -/*====================================================================== - - These manage a ring buffer of events pending for one user process - -======================================================================*/ - - -static int queue_empty(user_info_t *user) -{ - return (user->event_head == user->event_tail); -} - -static event_t get_queued_event(user_info_t *user) -{ - user->event_tail = (user->event_tail+1) % MAX_EVENTS; - return user->event[user->event_tail]; -} - -static void queue_event(user_info_t *user, event_t event) -{ - user->event_head = (user->event_head+1) % MAX_EVENTS; - if (user->event_head == user->event_tail) - user->event_tail = (user->event_tail+1) % MAX_EVENTS; - user->event[user->event_head] = event; -} - -void handle_event(struct pcmcia_socket *s, event_t event) -{ - user_info_t *user; - for (user = s->user; user; user = user->next) - queue_event(user, event); - wake_up_interruptible(&s->queue); -} - - -/*====================================================================== - - bind_request() and bind_device() are merged by now. Register_client() - is called right at the end of bind_request(), during the driver's - ->attach() call. Individual descriptions: - - bind_request() connects a socket to a particular client driver. - It looks up the specified device ID in the list of registered - drivers, binds it to the socket, and tries to create an instance - of the device. unbind_request() deletes a driver instance. - - Bind_device() associates a device driver with a particular socket. - It is normally called by Driver Services after it has identified - a newly inserted card. An instance of that driver will then be - eligible to register as a client of this socket. - - Register_client() uses the dev_info_t handle to match the - caller with a socket. The driver must have already been bound - to a socket with bind_device() -- in fact, bind_device() - allocates the client structure that will be used. - -======================================================================*/ - -static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info) -{ - struct pcmcia_driver *p_drv; - struct pcmcia_device *p_dev; - int ret = 0; - unsigned long flags; - - s = pcmcia_get_socket(s); - if (!s) - return -EINVAL; - - ds_dbg(2, "bind_request(%d, '%s')\n", s->sock, - (char *)bind_info->dev_info); - - p_drv = get_pcmcia_driver(&bind_info->dev_info); - if (!p_drv) { - ret = -EINVAL; - goto err_put; - } - - if (!try_module_get(p_drv->owner)) { - ret = -EINVAL; - goto err_put_driver; - } - - spin_lock_irqsave(&pcmcia_dev_list_lock, flags); - list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { - if (p_dev->func == bind_info->function) { - if ((p_dev->dev.driver == &p_drv->drv)) { - if (p_dev->cardmgr) { - /* if there's already a device - * registered, and it was registered - * by userspace before, we need to - * return the "instance". */ - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - bind_info->instance = p_dev->instance; - ret = -EBUSY; - goto err_put_module; - } else { - /* the correct driver managed to bind - * itself magically to the correct - * device. */ - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - p_dev->cardmgr = p_drv; - ret = 0; - goto err_put_module; - } - } else if (!p_dev->dev.driver) { - /* there's already a device available where - * no device has been bound to yet. So we don't - * need to register a device! */ - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - goto rescan; - } - } - } - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - - p_dev = pcmcia_device_add(s, bind_info->function); - if (!p_dev) { - ret = -EIO; - goto err_put_module; - } - -rescan: - p_dev->cardmgr = p_drv; - - /* if a driver is already running, we can abort */ - if (p_dev->dev.driver) - goto err_put_module; - - /* - * Prevent this racing with a card insertion. - */ - down(&s->skt_sem); - bus_rescan_devices(&pcmcia_bus_type); - up(&s->skt_sem); - - /* check whether the driver indeed matched. I don't care if this - * is racy or not, because it can only happen on cardmgr access - * paths... - */ - if (!(p_dev->dev.driver == &p_drv->drv)) - p_dev->cardmgr = NULL; - - err_put_module: - module_put(p_drv->owner); - err_put_driver: - put_driver(&p_drv->drv); - err_put: - pcmcia_put_socket(s); - - return (ret); -} /* bind_request */ - -#ifdef CONFIG_CARDBUS - -static struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s) -{ - if (!s || !(s->state & SOCKET_CARDBUS)) - return NULL; - - return s->cb_dev->subordinate; -} -#endif - -static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int first) -{ - dev_node_t *node; - struct pcmcia_device *p_dev; - unsigned long flags; - int ret = 0; - -#ifdef CONFIG_CARDBUS - /* - * Some unbelievably ugly code to associate the PCI cardbus - * device and its driver with the PCMCIA "bind" information. - */ - { - struct pci_bus *bus; - - bus = pcmcia_lookup_bus(s); - if (bus) { - struct list_head *list; - struct pci_dev *dev = NULL; - - list = bus->devices.next; - while (list != &bus->devices) { - struct pci_dev *pdev = pci_dev_b(list); - list = list->next; - - if (first) { - dev = pdev; - break; - } - - /* Try to handle "next" here some way? */ - } - if (dev && dev->driver) { - strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN); - bind_info->major = 0; - bind_info->minor = 0; - bind_info->next = NULL; - return 0; - } - } - } -#endif - - spin_lock_irqsave(&pcmcia_dev_list_lock, flags); - list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { - if (p_dev->func == bind_info->function) { - p_dev = pcmcia_get_dev(p_dev); - if (!p_dev) - continue; - goto found; - } - } - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - return -ENODEV; - - found: - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - - if ((!p_dev->instance) || - (p_dev->instance->state & DEV_CONFIG_PENDING)) { - ret = -EAGAIN; - goto err_put; - } - - if (first) - node = p_dev->instance->dev; - else - for (node = p_dev->instance->dev; node; node = node->next) - if (node == bind_info->next) - break; - if (!node) { - ret = -ENODEV; - goto err_put; - } - - strlcpy(bind_info->name, node->dev_name, DEV_NAME_LEN); - bind_info->major = node->major; - bind_info->minor = node->minor; - bind_info->next = node->next; - - err_put: - pcmcia_put_dev(p_dev); - return (ret); -} /* get_device_info */ - - -static int ds_open(struct inode *inode, struct file *file) -{ - socket_t i = iminor(inode); - struct pcmcia_socket *s; - user_info_t *user; - - ds_dbg(0, "ds_open(socket %d)\n", i); - - s = pcmcia_get_socket_by_nr(i); - if (!s) - return -ENODEV; - s = pcmcia_get_socket(s); - if (!s) - return -ENODEV; - - if ((file->f_flags & O_ACCMODE) != O_RDONLY) { - if (s->pcmcia_state.busy) { - pcmcia_put_socket(s); - return -EBUSY; - } - else - s->pcmcia_state.busy = 1; - } - - user = kmalloc(sizeof(user_info_t), GFP_KERNEL); - if (!user) { - pcmcia_put_socket(s); - return -ENOMEM; - } - user->event_tail = user->event_head = 0; - user->next = s->user; - user->user_magic = USER_MAGIC; - user->socket = s; - s->user = user; - file->private_data = user; - - if (s->pcmcia_state.present) - queue_event(user, CS_EVENT_CARD_INSERTION); - return 0; -} /* ds_open */ - -/*====================================================================*/ - -static int ds_release(struct inode *inode, struct file *file) -{ - struct pcmcia_socket *s; - user_info_t *user, **link; - - ds_dbg(0, "ds_release(socket %d)\n", iminor(inode)); - - user = file->private_data; - if (CHECK_USER(user)) - goto out; - - s = user->socket; - - /* Unlink user data structure */ - if ((file->f_flags & O_ACCMODE) != O_RDONLY) { - s->pcmcia_state.busy = 0; - } - file->private_data = NULL; - for (link = &s->user; *link; link = &(*link)->next) - if (*link == user) break; - if (link == NULL) - goto out; - *link = user->next; - user->user_magic = 0; - kfree(user); - pcmcia_put_socket(s); -out: - return 0; -} /* ds_release */ - -/*====================================================================*/ - -static ssize_t ds_read(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - struct pcmcia_socket *s; - user_info_t *user; - int ret; - - ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode)); - - if (count < 4) - return -EINVAL; - - user = file->private_data; - if (CHECK_USER(user)) - return -EIO; - - s = user->socket; - if (s->pcmcia_state.dead) - return -EIO; - - ret = wait_event_interruptible(s->queue, !queue_empty(user)); - if (ret == 0) - ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4; - - return ret; -} /* ds_read */ - -/*====================================================================*/ - -static ssize_t ds_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode)); - - if (count != 4) - return -EINVAL; - if ((file->f_flags & O_ACCMODE) == O_RDONLY) - return -EBADF; - - return -EIO; -} /* ds_write */ - -/*====================================================================*/ - -/* No kernel lock - fine */ -static u_int ds_poll(struct file *file, poll_table *wait) -{ - struct pcmcia_socket *s; - user_info_t *user; - - ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode)); - - user = file->private_data; - if (CHECK_USER(user)) - return POLLERR; - s = user->socket; - /* - * We don't check for a dead socket here since that - * will send cardmgr into an endless spin. - */ - poll_wait(file, &s->queue, wait); - if (!queue_empty(user)) - return POLLIN | POLLRDNORM; - return 0; -} /* ds_poll */ - -/*====================================================================*/ - -extern int pcmcia_adjust_resource_info(adjust_t *adj); - -static int ds_ioctl(struct inode * inode, struct file * file, - u_int cmd, u_long arg) -{ - struct pcmcia_socket *s; - void __user *uarg = (char __user *)arg; - u_int size; - int ret, err; - ds_ioctl_arg_t *buf; - user_info_t *user; - - ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg); - - user = file->private_data; - if (CHECK_USER(user)) - return -EIO; - - s = user->socket; - if (s->pcmcia_state.dead) - return -EIO; - - size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; - if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; - - /* Permission check */ - if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (cmd & IOC_IN) { - if (!access_ok(VERIFY_READ, uarg, size)) { - ds_dbg(3, "ds_ioctl(): verify_read = %d\n", -EFAULT); - return -EFAULT; - } - } - if (cmd & IOC_OUT) { - if (!access_ok(VERIFY_WRITE, uarg, size)) { - ds_dbg(3, "ds_ioctl(): verify_write = %d\n", -EFAULT); - return -EFAULT; - } - } - buf = kmalloc(sizeof(ds_ioctl_arg_t), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - err = ret = 0; - - if (cmd & IOC_IN) __copy_from_user((char *)buf, uarg, size); - - switch (cmd) { - case DS_ADJUST_RESOURCE_INFO: - ret = pcmcia_adjust_resource_info(&buf->adjust); - break; - case DS_GET_CARD_SERVICES_INFO: - ret = pcmcia_get_card_services_info(&buf->servinfo); - break; - case DS_GET_CONFIGURATION_INFO: - if (buf->config.Function && - (buf->config.Function >= s->functions)) - ret = CS_BAD_ARGS; - else - ret = pccard_get_configuration_info(s, - buf->config.Function, &buf->config); - break; - case DS_GET_FIRST_TUPLE: - down(&s->skt_sem); - pcmcia_validate_mem(s); - up(&s->skt_sem); - ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple); - break; - case DS_GET_NEXT_TUPLE: - ret = pccard_get_next_tuple(s, BIND_FN_ALL, &buf->tuple); - break; - case DS_GET_TUPLE_DATA: - buf->tuple.TupleData = buf->tuple_parse.data; - buf->tuple.TupleDataMax = sizeof(buf->tuple_parse.data); - ret = pccard_get_tuple_data(s, &buf->tuple); - break; - case DS_PARSE_TUPLE: - buf->tuple.TupleData = buf->tuple_parse.data; - ret = pccard_parse_tuple(&buf->tuple, &buf->tuple_parse.parse); - break; - case DS_RESET_CARD: - ret = pccard_reset_card(s); - break; - case DS_GET_STATUS: - if (buf->status.Function && - (buf->status.Function >= s->functions)) - ret = CS_BAD_ARGS; - else - ret = pccard_get_status(s, buf->status.Function, &buf->status); - break; - case DS_VALIDATE_CIS: - down(&s->skt_sem); - pcmcia_validate_mem(s); - up(&s->skt_sem); - ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo); - break; - case DS_SUSPEND_CARD: - ret = pcmcia_suspend_card(s); - break; - case DS_RESUME_CARD: - ret = pcmcia_resume_card(s); - break; - case DS_EJECT_CARD: - err = pcmcia_eject_card(s); - break; - case DS_INSERT_CARD: - err = pcmcia_insert_card(s); - break; - case DS_ACCESS_CONFIGURATION_REGISTER: - if ((buf->conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) { - err = -EPERM; - goto free_out; - } - if (buf->conf_reg.Function && - (buf->conf_reg.Function >= s->functions)) - ret = CS_BAD_ARGS; - else - ret = pccard_access_configuration_register(s, - buf->conf_reg.Function, &buf->conf_reg); - break; - case DS_GET_FIRST_REGION: - case DS_GET_NEXT_REGION: - case DS_BIND_MTD: - if (!capable(CAP_SYS_ADMIN)) { - err = -EPERM; - goto free_out; - } else { - static int printed = 0; - if (!printed) { - printk(KERN_WARNING "2.6. kernels use pcmciamtd instead of memory_cs.c and do not require special\n"); - printk(KERN_WARNING "MTD handling any more.\n"); - printed++; - } - } - err = -EINVAL; - goto free_out; - break; - case DS_GET_FIRST_WINDOW: - ret = pcmcia_get_window(s, &buf->win_info.handle, 0, - &buf->win_info.window); - break; - case DS_GET_NEXT_WINDOW: - ret = pcmcia_get_window(s, &buf->win_info.handle, - buf->win_info.handle->index + 1, &buf->win_info.window); - break; - case DS_GET_MEM_PAGE: - ret = pcmcia_get_mem_page(buf->win_info.handle, - &buf->win_info.map); - break; - case DS_REPLACE_CIS: - ret = pcmcia_replace_cis(s, &buf->cisdump); - break; - case DS_BIND_REQUEST: - if (!capable(CAP_SYS_ADMIN)) { - err = -EPERM; - goto free_out; - } - err = bind_request(s, &buf->bind_info); - break; - case DS_GET_DEVICE_INFO: - err = get_device_info(s, &buf->bind_info, 1); - break; - case DS_GET_NEXT_DEVICE: - err = get_device_info(s, &buf->bind_info, 0); - break; - case DS_UNBIND_REQUEST: - err = 0; - break; - default: - err = -EINVAL; - } - - if ((err == 0) && (ret != CS_SUCCESS)) { - ds_dbg(2, "ds_ioctl: ret = %d\n", ret); - switch (ret) { - case CS_BAD_SOCKET: case CS_NO_CARD: - err = -ENODEV; break; - case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ: - case CS_BAD_TUPLE: - err = -EINVAL; break; - case CS_IN_USE: - err = -EBUSY; break; - case CS_OUT_OF_RESOURCE: - err = -ENOSPC; break; - case CS_NO_MORE_ITEMS: - err = -ENODATA; break; - case CS_UNSUPPORTED_FUNCTION: - err = -ENOSYS; break; - default: - err = -EIO; break; - } - } - - if (cmd & IOC_OUT) { - if (__copy_to_user(uarg, (char *)buf, size)) - err = -EFAULT; - } - -free_out: - kfree(buf); - return err; -} /* ds_ioctl */ - -/*====================================================================*/ - -static struct file_operations ds_fops = { - .owner = THIS_MODULE, - .open = ds_open, - .release = ds_release, - .ioctl = ds_ioctl, - .read = ds_read, - .write = ds_write, - .poll = ds_poll, -}; - -void __init pcmcia_setup_ioctl(void) { - int i; - - /* Set up character device for user mode clients */ - i = register_chrdev(0, "pcmcia", &ds_fops); - if (i < 0) - printk(KERN_NOTICE "unable to find a free device # for " - "Driver Services (error=%d)\n", i); - else - major_dev = i; - -#ifdef CONFIG_PROC_FS - proc_pccard = proc_mkdir("pccard", proc_bus); - if (proc_pccard) - create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL); -#endif -} - - -void __exit pcmcia_cleanup_ioctl(void) { -#ifdef CONFIG_PROC_FS - if (proc_pccard) { - remove_proc_entry("drivers", proc_pccard); - remove_proc_entry("pccard", proc_bus); - } -#endif - if (major_dev != -1) - unregister_chrdev(major_dev, "pcmcia"); -} diff --git a/trunk/drivers/pcmcia/pcmcia_resource.c b/trunk/drivers/pcmcia/pcmcia_resource.c deleted file mode 100644 index c01dc6bf1526..000000000000 --- a/trunk/drivers/pcmcia/pcmcia_resource.c +++ /dev/null @@ -1,998 +0,0 @@ -/* - * PCMCIA 16-bit resource management functions - * - * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds - * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - * - * Copyright (C) 1999 David A. Hinds - * Copyright (C) 2004-2005 Dominik Brodowski - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#define IN_CARD_SERVICES -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cs_internal.h" -#include "ds_internal.h" - - -/* Access speed for IO windows */ -static int io_speed = 0; -module_param(io_speed, int, 0444); - - -#ifdef CONFIG_PCMCIA_PROBE -/* mask of IRQs already reserved by other cards, we should avoid using them */ -static u8 pcmcia_used_irq[NR_IRQS]; -#endif - - -#ifdef DEBUG -extern int ds_pc_debug; -#define cs_socket_name(skt) ((skt)->dev.class_id) - -#define ds_dbg(skt, lvl, fmt, arg...) do { \ - if (ds_pc_debug >= lvl) \ - printk(KERN_DEBUG "pcmcia_resource: %s: " fmt, \ - cs_socket_name(skt) , ## arg); \ -} while (0) -#else -#define ds_dbg(lvl, fmt, arg...) do { } while (0) -#endif - - - -/** alloc_io_space - * - * Special stuff for managing IO windows, because they are scarce - */ - -static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base, - ioaddr_t num, u_int lines) -{ - int i; - kio_addr_t try, align; - - align = (*base) ? (lines ? 1<features & SS_CAP_STATIC_MAP) && s->io_offset) { - *base = s->io_offset | (*base & 0x0fff); - s->io[0].Attributes = attr; - return 0; - } - /* Check for an already-allocated window that must conflict with - * what was asked for. It is a hack because it does not catch all - * potential conflicts, just the most obvious ones. - */ - for (i = 0; i < MAX_IO_WIN; i++) - if ((s->io[i].NumPorts != 0) && - ((s->io[i].BasePort & (align-1)) == *base)) - return 1; - for (i = 0; i < MAX_IO_WIN; i++) { - if (s->io[i].NumPorts == 0) { - s->io[i].res = pcmcia_find_io_region(*base, num, align, s); - if (s->io[i].res) { - s->io[i].Attributes = attr; - s->io[i].BasePort = *base = s->io[i].res->start; - s->io[i].NumPorts = s->io[i].InUse = num; - break; - } else - return 1; - } else if (s->io[i].Attributes != attr) - continue; - /* Try to extend top of window */ - try = s->io[i].BasePort + s->io[i].NumPorts; - if ((*base == 0) || (*base == try)) - if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start, - s->io[i].res->end + num, s) == 0) { - *base = try; - s->io[i].NumPorts += num; - s->io[i].InUse += num; - break; - } - /* Try to extend bottom of window */ - try = s->io[i].BasePort - num; - if ((*base == 0) || (*base == try)) - if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num, - s->io[i].res->end, s) == 0) { - s->io[i].BasePort = *base = try; - s->io[i].NumPorts += num; - s->io[i].InUse += num; - break; - } - } - return (i == MAX_IO_WIN); -} /* alloc_io_space */ - - -static void release_io_space(struct pcmcia_socket *s, ioaddr_t base, - ioaddr_t num) -{ - int i; - - for (i = 0; i < MAX_IO_WIN; i++) { - if ((s->io[i].BasePort <= base) && - (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) { - s->io[i].InUse -= num; - /* Free the window if no one else is using it */ - if (s->io[i].InUse == 0) { - s->io[i].NumPorts = 0; - release_resource(s->io[i].res); - kfree(s->io[i].res); - s->io[i].res = NULL; - } - } - } -} /* release_io_space */ - - -/** pccard_access_configuration_register - * - * Access_configuration_register() reads and writes configuration - * registers in attribute memory. Memory window 0 is reserved for - * this and the tuple reading services. - */ - -int pccard_access_configuration_register(struct pcmcia_socket *s, - unsigned int function, - conf_reg_t *reg) -{ - config_t *c; - int addr; - u_char val; - - if (!s || !s->config) - return CS_NO_CARD; - - c = &s->config[function]; - - if (c == NULL) - return CS_NO_CARD; - - if (!(c->state & CONFIG_LOCKED)) - return CS_CONFIGURATION_LOCKED; - - addr = (c->ConfigBase + reg->Offset) >> 1; - - switch (reg->Action) { - case CS_READ: - pcmcia_read_cis_mem(s, 1, addr, 1, &val); - reg->Value = val; - break; - case CS_WRITE: - val = reg->Value; - pcmcia_write_cis_mem(s, 1, addr, 1, &val); - break; - default: - return CS_BAD_ARGS; - break; - } - return CS_SUCCESS; -} /* pccard_access_configuration_register */ - -int pcmcia_access_configuration_register(client_handle_t handle, - conf_reg_t *reg) -{ - struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); - return pccard_access_configuration_register(s, handle->Function, reg); -} -EXPORT_SYMBOL(pcmcia_access_configuration_register); - - - -int pccard_get_configuration_info(struct pcmcia_socket *s, - unsigned int function, - config_info_t *config) -{ - config_t *c; - - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - - config->Function = function; - -#ifdef CONFIG_CARDBUS - if (s->state & SOCKET_CARDBUS) { - memset(config, 0, sizeof(config_info_t)); - config->Vcc = s->socket.Vcc; - config->Vpp1 = config->Vpp2 = s->socket.Vpp; - config->Option = s->cb_dev->subordinate->number; - if (s->state & SOCKET_CARDBUS_CONFIG) { - config->Attributes = CONF_VALID_CLIENT; - config->IntType = INT_CARDBUS; - config->AssignedIRQ = s->irq.AssignedIRQ; - if (config->AssignedIRQ) - config->Attributes |= CONF_ENABLE_IRQ; - config->BasePort1 = s->io[0].BasePort; - config->NumPorts1 = s->io[0].NumPorts; - } - return CS_SUCCESS; - } -#endif - - c = (s->config != NULL) ? &s->config[function] : NULL; - - if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { - config->Attributes = 0; - config->Vcc = s->socket.Vcc; - config->Vpp1 = config->Vpp2 = s->socket.Vpp; - return CS_SUCCESS; - } - - /* !!! This is a hack !!! */ - memcpy(&config->Attributes, &c->Attributes, sizeof(config_t)); - config->Attributes |= CONF_VALID_CLIENT; - config->CardValues = c->CardValues; - config->IRQAttributes = c->irq.Attributes; - config->AssignedIRQ = s->irq.AssignedIRQ; - config->BasePort1 = c->io.BasePort1; - config->NumPorts1 = c->io.NumPorts1; - config->Attributes1 = c->io.Attributes1; - config->BasePort2 = c->io.BasePort2; - config->NumPorts2 = c->io.NumPorts2; - config->Attributes2 = c->io.Attributes2; - config->IOAddrLines = c->io.IOAddrLines; - - return CS_SUCCESS; -} /* pccard_get_configuration_info */ - -int pcmcia_get_configuration_info(client_handle_t handle, - config_info_t *config) -{ - struct pcmcia_socket *s; - - if ((CHECK_HANDLE(handle)) || !config) - return CS_BAD_HANDLE; - s = SOCKET(handle); - if (!s) - return CS_BAD_HANDLE; - return pccard_get_configuration_info(s, handle->Function, config); -} -EXPORT_SYMBOL(pcmcia_get_configuration_info); - - -/** pcmcia_get_window - */ -int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, - int idx, win_req_t *req) -{ - window_t *win; - int w; - - if (!s || !(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - for (w = idx; w < MAX_WIN; w++) - if (s->state & SOCKET_WIN_REQ(w)) - break; - if (w == MAX_WIN) - return CS_NO_MORE_ITEMS; - win = &s->win[w]; - req->Base = win->ctl.res->start; - req->Size = win->ctl.res->end - win->ctl.res->start + 1; - req->AccessSpeed = win->ctl.speed; - req->Attributes = 0; - if (win->ctl.flags & MAP_ATTRIB) - req->Attributes |= WIN_MEMORY_TYPE_AM; - if (win->ctl.flags & MAP_ACTIVE) - req->Attributes |= WIN_ENABLE; - if (win->ctl.flags & MAP_16BIT) - req->Attributes |= WIN_DATA_WIDTH_16; - if (win->ctl.flags & MAP_USE_WAIT) - req->Attributes |= WIN_USE_WAIT; - *handle = win; - return CS_SUCCESS; -} /* pcmcia_get_window */ -EXPORT_SYMBOL(pcmcia_get_window); - - -/** pccard_get_status - * - * Get the current socket state bits. We don't support the latched - * SocketState yet: I haven't seen any point for it. - */ - -int pccard_get_status(struct pcmcia_socket *s, unsigned int function, - cs_status_t *status) -{ - config_t *c; - int val; - - s->ops->get_status(s, &val); - status->CardState = status->SocketState = 0; - status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0; - status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0; - status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0; - status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0; - if (s->state & SOCKET_SUSPEND) - status->CardState |= CS_EVENT_PM_SUSPEND; - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - - c = (s->config != NULL) ? &s->config[function] : NULL; - if ((c != NULL) && (c->state & CONFIG_LOCKED) && - (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { - u_char reg; - if (c->Present & PRESENT_PIN_REPLACE) { - pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); - status->CardState |= - (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; - status->CardState |= - (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0; - status->CardState |= - (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0; - status->CardState |= - (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0; - } else { - /* No PRR? Then assume we're always ready */ - status->CardState |= CS_EVENT_READY_CHANGE; - } - if (c->Present & PRESENT_EXT_STATUS) { - pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); - status->CardState |= - (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; - } - return CS_SUCCESS; - } - status->CardState |= - (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0; - status->CardState |= - (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0; - status->CardState |= - (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0; - status->CardState |= - (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0; - return CS_SUCCESS; -} /* pccard_get_status */ - -int pcmcia_get_status(client_handle_t handle, cs_status_t *status) -{ - struct pcmcia_socket *s; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); - return pccard_get_status(s, handle->Function, status); -} -EXPORT_SYMBOL(pcmcia_get_status); - - - -/** pcmcia_get_mem_page - * - * Change the card address of an already open memory window. - */ -int pcmcia_get_mem_page(window_handle_t win, memreq_t *req) -{ - if ((win == NULL) || (win->magic != WINDOW_MAGIC)) - return CS_BAD_HANDLE; - req->Page = 0; - req->CardOffset = win->ctl.card_start; - return CS_SUCCESS; -} /* pcmcia_get_mem_page */ -EXPORT_SYMBOL(pcmcia_get_mem_page); - - -int pcmcia_map_mem_page(window_handle_t win, memreq_t *req) -{ - struct pcmcia_socket *s; - if ((win == NULL) || (win->magic != WINDOW_MAGIC)) - return CS_BAD_HANDLE; - if (req->Page != 0) - return CS_BAD_PAGE; - s = win->sock; - win->ctl.card_start = req->CardOffset; - if (s->ops->set_mem_map(s, &win->ctl) != 0) - return CS_BAD_OFFSET; - return CS_SUCCESS; -} /* pcmcia_map_mem_page */ -EXPORT_SYMBOL(pcmcia_map_mem_page); - - -/** pcmcia_modify_configuration - * - * Modify a locked socket configuration - */ -int pcmcia_modify_configuration(client_handle_t handle, - modconf_t *mod) -{ - struct pcmcia_socket *s; - config_t *c; - - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); - c = CONFIG(handle); - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - if (!(c->state & CONFIG_LOCKED)) - return CS_CONFIGURATION_LOCKED; - - if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { - if (mod->Attributes & CONF_ENABLE_IRQ) { - c->Attributes |= CONF_ENABLE_IRQ; - s->socket.io_irq = s->irq.AssignedIRQ; - } else { - c->Attributes &= ~CONF_ENABLE_IRQ; - s->socket.io_irq = 0; - } - s->ops->set_socket(s, &s->socket); - } - - if (mod->Attributes & CONF_VCC_CHANGE_VALID) - return CS_BAD_VCC; - - /* We only allow changing Vpp1 and Vpp2 to the same value */ - if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && - (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { - if (mod->Vpp1 != mod->Vpp2) - return CS_BAD_VPP; - c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1; - if (s->ops->set_socket(s, &s->socket)) - return CS_BAD_VPP; - } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || - (mod->Attributes & CONF_VPP2_CHANGE_VALID)) - return CS_BAD_VPP; - - return CS_SUCCESS; -} /* modify_configuration */ -EXPORT_SYMBOL(pcmcia_modify_configuration); - - -int pcmcia_release_configuration(client_handle_t handle) -{ - pccard_io_map io = { 0, 0, 0, 0, 1 }; - struct pcmcia_socket *s; - int i; - - if (CHECK_HANDLE(handle) || - !(handle->state & CLIENT_CONFIG_LOCKED)) - return CS_BAD_HANDLE; - handle->state &= ~CLIENT_CONFIG_LOCKED; - s = SOCKET(handle); - -#ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) - return CS_SUCCESS; -#endif - - if (!(handle->state & CLIENT_STALE)) { - config_t *c = CONFIG(handle); - if (--(s->lock_count) == 0) { - s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ - s->socket.Vpp = 0; - s->socket.io_irq = 0; - s->ops->set_socket(s, &s->socket); - } - if (c->state & CONFIG_IO_REQ) - for (i = 0; i < MAX_IO_WIN; i++) { - if (s->io[i].NumPorts == 0) - continue; - s->io[i].Config--; - if (s->io[i].Config != 0) - continue; - io.map = i; - s->ops->set_io_map(s, &io); - } - c->state &= ~CONFIG_LOCKED; - } - - return CS_SUCCESS; -} /* pcmcia_release_configuration */ -EXPORT_SYMBOL(pcmcia_release_configuration); - - -/** pcmcia_release_io - * - * Release_io() releases the I/O ranges allocated by a client. This - * may be invoked some time after a card ejection has already dumped - * the actual socket configuration, so if the client is "stale", we - * don't bother checking the port ranges against the current socket - * values. - */ -int pcmcia_release_io(client_handle_t handle, io_req_t *req) -{ - struct pcmcia_socket *s; - - if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ)) - return CS_BAD_HANDLE; - handle->state &= ~CLIENT_IO_REQ; - s = SOCKET(handle); - -#ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) - return CS_SUCCESS; -#endif - - if (!(handle->state & CLIENT_STALE)) { - config_t *c = CONFIG(handle); - if (c->state & CONFIG_LOCKED) - return CS_CONFIGURATION_LOCKED; - if ((c->io.BasePort1 != req->BasePort1) || - (c->io.NumPorts1 != req->NumPorts1) || - (c->io.BasePort2 != req->BasePort2) || - (c->io.NumPorts2 != req->NumPorts2)) - return CS_BAD_ARGS; - c->state &= ~CONFIG_IO_REQ; - } - - release_io_space(s, req->BasePort1, req->NumPorts1); - if (req->NumPorts2) - release_io_space(s, req->BasePort2, req->NumPorts2); - - return CS_SUCCESS; -} /* pcmcia_release_io */ -EXPORT_SYMBOL(pcmcia_release_io); - - -int pcmcia_release_irq(client_handle_t handle, irq_req_t *req) -{ - struct pcmcia_socket *s; - if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ)) - return CS_BAD_HANDLE; - handle->state &= ~CLIENT_IRQ_REQ; - s = SOCKET(handle); - - if (!(handle->state & CLIENT_STALE)) { - config_t *c = CONFIG(handle); - if (c->state & CONFIG_LOCKED) - return CS_CONFIGURATION_LOCKED; - if (c->irq.Attributes != req->Attributes) - return CS_BAD_ATTRIBUTE; - if (s->irq.AssignedIRQ != req->AssignedIRQ) - return CS_BAD_IRQ; - if (--s->irq.Config == 0) { - c->state &= ~CONFIG_IRQ_REQ; - s->irq.AssignedIRQ = 0; - } - } - - if (req->Attributes & IRQ_HANDLE_PRESENT) { - free_irq(req->AssignedIRQ, req->Instance); - } - -#ifdef CONFIG_PCMCIA_PROBE - pcmcia_used_irq[req->AssignedIRQ]--; -#endif - - return CS_SUCCESS; -} /* pcmcia_release_irq */ -EXPORT_SYMBOL(pcmcia_release_irq); - - -int pcmcia_release_window(window_handle_t win) -{ - struct pcmcia_socket *s; - - if ((win == NULL) || (win->magic != WINDOW_MAGIC)) - return CS_BAD_HANDLE; - s = win->sock; - if (!(win->handle->state & CLIENT_WIN_REQ(win->index))) - return CS_BAD_HANDLE; - - /* Shut down memory window */ - win->ctl.flags &= ~MAP_ACTIVE; - s->ops->set_mem_map(s, &win->ctl); - s->state &= ~SOCKET_WIN_REQ(win->index); - - /* Release system memory */ - if (win->ctl.res) { - release_resource(win->ctl.res); - kfree(win->ctl.res); - win->ctl.res = NULL; - } - win->handle->state &= ~CLIENT_WIN_REQ(win->index); - - win->magic = 0; - - return CS_SUCCESS; -} /* pcmcia_release_window */ -EXPORT_SYMBOL(pcmcia_release_window); - - -int pcmcia_request_configuration(client_handle_t handle, - config_req_t *req) -{ - int i; - u_int base; - struct pcmcia_socket *s; - config_t *c; - pccard_io_map iomap; - - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - -#ifdef CONFIG_CARDBUS - if (handle->state & CLIENT_CARDBUS) - return CS_UNSUPPORTED_MODE; -#endif - - if (req->IntType & INT_CARDBUS) - return CS_UNSUPPORTED_MODE; - c = CONFIG(handle); - if (c->state & CONFIG_LOCKED) - return CS_CONFIGURATION_LOCKED; - - /* Do power control. We don't allow changes in Vcc. */ - if (s->socket.Vcc != req->Vcc) - return CS_BAD_VCC; - if (req->Vpp1 != req->Vpp2) - return CS_BAD_VPP; - s->socket.Vpp = req->Vpp1; - if (s->ops->set_socket(s, &s->socket)) - return CS_BAD_VPP; - - c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1; - - /* Pick memory or I/O card, DMA mode, interrupt */ - c->IntType = req->IntType; - c->Attributes = req->Attributes; - if (req->IntType & INT_MEMORY_AND_IO) - s->socket.flags |= SS_IOCARD; - if (req->IntType & INT_ZOOMED_VIDEO) - s->socket.flags |= SS_ZVCARD | SS_IOCARD; - if (req->Attributes & CONF_ENABLE_DMA) - s->socket.flags |= SS_DMA_MODE; - if (req->Attributes & CONF_ENABLE_SPKR) - s->socket.flags |= SS_SPKR_ENA; - if (req->Attributes & CONF_ENABLE_IRQ) - s->socket.io_irq = s->irq.AssignedIRQ; - else - s->socket.io_irq = 0; - s->ops->set_socket(s, &s->socket); - s->lock_count++; - - /* Set up CIS configuration registers */ - base = c->ConfigBase = req->ConfigBase; - c->Present = c->CardValues = req->Present; - if (req->Present & PRESENT_COPY) { - c->Copy = req->Copy; - pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); - } - if (req->Present & PRESENT_OPTION) { - if (s->functions == 1) { - c->Option = req->ConfigIndex & COR_CONFIG_MASK; - } else { - c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK; - c->Option |= COR_FUNC_ENA|COR_IREQ_ENA; - if (req->Present & PRESENT_IOBASE_0) - c->Option |= COR_ADDR_DECODE; - } - if (c->state & CONFIG_IRQ_REQ) - if (!(c->irq.Attributes & IRQ_FORCED_PULSE)) - c->Option |= COR_LEVEL_REQ; - pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); - mdelay(40); - } - if (req->Present & PRESENT_STATUS) { - c->Status = req->Status; - pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status); - } - if (req->Present & PRESENT_PIN_REPLACE) { - c->Pin = req->Pin; - pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin); - } - if (req->Present & PRESENT_EXT_STATUS) { - c->ExtStatus = req->ExtStatus; - pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus); - } - if (req->Present & PRESENT_IOBASE_0) { - u_char b = c->io.BasePort1 & 0xff; - pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b); - b = (c->io.BasePort1 >> 8) & 0xff; - pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b); - } - if (req->Present & PRESENT_IOSIZE) { - u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1; - pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b); - } - - /* Configure I/O windows */ - if (c->state & CONFIG_IO_REQ) { - iomap.speed = io_speed; - for (i = 0; i < MAX_IO_WIN; i++) - if (s->io[i].NumPorts != 0) { - iomap.map = i; - iomap.flags = MAP_ACTIVE; - switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) { - case IO_DATA_PATH_WIDTH_16: - iomap.flags |= MAP_16BIT; break; - case IO_DATA_PATH_WIDTH_AUTO: - iomap.flags |= MAP_AUTOSZ; break; - default: - break; - } - iomap.start = s->io[i].BasePort; - iomap.stop = iomap.start + s->io[i].NumPorts - 1; - s->ops->set_io_map(s, &iomap); - s->io[i].Config++; - } - } - - c->state |= CONFIG_LOCKED; - handle->state |= CLIENT_CONFIG_LOCKED; - return CS_SUCCESS; -} /* pcmcia_request_configuration */ -EXPORT_SYMBOL(pcmcia_request_configuration); - - -/** pcmcia_request_io - * - * Request_io() reserves ranges of port addresses for a socket. - * I have not implemented range sharing or alias addressing. - */ -int pcmcia_request_io(client_handle_t handle, io_req_t *req) -{ - struct pcmcia_socket *s; - config_t *c; - - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - - if (handle->state & CLIENT_CARDBUS) { -#ifdef CONFIG_CARDBUS - handle->state |= CLIENT_IO_REQ; - return CS_SUCCESS; -#else - return CS_UNSUPPORTED_FUNCTION; -#endif - } - - if (!req) - return CS_UNSUPPORTED_MODE; - c = CONFIG(handle); - if (c->state & CONFIG_LOCKED) - return CS_CONFIGURATION_LOCKED; - if (c->state & CONFIG_IO_REQ) - return CS_IN_USE; - if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) - return CS_BAD_ATTRIBUTE; - if ((req->NumPorts2 > 0) && - (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) - return CS_BAD_ATTRIBUTE; - - if (alloc_io_space(s, req->Attributes1, &req->BasePort1, - req->NumPorts1, req->IOAddrLines)) - return CS_IN_USE; - - if (req->NumPorts2) { - if (alloc_io_space(s, req->Attributes2, &req->BasePort2, - req->NumPorts2, req->IOAddrLines)) { - release_io_space(s, req->BasePort1, req->NumPorts1); - return CS_IN_USE; - } - } - - c->io = *req; - c->state |= CONFIG_IO_REQ; - handle->state |= CLIENT_IO_REQ; - return CS_SUCCESS; -} /* pcmcia_request_io */ -EXPORT_SYMBOL(pcmcia_request_io); - - -/** pcmcia_request_irq - * - * Request_irq() reserves an irq for this client. - * - * Also, since Linux only reserves irq's when they are actually - * hooked, we don't guarantee that an irq will still be available - * when the configuration is locked. Now that I think about it, - * there might be a way to fix this using a dummy handler. - */ - -#ifdef CONFIG_PCMCIA_PROBE -static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs) -{ - return IRQ_NONE; -} -#endif - -int pcmcia_request_irq(client_handle_t handle, irq_req_t *req) -{ - struct pcmcia_socket *s; - config_t *c; - int ret = CS_IN_USE, irq = 0; - struct pcmcia_device *p_dev = handle_to_pdev(handle); - - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - s = SOCKET(handle); - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - c = CONFIG(handle); - if (c->state & CONFIG_LOCKED) - return CS_CONFIGURATION_LOCKED; - if (c->state & CONFIG_IRQ_REQ) - return CS_IN_USE; - -#ifdef CONFIG_PCMCIA_PROBE - if (s->irq.AssignedIRQ != 0) { - /* If the interrupt is already assigned, it must be the same */ - irq = s->irq.AssignedIRQ; - } else { - int try; - u32 mask = s->irq_mask; - void *data = NULL; - - for (try = 0; try < 64; try++) { - irq = try % 32; - - /* marked as available by driver, and not blocked by userspace? */ - if (!((mask >> irq) & 1)) - continue; - - /* avoid an IRQ which is already used by a PCMCIA card */ - if ((try < 32) && pcmcia_used_irq[irq]) - continue; - - /* register the correct driver, if possible, of check whether - * registering a dummy handle works, i.e. if the IRQ isn't - * marked as used by the kernel resource management core */ - ret = request_irq(irq, - (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action, - ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || - (s->functions > 1) || - (irq == s->pci_irq)) ? SA_SHIRQ : 0, - p_dev->dev.bus_id, - (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data); - if (!ret) { - if (!(req->Attributes & IRQ_HANDLE_PRESENT)) - free_irq(irq, data); - break; - } - } - } -#endif - if (ret) { - if (!s->pci_irq) - return ret; - irq = s->pci_irq; - } - - if (ret && req->Attributes & IRQ_HANDLE_PRESENT) { - if (request_irq(irq, req->Handler, - ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || - (s->functions > 1) || - (irq == s->pci_irq)) ? SA_SHIRQ : 0, - p_dev->dev.bus_id, req->Instance)) - return CS_IN_USE; - } - - c->irq.Attributes = req->Attributes; - s->irq.AssignedIRQ = req->AssignedIRQ = irq; - s->irq.Config++; - - c->state |= CONFIG_IRQ_REQ; - handle->state |= CLIENT_IRQ_REQ; - -#ifdef CONFIG_PCMCIA_PROBE - pcmcia_used_irq[irq]++; -#endif - - return CS_SUCCESS; -} /* pcmcia_request_irq */ -EXPORT_SYMBOL(pcmcia_request_irq); - - -/** pcmcia_request_window - * - * Request_window() establishes a mapping between card memory space - * and system memory space. - */ -int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh) -{ - struct pcmcia_socket *s; - window_t *win; - u_long align; - int w; - - if (CHECK_HANDLE(*handle)) - return CS_BAD_HANDLE; - s = (*handle)->Socket; - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - if (req->Attributes & (WIN_PAGED | WIN_SHARED)) - return CS_BAD_ATTRIBUTE; - - /* Window size defaults to smallest available */ - if (req->Size == 0) - req->Size = s->map_size; - align = (((s->features & SS_CAP_MEM_ALIGN) || - (req->Attributes & WIN_STRICT_ALIGN)) ? - req->Size : s->map_size); - if (req->Size & (s->map_size-1)) - return CS_BAD_SIZE; - if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || - (req->Base & (align-1))) - return CS_BAD_BASE; - if (req->Base) - align = 0; - - /* Allocate system memory window */ - for (w = 0; w < MAX_WIN; w++) - if (!(s->state & SOCKET_WIN_REQ(w))) break; - if (w == MAX_WIN) - return CS_OUT_OF_RESOURCE; - - win = &s->win[w]; - win->magic = WINDOW_MAGIC; - win->index = w; - win->handle = *handle; - win->sock = s; - - if (!(s->features & SS_CAP_STATIC_MAP)) { - win->ctl.res = pcmcia_find_mem_region(req->Base, req->Size, align, - (req->Attributes & WIN_MAP_BELOW_1MB), s); - if (!win->ctl.res) - return CS_IN_USE; - } - (*handle)->state |= CLIENT_WIN_REQ(w); - - /* Configure the socket controller */ - win->ctl.map = w+1; - win->ctl.flags = 0; - win->ctl.speed = req->AccessSpeed; - if (req->Attributes & WIN_MEMORY_TYPE) - win->ctl.flags |= MAP_ATTRIB; - if (req->Attributes & WIN_ENABLE) - win->ctl.flags |= MAP_ACTIVE; - if (req->Attributes & WIN_DATA_WIDTH_16) - win->ctl.flags |= MAP_16BIT; - if (req->Attributes & WIN_USE_WAIT) - win->ctl.flags |= MAP_USE_WAIT; - win->ctl.card_start = 0; - if (s->ops->set_mem_map(s, &win->ctl) != 0) - return CS_BAD_ARGS; - s->state |= SOCKET_WIN_REQ(w); - - /* Return window handle */ - if (s->features & SS_CAP_STATIC_MAP) { - req->Base = win->ctl.static_start; - } else { - req->Base = win->ctl.res->start; - } - *wh = win; - - return CS_SUCCESS; -} /* pcmcia_request_window */ -EXPORT_SYMBOL(pcmcia_request_window); diff --git a/trunk/drivers/pcmcia/rsrc_mgr.c b/trunk/drivers/pcmcia/rsrc_mgr.c index 0668384ebc8b..b6843f8d300d 100644 --- a/trunk/drivers/pcmcia/rsrc_mgr.c +++ b/trunk/drivers/pcmcia/rsrc_mgr.c @@ -72,7 +72,7 @@ int pcmcia_adjust_resource_info(adjust_t *adj) /* you can't use the old interface if the new * one was used before */ spin_lock_irqsave(&s->lock, flags); - if ((s->resource_setup_new) && + if ((s->resource_setup_done) && !(s->resource_setup_old)) { spin_unlock_irqrestore(&s->lock, flags); continue; @@ -105,32 +105,29 @@ void pcmcia_validate_mem(struct pcmcia_socket *s) } EXPORT_SYMBOL(pcmcia_validate_mem); -int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start, +int adjust_io_region(struct resource *res, unsigned long r_start, unsigned long r_end, struct pcmcia_socket *s) { if (s->resource_ops->adjust_io_region) return s->resource_ops->adjust_io_region(res, r_start, r_end, s); return -ENOMEM; } -EXPORT_SYMBOL(pcmcia_adjust_io_region); -struct resource *pcmcia_find_io_region(unsigned long base, int num, +struct resource *find_io_region(unsigned long base, int num, unsigned long align, struct pcmcia_socket *s) { if (s->resource_ops->find_io) return s->resource_ops->find_io(base, num, align, s); return NULL; } -EXPORT_SYMBOL(pcmcia_find_io_region); -struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, +struct resource *find_mem_region(u_long base, u_long num, u_long align, int low, struct pcmcia_socket *s) { if (s->resource_ops->find_mem) return s->resource_ops->find_mem(base, num, align, low, s); return NULL; } -EXPORT_SYMBOL(pcmcia_find_mem_region); void release_resource_db(struct pcmcia_socket *s) { diff --git a/trunk/drivers/pcmcia/rsrc_nonstatic.c b/trunk/drivers/pcmcia/rsrc_nonstatic.c index c42455d20eb6..5876bab7c14c 100644 --- a/trunk/drivers/pcmcia/rsrc_nonstatic.c +++ b/trunk/drivers/pcmcia/rsrc_nonstatic.c @@ -372,9 +372,6 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) base, base+num-1); bad = fail = 0; step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff); - /* don't allow too large steps */ - if (step > 0x800000) - step = 0x800000; /* cis_readable wants to map 2x map_size */ if (step < 2 * s->map_size) step = 2 * s->map_size; @@ -468,7 +465,8 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { mm = *m; - do_mem_probe(mm.base, mm.num, s); + if (do_mem_probe(mm.base, mm.num, s)) + break; } } @@ -603,7 +601,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star ======================================================================*/ -static struct resource *nonstatic_find_io_region(unsigned long base, int num, +struct resource *nonstatic_find_io_region(unsigned long base, int num, unsigned long align, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id); @@ -637,8 +635,8 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, return res; } -static struct resource * nonstatic_find_mem_region(u_long base, u_long num, - u_long align, int low, struct pcmcia_socket *s) +struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long align, + int low, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id); struct socket_data *s_data = s->resource_data; @@ -685,23 +683,27 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num, } -static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end) +static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj) { + u_long base, num; struct socket_data *data = s->resource_data; - unsigned long size = end - start + 1; - int ret = 0; + int ret; - if (end <= start) - return -EINVAL; + base = adj->resource.memory.Base; + num = adj->resource.memory.Size; + if ((num == 0) || (base+num-1 < base)) + return CS_BAD_SIZE; + + ret = CS_SUCCESS; down(&rsrc_sem); - switch (action) { + switch (adj->Action) { case ADD_MANAGED_RESOURCE: - ret = add_interval(&data->mem_db, start, size); + ret = add_interval(&data->mem_db, base, num); break; case REMOVE_MANAGED_RESOURCE: - ret = sub_interval(&data->mem_db, start, size); - if (!ret) { + ret = sub_interval(&data->mem_db, base, num); + if (ret == CS_SUCCESS) { struct pcmcia_socket *socket; down_read(&pcmcia_socket_list_rwsem); list_for_each_entry(socket, &pcmcia_socket_list, socket_list) @@ -710,7 +712,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned } break; default: - ret = -EINVAL; + ret = CS_UNSUPPORTED_FUNCTION; } up(&rsrc_sem); @@ -718,35 +720,36 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned } -static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end) +static int adjust_io(struct pcmcia_socket *s, adjust_t *adj) { struct socket_data *data = s->resource_data; - unsigned long size = end - start + 1; - int ret = 0; + kio_addr_t base, num; + int ret = CS_SUCCESS; - if (end <= start) - return -EINVAL; - - if (end > IO_SPACE_LIMIT) - return -EINVAL; + base = adj->resource.io.BasePort; + num = adj->resource.io.NumPorts; + if ((base < 0) || (base > 0xffff)) + return CS_BAD_BASE; + if ((num <= 0) || (base+num > 0x10000) || (base+num <= base)) + return CS_BAD_SIZE; down(&rsrc_sem); - switch (action) { + switch (adj->Action) { case ADD_MANAGED_RESOURCE: - if (add_interval(&data->io_db, start, size) != 0) { - ret = -EBUSY; + if (add_interval(&data->io_db, base, num) != 0) { + ret = CS_IN_USE; break; } #ifdef CONFIG_PCMCIA_PROBE if (probe_io) - do_io_probe(s, start, size); + do_io_probe(s, base, num); #endif break; case REMOVE_MANAGED_RESOURCE: - sub_interval(&data->io_db, start, size); + sub_interval(&data->io_db, base, num); break; default: - ret = -EINVAL; + ret = CS_UNSUPPORTED_FUNCTION; break; } up(&rsrc_sem); @@ -757,82 +760,15 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj) { - unsigned long end; - switch (adj->Resource) { case RES_MEMORY_RANGE: - end = adj->resource.memory.Base + adj->resource.memory.Size - 1; - return adjust_memory(s, adj->Action, adj->resource.memory.Base, end); + return adjust_memory(s, adj); case RES_IO_RANGE: - end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1; - return adjust_io(s, adj->Action, adj->resource.io.BasePort, end); + return adjust_io(s, adj); } return CS_UNSUPPORTED_FUNCTION; } -#ifdef CONFIG_PCI -static int nonstatic_autoadd_resources(struct pcmcia_socket *s) -{ - struct resource *res; - int i, done = 0; - - if (!s->cb_dev || !s->cb_dev->bus) - return -ENODEV; - -#if defined(CONFIG_X86) || defined(CONFIG_X86_64) - /* If this is the root bus, the risk of hitting - * some strange system devices which aren't protected - * by either ACPI resource tables or properly requested - * resources is too big. Therefore, don't do auto-adding - * of resources at the moment. - */ - if (s->cb_dev->bus->number == 0) - return -EINVAL; -#endif - - for (i=0; i < PCI_BUS_NUM_RESOURCES; i++) { - res = s->cb_dev->bus->resource[i]; - if (!res) - continue; - - if (res->flags & IORESOURCE_IO) { - if (res == &ioport_resource) - continue; - printk(KERN_INFO "pcmcia: parent PCI bridge I/O window: 0x%lx - 0x%lx\n", - res->start, res->end); - if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end)) - done |= IORESOURCE_IO; - - } - - if (res->flags & IORESOURCE_MEM) { - if (res == &iomem_resource) - continue; - printk(KERN_INFO "pcmcia: parent PCI bridge Memory window: 0x%lx - 0x%lx\n", - res->start, res->end); - if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end)) - done |= IORESOURCE_MEM; - } - } - - /* if we got at least one of IO, and one of MEM, we can be glad and - * activate the PCMCIA subsystem */ - if (done & (IORESOURCE_MEM | IORESOURCE_IO)) - s->resource_setup_done = 1; - - return 0; -} - -#else - -static inline int nonstatic_autoadd_resources(struct pcmcia_socket *s) -{ - return -ENODEV; -} - -#endif - - static int nonstatic_init(struct pcmcia_socket *s) { struct socket_data *data; @@ -847,8 +783,6 @@ static int nonstatic_init(struct pcmcia_socket *s) s->resource_data = (void *) data; - nonstatic_autoadd_resources(s); - return 0; } @@ -911,16 +845,17 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size { struct pcmcia_socket *s = class_get_devdata(class_dev); unsigned long start_addr, end_addr; - unsigned int add = ADD_MANAGED_RESOURCE; + unsigned int add = 1; + adjust_t adj; ssize_t ret = 0; ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); if (ret != 2) { ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); - add = REMOVE_MANAGED_RESOURCE; + add = 0; if (ret != 2) { ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); - add = ADD_MANAGED_RESOURCE; + add = 1; if (ret != 2) return -EINVAL; } @@ -928,9 +863,12 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size if (end_addr <= start_addr) return -EINVAL; - ret = adjust_io(s, add, start_addr, end_addr); - if (!ret) - s->resource_setup_new = 1; + adj.Action = add ? ADD_MANAGED_RESOURCE : REMOVE_MANAGED_RESOURCE; + adj.Resource = RES_IO_RANGE; + adj.resource.io.BasePort = start_addr; + adj.resource.io.NumPorts = end_addr - start_addr + 1; + + ret = adjust_io(s, &adj); return ret ? ret : count; } @@ -963,16 +901,17 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz { struct pcmcia_socket *s = class_get_devdata(class_dev); unsigned long start_addr, end_addr; - unsigned int add = ADD_MANAGED_RESOURCE; + unsigned int add = 1; + adjust_t adj; ssize_t ret = 0; ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); if (ret != 2) { ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); - add = REMOVE_MANAGED_RESOURCE; + add = 0; if (ret != 2) { ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); - add = ADD_MANAGED_RESOURCE; + add = 1; if (ret != 2) return -EINVAL; } @@ -980,9 +919,12 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz if (end_addr <= start_addr) return -EINVAL; - ret = adjust_memory(s, add, start_addr, end_addr); - if (!ret) - s->resource_setup_new = 1; + adj.Action = add ? ADD_MANAGED_RESOURCE : REMOVE_MANAGED_RESOURCE; + adj.Resource = RES_MEMORY_RANGE; + adj.resource.memory.Base = start_addr; + adj.resource.memory.Size = end_addr - start_addr + 1; + + ret = adjust_memory(s, &adj); return ret ? ret : count; } diff --git a/trunk/drivers/pcmcia/socket_sysfs.c b/trunk/drivers/pcmcia/socket_sysfs.c index fcef54c1c2da..8eed03938214 100644 --- a/trunk/drivers/pcmcia/socket_sysfs.c +++ b/trunk/drivers/pcmcia/socket_sysfs.c @@ -163,164 +163,28 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, return -EINVAL; spin_lock_irqsave(&s->lock, flags); - if (!s->resource_setup_done) + if (!s->resource_setup_done) { s->resource_setup_done = 1; - spin_unlock_irqrestore(&s->lock, flags); - - down(&s->skt_sem); - if ((s->callback) && - (s->state & SOCKET_PRESENT) && - !(s->state & SOCKET_CARDBUS)) { - if (try_module_get(s->callback->owner)) { - s->callback->requery(s); - module_put(s->callback->owner); - } - } - up(&s->skt_sem); - - return count; -} -static CLASS_DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource); - - -static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off, size_t count) -{ - tuple_t tuple; - int status, i; - loff_t pointer = 0; - ssize_t ret = 0; - u_char *tuplebuffer; - u_char *tempbuffer; - - tuplebuffer = kmalloc(sizeof(u_char) * 256, GFP_KERNEL); - if (!tuplebuffer) - return -ENOMEM; - - tempbuffer = kmalloc(sizeof(u_char) * 258, GFP_KERNEL); - if (!tempbuffer) { - ret = -ENOMEM; - goto free_tuple; - } - - memset(&tuple, 0, sizeof(tuple_t)); - - tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON; - tuple.DesiredTuple = RETURN_FIRST_TUPLE; - tuple.TupleOffset = 0; - - status = pccard_get_first_tuple(s, BIND_FN_ALL, &tuple); - while (!status) { - tuple.TupleData = tuplebuffer; - tuple.TupleDataMax = 255; - memset(tuplebuffer, 0, sizeof(u_char) * 255); + spin_unlock_irqrestore(&s->lock, flags); - status = pccard_get_tuple_data(s, &tuple); - if (status) - break; - - if (off < (pointer + 2 + tuple.TupleDataLen)) { - tempbuffer[0] = tuple.TupleCode & 0xff; - tempbuffer[1] = tuple.TupleLink & 0xff; - for (i = 0; i < tuple.TupleDataLen; i++) - tempbuffer[i + 2] = tuplebuffer[i] & 0xff; - - for (i = 0; i < (2 + tuple.TupleDataLen); i++) { - if (((i + pointer) >= off) && - (i + pointer) < (off + count)) { - buf[ret] = tempbuffer[i]; - ret++; - } - } - } - - pointer += 2 + tuple.TupleDataLen; - - if (pointer >= (off + count)) - break; - - if (tuple.TupleCode == CISTPL_END) - break; - status = pccard_get_next_tuple(s, BIND_FN_ALL, &tuple); - } - - kfree(tempbuffer); - free_tuple: - kfree(tuplebuffer); - - return (ret); -} - -static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) -{ - unsigned int size = 0x200; - - if (off >= size) - count = 0; - else { - struct pcmcia_socket *s; - cisinfo_t cisinfo; - - if (off + count > size) - count = size - off; - - s = to_socket(container_of(kobj, struct class_device, kobj)); - - if (!(s->state & SOCKET_PRESENT)) - return -ENODEV; - if (pccard_validate_cis(s, BIND_FN_ALL, &cisinfo)) - return -EIO; - if (!cisinfo.Chains) - return -ENODATA; - - count = pccard_extract_cis(s, buf, off, count); - } - - return (count); -} - -static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) -{ - struct pcmcia_socket *s = to_socket(container_of(kobj, struct class_device, kobj)); - cisdump_t *cis; - ssize_t ret = count; - - if (off) - return -EINVAL; - - if (count >= 0x200) - return -EINVAL; - - if (!(s->state & SOCKET_PRESENT)) - return -ENODEV; - - cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL); - if (!cis) - return -ENOMEM; - memset(cis, 0, sizeof(cisdump_t)); - - cis->Length = count + 1; - memcpy(cis->Data, buf, count); - - if (pcmcia_replace_cis(s, cis)) - ret = -EIO; - - kfree(cis); - - if (!ret) { down(&s->skt_sem); - if ((s->callback) && (s->state & SOCKET_PRESENT) && + if ((s->callback) && + (s->state & SOCKET_PRESENT) && !(s->state & SOCKET_CARDBUS)) { if (try_module_get(s->callback->owner)) { - s->callback->requery(s); + s->callback->resources_done(s); module_put(s->callback->owner); } } up(&s->skt_sem); - } + return count; + } + spin_unlock_irqrestore(&s->lock, flags); - return (ret); + return count; } +static CLASS_DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource); static struct class_device_attribute *pccard_socket_attributes[] = { @@ -335,13 +199,6 @@ static struct class_device_attribute *pccard_socket_attributes[] = { NULL, }; -static struct bin_attribute pccard_cis_attr = { - .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE}, - .size = 0x200, - .read = pccard_show_cis, - .write = pccard_store_cis, -}; - static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev) { struct class_device_attribute **attr; @@ -352,8 +209,6 @@ static int __devinit pccard_sysfs_add_socket(struct class_device *class_dev) if (ret) break; } - if (!ret) - ret = sysfs_create_bin_file(&class_dev->kobj, &pccard_cis_attr); return ret; } @@ -362,7 +217,6 @@ static void __devexit pccard_sysfs_remove_socket(struct class_device *class_dev) { struct class_device_attribute **attr; - sysfs_remove_bin_file(&class_dev->kobj, &pccard_cis_attr); for (attr = pccard_socket_attributes; *attr; attr++) class_device_remove_file(class_dev, *attr); } diff --git a/trunk/drivers/pcmcia/yenta_socket.c b/trunk/drivers/pcmcia/yenta_socket.c index 02b23abc2df1..bee05362fd24 100644 --- a/trunk/drivers/pcmcia/yenta_socket.c +++ b/trunk/drivers/pcmcia/yenta_socket.c @@ -549,11 +549,6 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ unsigned offset; unsigned mask; - res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; - /* Already allocated? */ - if (res->parent) - return 0; - /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ mask = ~0xfff; if (type & IORESOURCE_IO) @@ -561,6 +556,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ offset = 0x1c + 8*nr; bus = socket->dev->subordinate; + res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr; res->name = bus->name; res->flags = type; res->start = 0; diff --git a/trunk/drivers/scsi/pcmcia/aha152x_stub.c b/trunk/drivers/scsi/pcmcia/aha152x_stub.c index f1f6bf596dc9..e60b4c0a8427 100644 --- a/trunk/drivers/scsi/pcmcia/aha152x_stub.c +++ b/trunk/drivers/scsi/pcmcia/aha152x_stub.c @@ -318,16 +318,6 @@ static int aha152x_event(event_t event, int priority, return 0; } -static struct pcmcia_device_id aha152x_ids[] = { - PCMCIA_DEVICE_PROD_ID123("New Media", "SCSI", "Bus Toaster", 0xcdf7e4cc, 0x35f26476, 0xa8851d6e), - PCMCIA_DEVICE_PROD_ID123("NOTEWORTHY", "SCSI", "Bus Toaster", 0xad89c6e8, 0x35f26476, 0xa8851d6e), - PCMCIA_DEVICE_PROD_ID12("Adaptec, Inc.", "APA-1460 SCSI Host Adapter", 0x24ba9738, 0x3a3c3d20), - PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Multimedia Sound/SCSI", 0x085a850b, 0x80a6535c), - PCMCIA_DEVICE_PROD_ID12("NOTEWORTHY", "NWCOMB02 SCSI/AUDIO COMBO CARD", 0xad89c6e8, 0x5f9a615b), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, aha152x_ids); - static struct pcmcia_driver aha152x_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -335,7 +325,6 @@ static struct pcmcia_driver aha152x_cs_driver = { }, .attach = aha152x_attach, .detach = aha152x_detach, - .id_table = aha152x_ids, }; static int __init init_aha152x_cs(void) diff --git a/trunk/drivers/scsi/pcmcia/fdomain_stub.c b/trunk/drivers/scsi/pcmcia/fdomain_stub.c index 853e6ee9b71a..3df7bc72e354 100644 --- a/trunk/drivers/scsi/pcmcia/fdomain_stub.c +++ b/trunk/drivers/scsi/pcmcia/fdomain_stub.c @@ -299,15 +299,6 @@ static int fdomain_event(event_t event, int priority, return 0; } /* fdomain_event */ - -static struct pcmcia_device_id fdomain_ids[] = { - PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "SCSI PCMCIA Card", 0xe3736c88, 0x859cad20), - PCMCIA_DEVICE_PROD_ID1("SCSI PCMCIA Adapter Card", 0x8dacb57e), - PCMCIA_DEVICE_PROD_ID12(" SIMPLE TECHNOLOGY Corporation", "SCSI PCMCIA Credit Card Controller", 0x182bdafe, 0xc80d106f), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, fdomain_ids); - static struct pcmcia_driver fdomain_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -315,7 +306,6 @@ static struct pcmcia_driver fdomain_cs_driver = { }, .attach = fdomain_attach, .detach = fdomain_detach, - .id_table = fdomain_ids, }; static int __init init_fdomain_cs(void) diff --git a/trunk/drivers/scsi/pcmcia/nsp_cs.c b/trunk/drivers/scsi/pcmcia/nsp_cs.c index 91b3f28e7a19..3dddb323e718 100644 --- a/trunk/drivers/scsi/pcmcia/nsp_cs.c +++ b/trunk/drivers/scsi/pcmcia/nsp_cs.c @@ -2125,18 +2125,6 @@ static int nsp_cs_event(event_t event, * module entry point *====================================================================*/ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) -static struct pcmcia_device_id nsp_cs_ids[] = { - PCMCIA_DEVICE_PROD_ID123("IO DATA", "CBSC16 ", "1", 0x547e66dc, 0x0d63a3fd, 0x51de003a), - PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-001", "1", 0x534c02bc, 0x52008408, 0x51de003a), - PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-002", "1", 0x534c02bc, 0xcb09d5b2, 0x51de003a), - PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-003", "1", 0x534c02bc, 0xbc0ee524, 0x51de003a), - PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-004", "1", 0x534c02bc, 0x226a7087, 0x51de003a), - PCMCIA_DEVICE_PROD_ID123("WBT", "NinjaSCSI-3", "R1.0", 0xc7ba805f, 0xfdc7c97d, 0x6973710e), - PCMCIA_DEVICE_PROD_ID123("WORKBIT", "UltraNinja-16", "1", 0x28191418, 0xb70f4b09, 0x51de003a), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, nsp_cs_ids); - static struct pcmcia_driver nsp_driver = { .owner = THIS_MODULE, .drv = { @@ -2144,7 +2132,6 @@ static struct pcmcia_driver nsp_driver = { }, .attach = nsp_cs_attach, .detach = nsp_cs_detach, - .id_table = nsp_cs_ids, }; #endif diff --git a/trunk/drivers/scsi/pcmcia/qlogic_stub.c b/trunk/drivers/scsi/pcmcia/qlogic_stub.c index 0dcf41102abf..a0175f5d11cd 100644 --- a/trunk/drivers/scsi/pcmcia/qlogic_stub.c +++ b/trunk/drivers/scsi/pcmcia/qlogic_stub.c @@ -395,27 +395,6 @@ static int qlogic_event(event_t event, int priority, event_callback_args_t * arg return 0; } /* qlogic_event */ -static struct pcmcia_device_id qlogic_ids[] = { - PCMCIA_DEVICE_PROD_ID12("EIger Labs", "PCMCIA-to-SCSI Adapter", 0x88395fa7, 0x33b7a5e6), - PCMCIA_DEVICE_PROD_ID12("EPSON", "SCSI-2 PC Card SC200", 0xd361772f, 0x299d1751), - PCMCIA_DEVICE_PROD_ID12("MACNICA", "MIRACLE SCSI-II mPS110", 0x20841b68, 0xab3c3b6d), - PCMCIA_DEVICE_PROD_ID12("MIDORI ELECTRONICS ", "CN-SC43", 0x6534382a, 0xd67eee79), - PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J03R", 0x18df0ba0, 0x24662e8a), - PCMCIA_DEVICE_PROD_ID12("KME ", "KXLC003", 0x82375a27, 0xf68e5bf7), - PCMCIA_DEVICE_PROD_ID12("KME ", "KXLC004", 0x82375a27, 0x68eace54), - PCMCIA_DEVICE_PROD_ID12("KME", "KXLC101", 0x3faee676, 0x194250ec), - PCMCIA_DEVICE_PROD_ID12("QLOGIC CORPORATION", "pc05", 0xd77b2930, 0xa85b2735), - PCMCIA_DEVICE_PROD_ID12("QLOGIC CORPORATION", "pc05 rev 1.10", 0xd77b2930, 0x70f8b5f8), - PCMCIA_DEVICE_PROD_ID123("KME", "KXLC002", "00", 0x3faee676, 0x81896b61, 0xf99f065f), - PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "SCSI2 CARD 37", 0x85c10e17, 0x1a2640c1), - PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "SCSC200A PC CARD SCSI", 0xb4585a1a, 0xa6f06ebe), - PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "SCSC200B PC CARD SCSI-10", 0xb4585a1a, 0x0a88dea0), - /* these conflict with other cards! */ - /* PCMCIA_DEVICE_PROD_ID123("MACNICA", "MIRACLE SCSI", "mPS100", 0x20841b68, 0xf8dedaeb, 0x89f7fafb), */ - /* PCMCIA_DEVICE_PROD_ID123("MACNICA", "MIRACLE SCSI", "mPS100", 0x20841b68, 0xf8dedaeb, 0x89f7fafb), */ - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, qlogic_ids); static struct pcmcia_driver qlogic_cs_driver = { .owner = THIS_MODULE, @@ -424,7 +403,6 @@ static struct pcmcia_driver qlogic_cs_driver = { }, .attach = qlogic_attach, .detach = qlogic_detach, - .id_table = qlogic_ids, }; static int __init init_qlogic_cs(void) diff --git a/trunk/drivers/scsi/pcmcia/sym53c500_cs.c b/trunk/drivers/scsi/pcmcia/sym53c500_cs.c index 7d4b16b6797d..1667da9508b4 100644 --- a/trunk/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/trunk/drivers/scsi/pcmcia/sym53c500_cs.c @@ -999,14 +999,6 @@ MODULE_AUTHOR("Bob Tracy "); MODULE_DESCRIPTION("SYM53C500 PCMCIA SCSI driver"); MODULE_LICENSE("GPL"); -static struct pcmcia_device_id sym53c500_ids[] = { - PCMCIA_DEVICE_PROD_ID12("BASICS by New Media Corporation", "SCSI Sym53C500", 0x23c78a9d, 0x0099e7f7), - PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "SCSI Bus Toaster Sym53C500", 0x085a850b, 0x45432eb8), - PCMCIA_DEVICE_PROD_ID2("SCSI9000", 0x21648f44), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, sym53c500_ids); - static struct pcmcia_driver sym53c500_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -1014,7 +1006,6 @@ static struct pcmcia_driver sym53c500_cs_driver = { }, .attach = SYM53C500_attach, .detach = SYM53C500_detach, - .id_table = sym53c500_ids, }; static int __init diff --git a/trunk/drivers/serial/serial_cs.c b/trunk/drivers/serial/serial_cs.c index 73a34b18866f..0d7b65f93e8d 100644 --- a/trunk/drivers/serial/serial_cs.c +++ b/trunk/drivers/serial/serial_cs.c @@ -772,111 +772,6 @@ serial_event(event_t event, int priority, event_callback_args_t * args) return 0; } -static struct pcmcia_device_id serial_ids[] = { - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0104, 0x000a), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0xea15), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0109, 0x0501), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0138, 0x110a), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0140, 0x000a), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0x3341), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0143, 0xc0ab), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x016c, 0x0081), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x021b, 0x0101), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x08a1, 0xc0ab), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0d0a), - PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0105, 0x0e0a), - PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63), - PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63), - PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef), - PCMCIA_PFC_DEVICE_PROD_ID123(1, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef), - PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea), - PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM33", 0x2e3ee845, 0x80609023), - PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a), - PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29), - PCMCIA_PFC_DEVICE_PROD_ID13(1, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "AnyCom", "Fast Ethernet ", 0x578ba6e7, 0x02d92d1e), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard", 0x0c2f80cd, 0x0573c29f), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet", 0x2e3ee845, 0xc0e778c2), - PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070), - PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562), - PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070), - PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x016c, 0x0020), - PCMCIA_MFC_DEVICE_PROD_ID123(1, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f), - PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c), - PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3), - PCMCIA_MFC_DEVICE_PROD_ID12(1, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15), - PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77), - PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302), - PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301), - PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039), - PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006), - PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a), - PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d50), - PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d51), - PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d52), - PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0d53), - PCMCIA_DEVICE_MANF_CARD(0x010b, 0xd180), - PCMCIA_DEVICE_MANF_CARD(0x0137, 0x000e), - PCMCIA_DEVICE_MANF_CARD(0x0137, 0x001b), - PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0025), - PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0045), - PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0052), - PCMCIA_DEVICE_PROD_ID134("ADV", "TECH", "COMpad-32/85", 0x67459937, 0x916d02ba, 0x8fbe92ae), - PCMCIA_DEVICE_PROD_ID124("GATEWAY2000", "CC3144", "PCMCIA MODEM", 0x506bccae, 0xcb3685f1, 0xbd6c43ef), - PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef), - PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef), - PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0), - PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a), - PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02), - PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa), - PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 28800 FAX/DATA MODEM", 0xa3a3062c, 0x8cbd7c76), - PCMCIA_DEVICE_PROD_ID12("COMPAQ", "PCMCIA 33600 FAX/DATA MODEM", 0xa3a3062c, 0x5a00ce95), - PCMCIA_DEVICE_PROD_ID12("Computerboards, Inc.", "PCM-COM422", 0xd0b78f51, 0x7e2d49ed), - PCMCIA_DEVICE_PROD_ID12("Dr. Neuhaus", "FURY CARD 14K4", 0x76942813, 0x8b96ce65), - PCMCIA_DEVICE_PROD_ID12("Intelligent", "ANGIA FAX/MODEM", 0xb496e65e, 0xf31602a6), - PCMCIA_DEVICE_PROD_ID12("Intel", "MODEM 2400", 0x816cc815, 0x23539b80), - PCMCIA_DEVICE_PROD_ID12("IOTech Inc ", "PCMCIA Dual RS-232 Serial Port Card", 0x3bd2d898, 0x92abc92f), - PCMCIA_DEVICE_PROD_ID12("MACRONIX", "FAX/MODEM", 0x668388b3, 0x3f9bdf2f), - PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT1432LT", 0x5f73be51, 0x0b3e2383), - PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e), - PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a), - PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab), - PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "PCMLM28.cis"), - PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "PCMLM28.cis"), - PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "3CCFEM556.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"), - PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), - PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"), - /* too generic */ - /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ - /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */ - PCMCIA_DEVICE_FUNC_ID(2), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, serial_ids); - static struct pcmcia_driver serial_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -884,7 +779,6 @@ static struct pcmcia_driver serial_cs_driver = { }, .attach = serial_attach, .detach = serial_detach, - .id_table = serial_ids, }; static int __init init_serial_cs(void) diff --git a/trunk/drivers/telephony/ixj_pcmcia.c b/trunk/drivers/telephony/ixj_pcmcia.c index ce5ebfe4af2b..e1ef0d7ee8d1 100644 --- a/trunk/drivers/telephony/ixj_pcmcia.c +++ b/trunk/drivers/telephony/ixj_pcmcia.c @@ -295,12 +295,6 @@ static int ixj_event(event_t event, int priority, event_callback_args_t * args) return 0; } -static struct pcmcia_device_id ixj_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x0257, 0x0600), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, ixj_ids); - static struct pcmcia_driver ixj_driver = { .owner = THIS_MODULE, .drv = { @@ -308,7 +302,6 @@ static struct pcmcia_driver ixj_driver = { }, .attach = ixj_attach, .detach = ixj_detach, - .id_table = ixj_ids, }; static int __init ixj_pcmcia_init(void) diff --git a/trunk/drivers/usb/host/sl811_cs.c b/trunk/drivers/usb/host/sl811_cs.c index 269d8ef01459..6e173265095c 100644 --- a/trunk/drivers/usb/host/sl811_cs.c +++ b/trunk/drivers/usb/host/sl811_cs.c @@ -68,6 +68,13 @@ static const char driver_name[DEV_NAME_LEN] = "sl811_cs"; static dev_link_t *dev_list = NULL; +static int irq_list[4] = { -1 }; +static int irq_list_count; + +module_param_array(irq_list, int, &irq_list_count, 0444); + +INT_MODULE_PARM(irq_mask, 0xdeb8); + typedef struct local_info_t { dev_link_t link; dev_node_t node; @@ -366,7 +373,7 @@ static dev_link_t *sl811_cs_attach(void) local_info_t *local; dev_link_t *link; client_reg_t client_reg; - int ret; + int ret, i; local = kmalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) @@ -378,6 +385,11 @@ static dev_link_t *sl811_cs_attach(void) /* Initialize */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < irq_list_count; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; link->irq.Handler = NULL; link->conf.Attributes = 0; @@ -406,12 +418,6 @@ static dev_link_t *sl811_cs_attach(void) return link; } -static struct pcmcia_device_id sl811_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0xc015, 0x0001), /* RATOC USB HOST CF+ Card */ - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, sl811_ids); - static struct pcmcia_driver sl811_cs_driver = { .owner = THIS_MODULE, .drv = { @@ -419,7 +425,6 @@ static struct pcmcia_driver sl811_cs_driver = { }, .attach = sl811_cs_attach, .detach = sl811_cs_detach, - .id_table = sl811_ids, }; /*====================================================================*/ diff --git a/trunk/include/asm-i386/ide.h b/trunk/include/asm-i386/ide.h index 79dfab87135d..859ebf4da632 100644 --- a/trunk/include/asm-i386/ide.h +++ b/trunk/include/asm-i386/ide.h @@ -41,17 +41,13 @@ static __inline__ int ide_default_irq(unsigned long base) static __inline__ unsigned long ide_default_io_base(int index) { - if (pci_find_device(PCI_ANY_ID, PCI_ANY_ID, NULL) == NULL) { - switch(index) { - case 2: return 0x1e8; - case 3: return 0x168; - case 4: return 0x1e0; - case 5: return 0x160; - } - } switch (index) { case 0: return 0x1f0; case 1: return 0x170; + case 2: return 0x1e8; + case 3: return 0x168; + case 4: return 0x1e0; + case 5: return 0x160; default: return 0; } diff --git a/trunk/include/asm-sparc64/auxio.h b/trunk/include/asm-sparc64/auxio.h index 81a590a50a1f..5eb01dd47150 100644 --- a/trunk/include/asm-sparc64/auxio.h +++ b/trunk/include/asm-sparc64/auxio.h @@ -75,8 +75,6 @@ #ifndef __ASSEMBLY__ -extern void __iomem *auxio_register; - #define AUXIO_LTE_ON 1 #define AUXIO_LTE_OFF 0 diff --git a/trunk/include/asm-sparc64/floppy.h b/trunk/include/asm-sparc64/floppy.h index 49d49a285943..e071b4b4edfd 100644 --- a/trunk/include/asm-sparc64/floppy.h +++ b/trunk/include/asm-sparc64/floppy.h @@ -159,7 +159,7 @@ static void sun_82077_fd_outb(unsigned char value, unsigned long port) * underruns. If non-zero, doing_pdma encodes the direction of * the transfer for debugging. 1=read 2=write */ -unsigned char *pdma_vaddr; +char *pdma_vaddr; unsigned long pdma_size; volatile int doing_pdma = 0; @@ -209,7 +209,8 @@ static void sun_fd_enable_dma(void) pdma_areasize = pdma_size; } -extern irqreturn_t sparc_floppy_irq(int, void *, struct pt_regs *); +/* Our low-level entry point in arch/sparc/kernel/entry.S */ +extern irqreturn_t floppy_hardint(int irq, void *unused, struct pt_regs *regs); static int sun_fd_request_irq(void) { @@ -219,8 +220,8 @@ static int sun_fd_request_irq(void) if(!once) { once = 1; - error = request_irq(FLOPPY_IRQ, sparc_floppy_irq, - SA_INTERRUPT, "floppy", NULL); + error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, + SA_INTERRUPT, "floppy", NULL); return ((error == 0) ? 0 : -1); } @@ -614,7 +615,7 @@ static unsigned long __init sun_floppy_init(void) struct linux_ebus *ebus; struct linux_ebus_device *edev = NULL; unsigned long config = 0; - void __iomem *auxio_reg; + unsigned long auxio_reg; for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { @@ -641,7 +642,7 @@ static unsigned long __init sun_floppy_init(void) /* Make sure the high density bit is set, some systems * (most notably Ultra5/Ultra10) come up with it clear. */ - auxio_reg = (void __iomem *) edev->resource[2].start; + auxio_reg = edev->resource[2].start; writel(readl(auxio_reg)|0x2, auxio_reg); sun_pci_ebus_dev = ebus->self; @@ -649,8 +650,7 @@ static unsigned long __init sun_floppy_init(void) spin_lock_init(&sun_pci_fd_ebus_dma.lock); /* XXX ioremap */ - sun_pci_fd_ebus_dma.regs = (void __iomem *) - edev->resource[1].start; + sun_pci_fd_ebus_dma.regs = edev->resource[1].start; if (!sun_pci_fd_ebus_dma.regs) return 0; diff --git a/trunk/include/asm-sparc64/irq.h b/trunk/include/asm-sparc64/irq.h index 018e2e46082b..3aef0ca67750 100644 --- a/trunk/include/asm-sparc64/irq.h +++ b/trunk/include/asm-sparc64/irq.h @@ -19,7 +19,7 @@ /* You should not mess with this directly. That's the job of irq.c. * * If you make changes here, please update hand coded assembler of - * the vectored interrupt trap handler in entry.S -DaveM + * SBUS/floppy interrupt handler in entry.S -DaveM * * This is currently one DCACHE line, two buckets per L2 cache * line. Keep this in mind please. @@ -122,6 +122,11 @@ extern void enable_irq(unsigned int); extern unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap); extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); +extern int request_fast_irq(unsigned int irq, + irqreturn_t (*handler)(int, void *, struct pt_regs *), + unsigned long flags, __const__ char *devname, + void *dev_id); + static __inline__ void set_softint(unsigned long bits) { __asm__ __volatile__("wr %0, 0x0, %%set_softint" diff --git a/trunk/include/asm-sparc64/rwsem.h b/trunk/include/asm-sparc64/rwsem.h index a1cc94f95984..bf2ae90ed3df 100644 --- a/trunk/include/asm-sparc64/rwsem.h +++ b/trunk/include/asm-sparc64/rwsem.h @@ -55,9 +55,8 @@ static __inline__ int rwsem_atomic_update(int delta, struct rw_semaphore *sem) "add %%g1, %1, %%g7\n\t" "cas [%2], %%g1, %%g7\n\t" "cmp %%g1, %%g7\n\t" - "membar #StoreLoad | #StoreStore\n\t" "bne,pn %%icc, 1b\n\t" - " nop\n\t" + " membar #StoreLoad | #StoreStore\n\t" "mov %%g7, %0\n\t" : "=&r" (tmp) : "0" (tmp), "r" (sem) diff --git a/trunk/include/asm-sparc64/spinlock.h b/trunk/include/asm-sparc64/spinlock.h index 9cb93a5c2b4f..db7581bdb531 100644 --- a/trunk/include/asm-sparc64/spinlock.h +++ b/trunk/include/asm-sparc64/spinlock.h @@ -52,14 +52,12 @@ static inline void _raw_spin_lock(spinlock_t *lock) __asm__ __volatile__( "1: ldstub [%1], %0\n" -" membar #StoreLoad | #StoreStore\n" " brnz,pn %0, 2f\n" -" nop\n" +" membar #StoreLoad | #StoreStore\n" " .subsection 2\n" "2: ldub [%1], %0\n" -" membar #LoadLoad\n" " brnz,pt %0, 2b\n" -" nop\n" +" membar #LoadLoad\n" " ba,a,pt %%xcc, 1b\n" " .previous" : "=&r" (tmp) @@ -97,18 +95,16 @@ static inline void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags) __asm__ __volatile__( "1: ldstub [%2], %0\n" -" membar #StoreLoad | #StoreStore\n" " brnz,pn %0, 2f\n" -" nop\n" +" membar #StoreLoad | #StoreStore\n" " .subsection 2\n" "2: rdpr %%pil, %1\n" " wrpr %3, %%pil\n" "3: ldub [%2], %0\n" -" membar #LoadLoad\n" " brnz,pt %0, 3b\n" -" nop\n" +" membar #LoadLoad\n" " ba,pt %%xcc, 1b\n" -" wrpr %1, %%pil\n" +" wrpr %1, %%pil\n" " .previous" : "=&r" (tmp1), "=&r" (tmp2) : "r"(lock), "r"(flags) @@ -166,14 +162,12 @@ static void inline __read_lock(rwlock_t *lock) "4: add %0, 1, %1\n" " cas [%2], %0, %1\n" " cmp %0, %1\n" -" membar #StoreLoad | #StoreStore\n" " bne,pn %%icc, 1b\n" -" nop\n" +" membar #StoreLoad | #StoreStore\n" " .subsection 2\n" "2: ldsw [%2], %0\n" -" membar #LoadLoad\n" " brlz,pt %0, 2b\n" -" nop\n" +" membar #LoadLoad\n" " ba,a,pt %%xcc, 4b\n" " .previous" : "=&r" (tmp1), "=&r" (tmp2) @@ -210,14 +204,12 @@ static void inline __write_lock(rwlock_t *lock) "4: or %0, %3, %1\n" " cas [%2], %0, %1\n" " cmp %0, %1\n" -" membar #StoreLoad | #StoreStore\n" " bne,pn %%icc, 1b\n" -" nop\n" +" membar #StoreLoad | #StoreStore\n" " .subsection 2\n" "2: lduw [%2], %0\n" -" membar #LoadLoad\n" " brnz,pt %0, 2b\n" -" nop\n" +" membar #LoadLoad\n" " ba,a,pt %%xcc, 4b\n" " .previous" : "=&r" (tmp1), "=&r" (tmp2) @@ -248,9 +240,8 @@ static int inline __write_trylock(rwlock_t *lock) " or %0, %4, %1\n" " cas [%3], %0, %1\n" " cmp %0, %1\n" -" membar #StoreLoad | #StoreStore\n" " bne,pn %%icc, 1b\n" -" nop\n" +" membar #StoreLoad | #StoreStore\n" " mov 1, %2\n" "2:" : "=&r" (tmp1), "=&r" (tmp2), "=&r" (result) diff --git a/trunk/include/asm-sparc64/spitfire.h b/trunk/include/asm-sparc64/spitfire.h index 1aa932773af8..9d7613eea812 100644 --- a/trunk/include/asm-sparc64/spitfire.h +++ b/trunk/include/asm-sparc64/spitfire.h @@ -111,6 +111,7 @@ static __inline__ void spitfire_put_dcache_tag(unsigned long addr, unsigned long "membar #Sync" : /* No outputs */ : "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG)); + __asm__ __volatile__ ("membar #Sync" : : : "memory"); } /* The instruction cache lines are flushed with this, but note that diff --git a/trunk/include/linux/etherdevice.h b/trunk/include/linux/etherdevice.h index 8a2df4dfbc59..a1478258d002 100644 --- a/trunk/include/linux/etherdevice.h +++ b/trunk/include/linux/etherdevice.h @@ -65,7 +65,7 @@ static inline int is_zero_ether_addr(const u8 *addr) */ static inline int is_multicast_ether_addr(const u8 *addr) { - return ((addr[0] != 0xff) && (0x01 & addr[0])); + return addr[0] & 0x01; } /** diff --git a/trunk/include/linux/mod_devicetable.h b/trunk/include/linux/mod_devicetable.h index 9b6d05172ed4..d6eb7b2efc04 100644 --- a/trunk/include/linux/mod_devicetable.h +++ b/trunk/include/linux/mod_devicetable.h @@ -175,50 +175,4 @@ struct serio_device_id { }; -/* PCMCIA */ - -struct pcmcia_device_id { - __u16 match_flags; - - __u16 manf_id; - __u16 card_id; - - __u8 func_id; - - /* for real multi-function devices */ - __u8 function; - - /* for pseude multi-function devices */ - __u8 device_no; - - __u32 prod_id_hash[4]; - - /* not matched against in kernelspace*/ -#ifdef __KERNEL__ - const char * prod_id[4]; -#else - kernel_ulong_t prod_id[4]; -#endif - - /* not matched against */ - kernel_ulong_t driver_info; -#ifdef __KERNEL__ - char * cisfile; -#else - kernel_ulong_t cisfile; -#endif -}; - -#define PCMCIA_DEV_ID_MATCH_MANF_ID 0x0001 -#define PCMCIA_DEV_ID_MATCH_CARD_ID 0x0002 -#define PCMCIA_DEV_ID_MATCH_FUNC_ID 0x0004 -#define PCMCIA_DEV_ID_MATCH_FUNCTION 0x0008 -#define PCMCIA_DEV_ID_MATCH_PROD_ID1 0x0010 -#define PCMCIA_DEV_ID_MATCH_PROD_ID2 0x0020 -#define PCMCIA_DEV_ID_MATCH_PROD_ID3 0x0040 -#define PCMCIA_DEV_ID_MATCH_PROD_ID4 0x0080 -#define PCMCIA_DEV_ID_MATCH_DEVICE_NO 0x0100 -#define PCMCIA_DEV_ID_MATCH_FAKE_CIS 0x0200 -#define PCMCIA_DEV_ID_MATCH_ANONYMOUS 0x0400 - #endif /* LINUX_MOD_DEVICETABLE_H */ diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index 1e0bc6a8d653..a3961e1d5183 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -1815,8 +1815,6 @@ #define PCI_VENDOR_ID_ITE 0x1283 #define PCI_DEVICE_ID_ITE_IT8172G 0x8172 #define PCI_DEVICE_ID_ITE_IT8172G_AUDIO 0x0801 -#define PCI_DEVICE_ID_ITE_8211 0x8211 -#define PCI_DEVICE_ID_ITE_8212 0x8212 #define PCI_DEVICE_ID_ITE_8872 0x8872 #define PCI_DEVICE_ID_ITE_IT8330G_0 0xe886 diff --git a/trunk/include/net/ieee80211.h b/trunk/include/net/ieee80211.h index 151c4f203559..7fe57f957a51 100644 --- a/trunk/include/net/ieee80211.h +++ b/trunk/include/net/ieee80211.h @@ -94,8 +94,6 @@ struct eapol { u16 length; } __attribute__ ((packed)); -#define IEEE80211_1ADDR_LEN 10 -#define IEEE80211_2ADDR_LEN 16 #define IEEE80211_3ADDR_LEN 24 #define IEEE80211_4ADDR_LEN 30 #define IEEE80211_FCS_LEN 4 @@ -302,6 +300,23 @@ struct ieee80211_snap_hdr { #define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 +/* Information Element IDs */ +#define WLAN_EID_SSID 0 +#define WLAN_EID_SUPP_RATES 1 +#define WLAN_EID_FH_PARAMS 2 +#define WLAN_EID_DS_PARAMS 3 +#define WLAN_EID_CF_PARAMS 4 +#define WLAN_EID_TIM 5 +#define WLAN_EID_IBSS_PARAMS 6 +#define WLAN_EID_CHALLENGE 16 +#define WLAN_EID_RSN 48 +#define WLAN_EID_GENERIC 221 + +#define IEEE80211_MGMT_HDR_LEN 24 +#define IEEE80211_DATA_HDR3_LEN 24 +#define IEEE80211_DATA_HDR4_LEN 30 + + #define IEEE80211_STATMASK_SIGNAL (1<<0) #define IEEE80211_STATMASK_RSSI (1<<1) #define IEEE80211_STATMASK_NOISE (1<<2) @@ -426,8 +441,6 @@ struct ieee80211_stats { struct ieee80211_device; -#include "ieee80211_crypt.h" - #define SEC_KEY_1 (1<<0) #define SEC_KEY_2 (1<<1) #define SEC_KEY_3 (1<<2) @@ -475,6 +488,15 @@ Total: 28-2340 bytes */ +struct ieee80211_header_data { + u16 frame_ctl; + u16 duration_id; + u8 addr1[6]; + u8 addr2[6]; + u8 addr3[6]; + u16 seq_ctrl; +}; + #define BEACON_PROBE_SSID_ID_POSITION 12 /* Management Frame Information Element Types */ @@ -519,7 +541,7 @@ struct ieee80211_info_element { */ struct ieee80211_authentication { - struct ieee80211_hdr_3addr header; + struct ieee80211_header_data header; u16 algorithm; u16 transaction; u16 status; @@ -528,7 +550,7 @@ struct ieee80211_authentication { struct ieee80211_probe_response { - struct ieee80211_hdr_3addr header; + struct ieee80211_header_data header; u32 time_stamp[2]; u16 beacon_interval; u16 capability; @@ -626,6 +648,12 @@ enum ieee80211_state { #define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5] +extern inline int is_broadcast_ether_addr(const u8 *addr) +{ + return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \ + (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); +} + #define CFG_IEEE80211_RESERVE_FCS (1<<0) #define CFG_IEEE80211_COMPUTE_FCS (1<<1) @@ -759,21 +787,21 @@ extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mod extern inline int ieee80211_get_hdrlen(u16 fc) { - int hdrlen = IEEE80211_3ADDR_LEN; + int hdrlen = 24; switch (WLAN_FC_GET_TYPE(fc)) { case IEEE80211_FTYPE_DATA: if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) - hdrlen = IEEE80211_4ADDR_LEN; + hdrlen = 30; /* Addr4 */ break; case IEEE80211_FTYPE_CTL: switch (WLAN_FC_GET_STYPE(fc)) { case IEEE80211_STYPE_CTS: case IEEE80211_STYPE_ACK: - hdrlen = IEEE80211_1ADDR_LEN; + hdrlen = 10; break; default: - hdrlen = IEEE80211_2ADDR_LEN; + hdrlen = 16; break; } break; diff --git a/trunk/include/pcmcia/ciscode.h b/trunk/include/pcmcia/ciscode.h index da19c297dd65..2000b43ece91 100644 --- a/trunk/include/pcmcia/ciscode.h +++ b/trunk/include/pcmcia/ciscode.h @@ -112,8 +112,6 @@ #define MANFID_TDK 0x0105 #define PRODID_TDK_CF010 0x0900 -#define PRODID_TDK_NP9610 0x0d0a -#define PRODID_TDK_MN3200 0x0e0a #define PRODID_TDK_GN3410 0x4815 #define MANFID_TOSHIBA 0x0098 diff --git a/trunk/include/pcmcia/cs.h b/trunk/include/pcmcia/cs.h index b42ddc0c1143..8d8643adc786 100644 --- a/trunk/include/pcmcia/cs.h +++ b/trunk/include/pcmcia/cs.h @@ -396,6 +396,7 @@ struct pcmcia_socket; int pcmcia_access_configuration_register(client_handle_t handle, conf_reg_t *reg); int pcmcia_deregister_client(client_handle_t handle); int pcmcia_get_configuration_info(client_handle_t handle, config_info_t *config); +int pcmcia_get_card_services_info(servinfo_t *info); int pcmcia_get_first_window(window_handle_t *win, win_req_t *req); int pcmcia_get_next_window(window_handle_t *win, win_req_t *req); int pcmcia_get_status(client_handle_t handle, cs_status_t *status); @@ -416,6 +417,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt); int pcmcia_resume_card(struct pcmcia_socket *skt); int pcmcia_eject_card(struct pcmcia_socket *skt); int pcmcia_insert_card(struct pcmcia_socket *skt); +int pcmcia_report_error(client_handle_t handle, error_info_t *err); struct pcmcia_socket * pcmcia_get_socket(struct pcmcia_socket *skt); void pcmcia_put_socket(struct pcmcia_socket *skt); diff --git a/trunk/include/pcmcia/device_id.h b/trunk/include/pcmcia/device_id.h deleted file mode 100644 index 346d81ece287..000000000000 --- a/trunk/include/pcmcia/device_id.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (2003-2004) Dominik Brodowski - * David Woodhouse - * - * License: GPL v2 - */ - -#define PCMCIA_DEVICE_MANF_CARD(manf, card) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \ - PCMCIA_DEV_ID_MATCH_CARD_ID, \ - .manf_id = (manf), \ - .card_id = (card), } - -#define PCMCIA_DEVICE_FUNC_ID(func) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_FUNC_ID, \ - .func_id = (func), } - -#define PCMCIA_DEVICE_PROD_ID1(v1, vh1) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1, \ - .prod_id = { (v1), NULL, NULL, NULL }, \ - .prod_id_hash = { (vh1), 0, 0, 0 }, } - -#define PCMCIA_DEVICE_PROD_ID2(v2, vh2) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID2, \ - .prod_id = { NULL, (v2), NULL, NULL }, \ - .prod_id_hash = { 0, (vh2), 0, 0 }, } - -#define PCMCIA_DEVICE_PROD_ID12(v1, v2, vh1, vh2) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2, \ - .prod_id = { (v1), (v2), NULL, NULL }, \ - .prod_id_hash = { (vh1), (vh2), 0, 0 }, } - -#define PCMCIA_DEVICE_PROD_ID13(v1, v3, vh1, vh3) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID3, \ - .prod_id = { (v1), NULL, (v3), NULL }, \ - .prod_id_hash = { (vh1), 0, (vh3), 0 }, } - -#define PCMCIA_DEVICE_PROD_ID14(v1, v4, vh1, vh4) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID4, \ - .prod_id = { (v1), NULL, NULL, (v4) }, \ - .prod_id_hash = { (vh1), 0, 0, (vh4) }, } - -#define PCMCIA_DEVICE_PROD_ID123(v1, v2, v3, vh1, vh2, vh3) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_PROD_ID3, \ - .prod_id = { (v1), (v2), (v3), NULL },\ - .prod_id_hash = { (vh1), (vh2), (vh3), 0 }, } - -#define PCMCIA_DEVICE_PROD_ID124(v1, v2, v4, vh1, vh2, vh4) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_PROD_ID4, \ - .prod_id = { (v1), (v2), NULL, (v4) }, \ - .prod_id_hash = { (vh1), (vh2), 0, (vh4) }, } - -#define PCMCIA_DEVICE_PROD_ID134(v1, v3, v4, vh1, vh3, vh4) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID3| \ - PCMCIA_DEV_ID_MATCH_PROD_ID4, \ - .prod_id = { (v1), NULL, (v3), (v4) }, \ - .prod_id_hash = { (vh1), 0, (vh3), (vh4) }, } - -#define PCMCIA_DEVICE_PROD_ID1234(v1, v2, v3, v4, vh1, vh2, vh3, vh4) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_PROD_ID3| \ - PCMCIA_DEV_ID_MATCH_PROD_ID4, \ - .prod_id = { (v1), (v2), (v3), (v4) }, \ - .prod_id_hash = { (vh1), (vh2), (vh3), (vh4) }, } - - -/* multi-function devices */ - -#define PCMCIA_MFC_DEVICE_MANF_CARD(mfc, manf, card) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \ - PCMCIA_DEV_ID_MATCH_CARD_ID| \ - PCMCIA_DEV_ID_MATCH_FUNCTION, \ - .manf_id = (manf), \ - .card_id = (card), \ - .function = (mfc), } - -#define PCMCIA_MFC_DEVICE_PROD_ID1(mfc, v1, vh1) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_FUNCTION, \ - .prod_id = { (v1), NULL, NULL, NULL }, \ - .prod_id_hash = { (vh1), 0, 0, 0 }, \ - .function = (mfc), } - -#define PCMCIA_MFC_DEVICE_PROD_ID2(mfc, v2, vh2) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_FUNCTION, \ - .prod_id = { NULL, (v2), NULL, NULL }, \ - .prod_id_hash = { 0, (vh2), 0, 0 }, \ - .function = (mfc), } - -#define PCMCIA_MFC_DEVICE_PROD_ID12(mfc, v1, v2, vh1, vh2) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_FUNCTION, \ - .prod_id = { (v1), (v2), NULL, NULL }, \ - .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ - .function = (mfc), } - -#define PCMCIA_MFC_DEVICE_PROD_ID13(mfc, v1, v3, vh1, vh3) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID3| \ - PCMCIA_DEV_ID_MATCH_FUNCTION, \ - .prod_id = { (v1), NULL, (v3), NULL }, \ - .prod_id_hash = { (vh1), 0, (vh3), 0 }, \ - .function = (mfc), } - -#define PCMCIA_MFC_DEVICE_PROD_ID123(mfc, v1, v2, v3, vh1, vh2, vh3) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_PROD_ID3| \ - PCMCIA_DEV_ID_MATCH_FUNCTION, \ - .prod_id = { (v1), (v2), (v3), NULL },\ - .prod_id_hash = { (vh1), (vh2), (vh3), 0 }, \ - .function = (mfc), } - -/* pseudo multi-function devices */ - -#define PCMCIA_PFC_DEVICE_MANF_CARD(mfc, manf, card) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \ - PCMCIA_DEV_ID_MATCH_CARD_ID| \ - PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ - .manf_id = (manf), \ - .card_id = (card), \ - .device_no = (mfc), } - -#define PCMCIA_PFC_DEVICE_PROD_ID1(mfc, v1, vh1) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ - .prod_id = { (v1), NULL, NULL, NULL }, \ - .prod_id_hash = { (vh1), 0, 0, 0 }, \ - .device_no = (mfc), } - -#define PCMCIA_PFC_DEVICE_PROD_ID2(mfc, v2, vh2) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ - .prod_id = { NULL, (v2), NULL, NULL }, \ - .prod_id_hash = { 0, (vh2), 0, 0 }, \ - .device_no = (mfc), } - -#define PCMCIA_PFC_DEVICE_PROD_ID12(mfc, v1, v2, vh1, vh2) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ - .prod_id = { (v1), (v2), NULL, NULL }, \ - .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ - .device_no = (mfc), } - -#define PCMCIA_PFC_DEVICE_PROD_ID13(mfc, v1, v3, vh1, vh3) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID3| \ - PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ - .prod_id = { (v1), NULL, (v3), NULL }, \ - .prod_id_hash = { (vh1), 0, (vh3), 0 }, \ - .device_no = (mfc), } - -#define PCMCIA_PFC_DEVICE_PROD_ID123(mfc, v1, v2, v3, vh1, vh2, vh3) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_PROD_ID3| \ - PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ - .prod_id = { (v1), (v2), (v3), NULL },\ - .prod_id_hash = { (vh1), (vh2), (vh3), 0 }, \ - .device_no = (mfc), } - -/* cards needing a CIS override */ - -#define PCMCIA_DEVICE_CIS_MANF_CARD(manf, card, _cisfile) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ - PCMCIA_DEV_ID_MATCH_MANF_ID| \ - PCMCIA_DEV_ID_MATCH_CARD_ID, \ - .manf_id = (manf), \ - .card_id = (card), \ - .cisfile = (_cisfile)} - -#define PCMCIA_DEVICE_CIS_PROD_ID12(v1, v2, vh1, vh2, _cisfile) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ - PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2, \ - .prod_id = { (v1), (v2), NULL, NULL }, \ - .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ - .cisfile = (_cisfile)} - -#define PCMCIA_DEVICE_CIS_PROD_ID123(v1, v2, v3, vh1, vh2, vh3, _cisfile) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ - PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_PROD_ID3, \ - .prod_id = { (v1), (v2), (v3), NULL },\ - .prod_id_hash = { (vh1), (vh2), (vh3), 0 }, \ - .cisfile = (_cisfile)} - - -#define PCMCIA_DEVICE_CIS_PROD_ID2(v2, vh2, _cisfile) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ - PCMCIA_DEV_ID_MATCH_PROD_ID2, \ - .prod_id = { NULL, (v2), NULL, NULL }, \ - .prod_id_hash = { 0, (vh2), 0, 0 }, \ - .cisfile = (_cisfile)} - -#define PCMCIA_PFC_DEVICE_CIS_PROD_ID12(mfc, v1, v2, vh1, vh2, _cisfile) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ - PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_DEVICE_NO, \ - .prod_id = { (v1), (v2), NULL, NULL }, \ - .prod_id_hash = { (vh1), (vh2), 0, 0 },\ - .device_no = (mfc), \ - .cisfile = (_cisfile)} - -#define PCMCIA_MFC_DEVICE_CIS_MANF_CARD(mfc, manf, card, _cisfile) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ - PCMCIA_DEV_ID_MATCH_MANF_ID| \ - PCMCIA_DEV_ID_MATCH_CARD_ID| \ - PCMCIA_DEV_ID_MATCH_FUNCTION, \ - .manf_id = (manf), \ - .card_id = (card), \ - .function = (mfc), \ - .cisfile = (_cisfile)} - -#define PCMCIA_MFC_DEVICE_CIS_PROD_ID12(mfc, v1, v2, vh1, vh2, _cisfile) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ - PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2| \ - PCMCIA_DEV_ID_MATCH_FUNCTION, \ - .prod_id = { (v1), (v2), NULL, NULL }, \ - .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ - .function = (mfc), \ - .cisfile = (_cisfile)} - -#define PCMCIA_MFC_DEVICE_CIS_PROD_ID4(mfc, v4, vh4, _cisfile) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_FAKE_CIS | \ - PCMCIA_DEV_ID_MATCH_PROD_ID4| \ - PCMCIA_DEV_ID_MATCH_FUNCTION, \ - .prod_id = { NULL, NULL, NULL, (v4) }, \ - .prod_id_hash = { 0, 0, 0, (vh4) }, \ - .function = (mfc), \ - .cisfile = (_cisfile)} - - -#define PCMCIA_DEVICE_NULL { .match_flags = 0, } diff --git a/trunk/include/pcmcia/ds.h b/trunk/include/pcmcia/ds.h index 2b52553f2d94..312fd958c901 100644 --- a/trunk/include/pcmcia/ds.h +++ b/trunk/include/pcmcia/ds.h @@ -18,8 +18,6 @@ #include #include -#include -#include typedef struct tuple_parse_t { tuple_t tuple; @@ -131,11 +129,12 @@ typedef struct dev_link_t { struct pcmcia_socket; +extern struct bus_type pcmcia_bus_type; + struct pcmcia_driver { dev_link_t *(*attach)(void); void (*detach)(dev_link_t *); struct module *owner; - struct pcmcia_device_id *id_table; struct device_driver drv; }; @@ -174,9 +173,7 @@ struct pcmcia_device { u8 has_manf_id:1; u8 has_card_id:1; u8 has_func_id:1; - - u8 allow_func_id_match:1; - u8 reserved:4; + u8 reserved:5; u8 func_id; u16 manf_id; diff --git a/trunk/include/pcmcia/ss.h b/trunk/include/pcmcia/ss.h index 0f7aacc33fe9..67b867f31fe4 100644 --- a/trunk/include/pcmcia/ss.h +++ b/trunk/include/pcmcia/ss.h @@ -15,12 +15,10 @@ #ifndef _LINUX_SS_H #define _LINUX_SS_H -#include -#include - #include #include #include +#include /* Definitions for card status flags for GetStatus */ #define SS_WRPROT 0x0001 @@ -173,7 +171,7 @@ typedef struct window_t { struct config_t; struct pcmcia_callback; -struct user_info_t; + struct pcmcia_socket { struct module *owner; @@ -218,9 +216,8 @@ struct pcmcia_socket { /* is set to one if resource setup is done using adjust_resource_info() */ u8 resource_setup_old:1; - u8 resource_setup_new:1; - u8 reserved:5; + u8 reserved:6; /* socket operations */ struct pccard_operations * ops; @@ -244,32 +241,9 @@ struct pcmcia_socket { unsigned int thread_events; /* pcmcia (16-bit) */ + struct pcmcia_bus_socket *pcmcia; struct pcmcia_callback *callback; -#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) - struct list_head devices_list; /* PCMCIA devices */ - u8 device_count; /* the number of devices, used - * only internally and subject - * to incorrectness and change */ - - struct { - u8 present:1, /* PCMCIA card is present in socket */ - busy:1, /* "master" ioctl is used */ - dead:1, /* pcmcia module is being unloaded */ - device_add_pending:1, /* a pseudo-multifunction-device - * add event is pending */ - reserved:4; - } pcmcia_state; - - struct work_struct device_add; /* for adding further pseudo-multifunction - * devices */ - -#ifdef CONFIG_PCMCIA_IOCTL - struct user_info_t *user; - wait_queue_head_t queue; -#endif -#endif - /* cardbus (32-bit) */ #ifdef CONFIG_CARDBUS struct resource * cb_cis_res; diff --git a/trunk/scripts/mod/file2alias.c b/trunk/scripts/mod/file2alias.c index 908bff6d1eef..32197efe67ed 100644 --- a/trunk/scripts/mod/file2alias.c +++ b/trunk/scripts/mod/file2alias.c @@ -287,42 +287,6 @@ static int do_pnp_card_entry(const char *filename, return 1; } -/* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */ -static int do_pcmcia_entry(const char *filename, - struct pcmcia_device_id *id, char *alias) -{ - unsigned int i; - - id->manf_id = TO_NATIVE(id->manf_id); - id->card_id = TO_NATIVE(id->card_id); - id->func_id = TO_NATIVE(id->func_id); - id->function = TO_NATIVE(id->function); - id->device_no = TO_NATIVE(id->device_no); - for (i=0; i<4; i++) { - id->prod_id_hash[i] = TO_NATIVE(id->prod_id_hash[i]); - } - - strcpy(alias, "pcmcia:"); - ADD(alias, "m", id->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID, - id->manf_id); - ADD(alias, "c", id->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID, - id->card_id); - ADD(alias, "f", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID, - id->func_id); - ADD(alias, "fn", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION, - id->function); - ADD(alias, "pfn", id->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO, - id->device_no); - ADD(alias, "pa", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, id->prod_id_hash[0]); - ADD(alias, "pb", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, id->prod_id_hash[1]); - ADD(alias, "pc", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, id->prod_id_hash[2]); - ADD(alias, "pd", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, id->prod_id_hash[3]); - - return 1; -} - - - /* Ignore any prefix, eg. v850 prepends _ */ static inline int sym_is(const char *symbol, const char *name) { @@ -398,9 +362,6 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, else if (sym_is(symname, "__mod_pnp_card_device_table")) do_table(symval, sym->st_size, sizeof(struct pnp_card_device_id), do_pnp_card_entry, mod); - else if (sym_is(symname, "__mod_pcmcia_device_table")) - do_table(symval, sym->st_size, sizeof(struct pcmcia_device_id), - do_pcmcia_entry, mod); } /* Now add out buffered information to the generated C source */ diff --git a/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.c b/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.c index 2d4f8e28478b..f72c81cc9952 100644 --- a/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -380,20 +380,13 @@ static int pdacf_event(event_t event, int priority, event_callback_args_t *args) /* * Module entry points */ -static struct pcmcia_device_id snd_pdacf_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x015d, 0x4c45), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, snd_pdacf_ids); - static struct pcmcia_driver pdacf_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "snd-pdaudiocf", }, .attach = snd_pdacf_attach, - .detach = snd_pdacf_detach, - .id_table = snd_pdacf_ids, + .detach = snd_pdacf_detach }; static int __init init_pdacf(void) diff --git a/trunk/sound/pcmcia/vx/vxpocket.c b/trunk/sound/pcmcia/vx/vxpocket.c index 5f4c13264159..fce2ad04fd8b 100644 --- a/trunk/sound/pcmcia/vx/vxpocket.c +++ b/trunk/sound/pcmcia/vx/vxpocket.c @@ -18,6 +18,17 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* + please add the following as /etc/pcmcia/vxpocket.conf: + + device "snd-vxpocket" + class "audio" module "snd-vxpocket" + + card "Digigram VX-POCKET" + manfid 0x01f1, 0x0100 + bind "snd-vxpocket" + + */ #include #include @@ -129,20 +140,13 @@ static void vxp_detach(dev_link_t *link) * Module entry points */ -static struct pcmcia_device_id vxp_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x01f1, 0x0100), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, vxp_ids); - static struct pcmcia_driver vxp_cs_driver = { .owner = THIS_MODULE, .drv = { .name = DEV_INFO, }, .attach = vxp_attach, - .detach = vxp_detach, - .id_table = vxp_ids, + .detach = vxp_detach }; static int __init init_vxpocket(void)