Merge /spare/repo/netdev-2.6 branch 'ieee80211'
This commit is contained in:
commit
d011e151bc
|
@ -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 PCMCIA (PC
|
||||
Card) hardware, for example, you probably needn't concern yourself
|
||||
with pcmcia-cs.
|
||||
necessary on all systems; obviously, if you don't have any ISDN
|
||||
hardware, for example, you probably needn't concern yourself with
|
||||
isdn4k-utils.
|
||||
|
||||
o Gnu C 2.95.3 # gcc --version
|
||||
o Gnu make 3.79.1 # make --version
|
||||
|
@ -57,6 +57,7 @@ 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
|
||||
|
@ -186,13 +187,20 @@ 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. Pay attention when you recompile your kernel ;-).
|
||||
Also, be sure to upgrade to the latest pcmcia-cs release.
|
||||
kernel source. The "pcmciautils" package (see above) replaces pcmcia-cs
|
||||
for newest kernels.
|
||||
|
||||
Quota-tools
|
||||
-----------
|
||||
|
@ -349,9 +357,13 @@ Xfsprogs
|
|||
--------
|
||||
o <ftp://oss.sgi.com/projects/xfs/download/>
|
||||
|
||||
Pcmciautils
|
||||
-----------
|
||||
o <ftp://ftp.kernel.org/pub/linux/utils/kernel/pcmcia/>
|
||||
|
||||
Pcmcia-cs
|
||||
---------
|
||||
o <ftp://pcmcia-cs.sourceforge.net/pub/pcmcia-cs/pcmcia-cs-3.1.21.tar.gz>
|
||||
o <http://pcmcia-cs.sourceforge.net/>
|
||||
|
||||
Quota-tools
|
||||
----------
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
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 <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
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".
|
|
@ -16,7 +16,7 @@
|
|||
#include <asm/ebus.h>
|
||||
#include <asm/auxio.h>
|
||||
|
||||
/* This cannot be static, as it is referenced in entry.S */
|
||||
/* This cannot be static, as it is referenced in irq.c */
|
||||
void __iomem *auxio_register = NULL;
|
||||
|
||||
enum auxio_type {
|
||||
|
|
|
@ -271,8 +271,9 @@ cplus_fptrap_insn_1:
|
|||
fmuld %f0, %f2, %f26
|
||||
faddd %f0, %f2, %f28
|
||||
fmuld %f0, %f2, %f30
|
||||
membar #Sync
|
||||
b,pt %xcc, fpdis_exit
|
||||
membar #Sync
|
||||
nop
|
||||
2: andcc %g5, FPRS_DU, %g0
|
||||
bne,pt %icc, 3f
|
||||
fzero %f32
|
||||
|
@ -301,8 +302,9 @@ cplus_fptrap_insn_2:
|
|||
fmuld %f32, %f34, %f58
|
||||
faddd %f32, %f34, %f60
|
||||
fmuld %f32, %f34, %f62
|
||||
membar #Sync
|
||||
ba,pt %xcc, fpdis_exit
|
||||
membar #Sync
|
||||
nop
|
||||
3: mov SECONDARY_CONTEXT, %g3
|
||||
add %g6, TI_FPREGS, %g1
|
||||
ldxa [%g3] ASI_DMMU, %g5
|
||||
|
@ -699,116 +701,6 @@ 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:
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/cpudata.h>
|
||||
#include <asm/auxio.h>
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static void distribute_irqs(void);
|
||||
|
@ -834,138 +835,66 @@ void handler_irq(int irq, struct pt_regs *regs)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_FD
|
||||
extern void floppy_interrupt(int irq, void *dev_cookie, struct pt_regs *regs);
|
||||
extern irqreturn_t floppy_interrupt(int, void *, struct pt_regs *);;
|
||||
|
||||
void sparc_floppy_irq(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;
|
||||
|
||||
irqreturn_t 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();
|
||||
if (likely(doing_pdma)) {
|
||||
void __iomem *stat = (void __iomem *) fdc_status;
|
||||
unsigned char *vaddr = pdma_vaddr;
|
||||
unsigned long size = pdma_size;
|
||||
u8 val;
|
||||
|
||||
irq_enter();
|
||||
kstat_this_cpu.irqs[irq]++;
|
||||
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++;
|
||||
|
||||
*(irq_work(cpu, irq)) = 0;
|
||||
bucket = get_ino_in_irqaction(action) + ivector_table;
|
||||
/* write */
|
||||
writeb(data, stat + 1);
|
||||
}
|
||||
size--;
|
||||
}
|
||||
|
||||
bucket->flags |= IBF_INPROGRESS;
|
||||
pdma_vaddr = vaddr;
|
||||
pdma_size = size;
|
||||
|
||||
floppy_interrupt(irq, dev_cookie, regs);
|
||||
upa_writel(ICLR_IDLE, bucket->iclr);
|
||||
/* 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);
|
||||
|
||||
bucket->flags &= ~IBF_INPROGRESS;
|
||||
doing_pdma = 0;
|
||||
}
|
||||
|
||||
irq_exit();
|
||||
main_interrupt:
|
||||
return floppy_interrupt(irq, dev_cookie, regs);
|
||||
}
|
||||
EXPORT_SYMBOL(sparc_floppy_irq);
|
||||
#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)
|
||||
|
||||
static void install_fast_irq(unsigned int cpu_irq,
|
||||
irqreturn_t (*handler)(int, void *, struct pt_regs *))
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if ((bucket->pil == 0) || (bucket->pil == 14)) {
|
||||
printk("request_fast_irq: Trying to register shared IRQ 0 or 14.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&irq_action_lock, flags);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
|
|
@ -32,8 +32,9 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore\n"
|
||||
" nop\n"
|
||||
: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
|
||||
: "r" (&sem->count), "r" (incr), "m" (sem->count)
|
||||
: "cc");
|
||||
|
@ -71,8 +72,9 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore\n"
|
||||
" nop\n"
|
||||
"2:\n"
|
||||
" .subsection 2\n"
|
||||
"3: mov %0, %%g1\n"
|
||||
|
@ -128,8 +130,9 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore\n"
|
||||
" nop\n"
|
||||
"2:\n"
|
||||
" .subsection 2\n"
|
||||
"3: mov %0, %%g1\n"
|
||||
|
@ -233,8 +236,9 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore\n"
|
||||
" nop\n"
|
||||
"2:\n"
|
||||
" .subsection 2\n"
|
||||
"3: mov %2, %%g1\n"
|
||||
|
|
|
@ -227,7 +227,6 @@ 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);
|
||||
|
|
|
@ -98,8 +98,9 @@ startup_continue:
|
|||
|
||||
sethi %hi(prom_entry_lock), %g2
|
||||
1: ldstub [%g2 + %lo(prom_entry_lock)], %g1
|
||||
membar #StoreLoad | #StoreStore
|
||||
brnz,pn %g1, 1b
|
||||
membar #StoreLoad | #StoreStore
|
||||
nop
|
||||
|
||||
sethi %hi(p1275buf), %g2
|
||||
or %g2, %lo(p1275buf), %g2
|
||||
|
|
|
@ -87,14 +87,17 @@
|
|||
#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;
|
||||
add %dest, 0x40, %dest; \
|
||||
DO_SYNC
|
||||
|
||||
#define STORE_JUMP(dest, fsrc, target) \
|
||||
EX_ST(STORE_BLK(%fsrc, %dest)); \
|
||||
add %dest, 0x40, %dest; \
|
||||
ba,pt %xcc, target;
|
||||
ba,pt %xcc, target; \
|
||||
nop;
|
||||
|
||||
#define FINISH_VISCHUNK(dest, f0, f1, left) \
|
||||
subcc %left, 8, %left;\
|
||||
|
@ -239,17 +242,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) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
|
||||
STORE_JUMP(o0, f48, 40f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 40f)
|
||||
2: FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
|
||||
STORE_JUMP(o0, f48, 48f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 48f)
|
||||
3: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
|
||||
STORE_JUMP(o0, f48, 56f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 56f)
|
||||
|
||||
1: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
|
||||
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
|
||||
|
@ -260,17 +263,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) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
|
||||
STORE_JUMP(o0, f48, 41f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 41f)
|
||||
2: FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
|
||||
STORE_JUMP(o0, f48, 49f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 49f)
|
||||
3: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
|
||||
STORE_JUMP(o0, f48, 57f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 57f)
|
||||
|
||||
1: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
|
||||
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
|
||||
|
@ -281,17 +284,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) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
|
||||
STORE_JUMP(o0, f48, 42f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 42f)
|
||||
2: FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
|
||||
STORE_JUMP(o0, f48, 50f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 50f)
|
||||
3: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
|
||||
STORE_JUMP(o0, f48, 58f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 58f)
|
||||
|
||||
1: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
|
||||
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
|
||||
|
@ -302,17 +305,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) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)
|
||||
STORE_JUMP(o0, f48, 43f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 43f)
|
||||
2: FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
|
||||
STORE_JUMP(o0, f48, 51f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 51f)
|
||||
3: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
|
||||
STORE_JUMP(o0, f48, 59f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 59f)
|
||||
|
||||
1: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
|
||||
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
|
||||
|
@ -323,17 +326,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) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
|
||||
STORE_JUMP(o0, f48, 44f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 44f)
|
||||
2: FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
|
||||
STORE_JUMP(o0, f48, 52f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 52f)
|
||||
3: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
|
||||
STORE_JUMP(o0, f48, 60f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 60f)
|
||||
|
||||
1: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
|
||||
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
|
||||
|
@ -344,17 +347,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) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
|
||||
STORE_JUMP(o0, f48, 45f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 45f)
|
||||
2: FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
|
||||
STORE_JUMP(o0, f48, 53f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 53f)
|
||||
3: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
|
||||
STORE_JUMP(o0, f48, 61f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 61f)
|
||||
|
||||
1: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
|
||||
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
|
||||
|
@ -365,17 +368,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) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
|
||||
STORE_JUMP(o0, f48, 46f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 46f)
|
||||
2: FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
|
||||
STORE_JUMP(o0, f48, 54f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 54f)
|
||||
3: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
|
||||
STORE_JUMP(o0, f48, 62f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 62f)
|
||||
|
||||
1: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
|
||||
LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
|
||||
|
@ -386,17 +389,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) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
|
||||
STORE_JUMP(o0, f48, 47f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 47f)
|
||||
2: FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
|
||||
STORE_JUMP(o0, f48, 55f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 55f)
|
||||
3: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
|
||||
STORE_SYNC(o0, f48) membar #Sync
|
||||
STORE_SYNC(o0, f48)
|
||||
FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
|
||||
STORE_JUMP(o0, f48, 63f) membar #Sync
|
||||
STORE_JUMP(o0, f48, 63f)
|
||||
|
||||
40: FINISH_VISCHUNK(o0, f0, f2, g3)
|
||||
41: FINISH_VISCHUNK(o0, f2, f4, g3)
|
||||
|
|
|
@ -72,7 +72,11 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
|
|||
|
||||
stda %f48, [%g3 + %g1] ASI_BLK_P
|
||||
5: membar #Sync
|
||||
jmpl %g7 + %g0, %g0
|
||||
ba,pt %xcc, 80f
|
||||
nop
|
||||
|
||||
.align 32
|
||||
80: jmpl %g7 + %g0, %g0
|
||||
nop
|
||||
|
||||
6: ldub [%g3 + TI_FPSAVED], %o5
|
||||
|
@ -87,8 +91,11 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3
|
|||
stda %f32, [%g2 + %g1] ASI_BLK_P
|
||||
stda %f48, [%g3 + %g1] ASI_BLK_P
|
||||
membar #Sync
|
||||
jmpl %g7 + %g0, %g0
|
||||
ba,pt %xcc, 80f
|
||||
nop
|
||||
|
||||
.align 32
|
||||
80: jmpl %g7 + %g0, %g0
|
||||
nop
|
||||
|
||||
.align 32
|
||||
|
@ -126,6 +133,10 @@ 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
|
||||
|
|
|
@ -7,18 +7,6 @@
|
|||
#include <linux/config.h>
|
||||
#include <asm/asi.h>
|
||||
|
||||
/* 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
|
||||
|
@ -52,6 +40,24 @@ 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 */
|
||||
|
@ -62,9 +68,10 @@ 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
|
||||
sra %g7, 0, %o0
|
||||
nop
|
||||
.size atomic_add_ret, .-atomic_add_ret
|
||||
|
||||
.globl atomic_sub_ret
|
||||
|
@ -77,9 +84,10 @@ 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
|
||||
sra %g7, 0, %o0
|
||||
nop
|
||||
.size atomic_sub_ret, .-atomic_sub_ret
|
||||
|
||||
.globl atomic64_add
|
||||
|
@ -118,9 +126,10 @@ 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
|
||||
mov %g7, %o0
|
||||
nop
|
||||
.size atomic64_add_ret, .-atomic64_add_ret
|
||||
|
||||
.globl atomic64_sub_ret
|
||||
|
@ -133,7 +142,8 @@ 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
|
||||
mov %g7, %o0
|
||||
nop
|
||||
.size atomic64_sub_ret, .-atomic64_sub_ret
|
||||
|
|
|
@ -7,19 +7,25 @@
|
|||
#include <linux/config.h>
|
||||
#include <asm/asi.h>
|
||||
|
||||
.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 membar #StoreLoad | #StoreStore
|
||||
#else
|
||||
#define BITOP_PRE_BARRIER nop
|
||||
#define BITOP_POST_BARRIER nop
|
||||
#endif
|
||||
#define BITOP_POST_BARRIER \
|
||||
ba,pt %xcc, 80b; \
|
||||
membar #StoreLoad | #StoreStore
|
||||
|
||||
.text
|
||||
80: retl
|
||||
nop
|
||||
#else
|
||||
#define BITOP_PRE_BARRIER
|
||||
#define BITOP_POST_BARRIER
|
||||
#endif
|
||||
|
||||
.globl test_and_set_bit
|
||||
.type test_and_set_bit,#function
|
||||
|
@ -37,10 +43,11 @@ test_and_set_bit: /* %o0=nr, %o1=addr */
|
|||
cmp %g7, %g1
|
||||
bne,pn %xcc, 1b
|
||||
and %g7, %o2, %g2
|
||||
BITOP_POST_BARRIER
|
||||
clr %o0
|
||||
movrne %g2, 1, %o0
|
||||
BITOP_POST_BARRIER
|
||||
retl
|
||||
movrne %g2, 1, %o0
|
||||
nop
|
||||
.size test_and_set_bit, .-test_and_set_bit
|
||||
|
||||
.globl test_and_clear_bit
|
||||
|
@ -59,10 +66,11 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */
|
|||
cmp %g7, %g1
|
||||
bne,pn %xcc, 1b
|
||||
and %g7, %o2, %g2
|
||||
BITOP_POST_BARRIER
|
||||
clr %o0
|
||||
movrne %g2, 1, %o0
|
||||
BITOP_POST_BARRIER
|
||||
retl
|
||||
movrne %g2, 1, %o0
|
||||
nop
|
||||
.size test_and_clear_bit, .-test_and_clear_bit
|
||||
|
||||
.globl test_and_change_bit
|
||||
|
@ -81,10 +89,11 @@ test_and_change_bit: /* %o0=nr, %o1=addr */
|
|||
cmp %g7, %g1
|
||||
bne,pn %xcc, 1b
|
||||
and %g7, %o2, %g2
|
||||
BITOP_POST_BARRIER
|
||||
clr %o0
|
||||
movrne %g2, 1, %o0
|
||||
BITOP_POST_BARRIER
|
||||
retl
|
||||
movrne %g2, 1, %o0
|
||||
nop
|
||||
.size test_and_change_bit, .-test_and_change_bit
|
||||
|
||||
.globl set_bit
|
||||
|
|
|
@ -252,8 +252,9 @@ wlock_again:
|
|||
" andn %%g1, %%g3, %%g7\n"
|
||||
" casx [%0], %%g1, %%g7\n"
|
||||
" cmp %%g1, %%g7\n"
|
||||
" membar #StoreLoad | #StoreStore\n"
|
||||
" bne,pn %%xcc, 1b\n"
|
||||
" membar #StoreLoad | #StoreStore"
|
||||
" nop"
|
||||
: /* no outputs */
|
||||
: "r" (&(rw->lock))
|
||||
: "g3", "g1", "g7", "cc", "memory");
|
||||
|
@ -351,8 +352,9 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore"
|
||||
" nop"
|
||||
: /* no outputs */
|
||||
: "r" (&(rw->lock))
|
||||
: "g3", "g1", "g7", "cc", "memory");
|
||||
|
|
|
@ -48,8 +48,9 @@ start_to_zero:
|
|||
#endif
|
||||
to_zero:
|
||||
ldstub [%o1], %g3
|
||||
membar #StoreLoad | #StoreStore
|
||||
brnz,pn %g3, spin_on_lock
|
||||
membar #StoreLoad | #StoreStore
|
||||
nop
|
||||
loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */
|
||||
cmp %g2, %g7
|
||||
|
||||
|
@ -71,8 +72,9 @@ loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */
|
|||
nop
|
||||
spin_on_lock:
|
||||
ldub [%o1], %g3
|
||||
membar #LoadLoad
|
||||
brnz,pt %g3, spin_on_lock
|
||||
membar #LoadLoad
|
||||
nop
|
||||
ba,pt %xcc, to_zero
|
||||
nop
|
||||
nop
|
||||
|
|
|
@ -17,8 +17,9 @@ __down_read:
|
|||
bne,pn %icc, 1b
|
||||
add %g7, 1, %g7
|
||||
cmp %g7, 0
|
||||
membar #StoreLoad | #StoreStore
|
||||
bl,pn %icc, 3f
|
||||
membar #StoreLoad | #StoreStore
|
||||
nop
|
||||
2:
|
||||
retl
|
||||
nop
|
||||
|
@ -57,8 +58,9 @@ __down_write:
|
|||
cmp %g3, %g7
|
||||
bne,pn %icc, 1b
|
||||
cmp %g7, 0
|
||||
membar #StoreLoad | #StoreStore
|
||||
bne,pn %icc, 3f
|
||||
membar #StoreLoad | #StoreStore
|
||||
nop
|
||||
2: retl
|
||||
nop
|
||||
3:
|
||||
|
@ -97,8 +99,9 @@ __up_read:
|
|||
cmp %g1, %g7
|
||||
bne,pn %icc, 1b
|
||||
cmp %g7, 0
|
||||
membar #StoreLoad | #StoreStore
|
||||
bl,pn %icc, 3f
|
||||
membar #StoreLoad | #StoreStore
|
||||
nop
|
||||
2: retl
|
||||
nop
|
||||
3: sethi %hi(RWSEM_ACTIVE_MASK), %g1
|
||||
|
@ -126,8 +129,9 @@ __up_write:
|
|||
bne,pn %icc, 1b
|
||||
sub %g7, %g1, %g7
|
||||
cmp %g7, 0
|
||||
membar #StoreLoad | #StoreStore
|
||||
bl,pn %icc, 3f
|
||||
membar #StoreLoad | #StoreStore
|
||||
nop
|
||||
2:
|
||||
retl
|
||||
nop
|
||||
|
@ -151,8 +155,9 @@ __downgrade_write:
|
|||
bne,pn %icc, 1b
|
||||
sub %g7, %g1, %g7
|
||||
cmp %g7, 0
|
||||
membar #StoreLoad | #StoreStore
|
||||
bl,pn %icc, 3f
|
||||
membar #StoreLoad | #StoreStore
|
||||
nop
|
||||
2:
|
||||
retl
|
||||
nop
|
||||
|
|
|
@ -136,8 +136,9 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore"
|
||||
" nop"
|
||||
: /* no outputs */
|
||||
: "r" (mask), "r" (non_cpu_bits), "r" (&page->flags)
|
||||
: "g1", "g7");
|
||||
|
@ -157,8 +158,9 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore\n"
|
||||
" nop\n"
|
||||
"2:"
|
||||
: /* no outputs */
|
||||
: "r" (cpu), "r" (mask), "r" (&page->flags),
|
||||
|
|
|
@ -266,8 +266,9 @@ __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
|
||||
membar #Sync
|
||||
nop
|
||||
stxa %g2, [%o4] ASI_DMMU
|
||||
flush %g6
|
||||
wrpr %g0, 0, %tl
|
||||
|
|
|
@ -300,7 +300,6 @@ 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)
|
||||
|
||||
|
@ -348,6 +347,28 @@ 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
|
||||
|
@ -1071,16 +1092,6 @@ 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
|
||||
*/
|
||||
|
@ -1846,18 +1857,6 @@ 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);
|
||||
|
@ -1952,7 +1951,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) {
|
||||
!cfq_cfqq_must_alloc_slice(cfqq)) {
|
||||
cfq_mark_cfqq_must_alloc_slice(cfqq);
|
||||
return ELV_MQUEUE_MUST;
|
||||
}
|
||||
|
@ -1969,7 +1968,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) {
|
||||
if (rw == READ || !cfq_cfqq_must_alloc_slice(cfqq)) {
|
||||
cfq_mark_cfqq_must_alloc_slice(cfqq);
|
||||
return ELV_MQUEUE_MUST;
|
||||
}
|
||||
|
|
|
@ -1089,6 +1089,14 @@ 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 = {
|
||||
|
@ -1096,6 +1104,7 @@ static struct pcmcia_driver bluecard_driver = {
|
|||
},
|
||||
.attach = bluecard_attach,
|
||||
.detach = bluecard_detach,
|
||||
.id_table = bluecard_ids,
|
||||
};
|
||||
|
||||
static int __init init_bluecard_cs(void)
|
||||
|
|
|
@ -935,6 +935,12 @@ 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 = {
|
||||
|
@ -942,6 +948,7 @@ static struct pcmcia_driver bt3c_driver = {
|
|||
},
|
||||
.attach = bt3c_attach,
|
||||
.detach = bt3c_detach,
|
||||
.id_table = bt3c_ids,
|
||||
};
|
||||
|
||||
static int __init init_bt3c_cs(void)
|
||||
|
|
|
@ -855,6 +855,12 @@ 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 = {
|
||||
|
@ -862,6 +868,7 @@ static struct pcmcia_driver btuart_driver = {
|
|||
},
|
||||
.attach = btuart_attach,
|
||||
.detach = btuart_detach,
|
||||
.id_table = btuart_ids,
|
||||
};
|
||||
|
||||
static int __init init_btuart_cs(void)
|
||||
|
|
|
@ -807,6 +807,13 @@ 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 = {
|
||||
|
@ -814,6 +821,7 @@ static struct pcmcia_driver dtl1_driver = {
|
|||
},
|
||||
.attach = dtl1_attach,
|
||||
.detach = dtl1_detach,
|
||||
.id_table = dtl1_ids,
|
||||
};
|
||||
|
||||
static int __init init_dtl1_cs(void)
|
||||
|
|
|
@ -581,7 +581,7 @@ static dev_link_t *mgslpc_attach(void)
|
|||
|
||||
/* Interrupt setup */
|
||||
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
|
||||
link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
|
||||
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
|
||||
link->irq.Handler = NULL;
|
||||
|
||||
link->conf.Attributes = 0;
|
||||
|
@ -3081,6 +3081,12 @@ 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 = {
|
||||
|
@ -3088,6 +3094,7 @@ static struct pcmcia_driver mgslpc_driver = {
|
|||
},
|
||||
.attach = mgslpc_attach,
|
||||
.detach = mgslpc_detach,
|
||||
.id_table = mgslpc_ids,
|
||||
};
|
||||
|
||||
static struct tty_operations mgslpc_ops = {
|
||||
|
|
|
@ -606,6 +606,12 @@ config BLK_DEV_IT8172
|
|||
<http://www.ite.com.tw/ia/brief_it8172bsp.htm>; picture of the
|
||||
board at <http://www.mvista.com/partners/semiconductor/ite.html>.
|
||||
|
||||
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
|
||||
|
|
|
@ -119,6 +119,10 @@ 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.
|
||||
|
|
|
@ -132,7 +132,6 @@ 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 }
|
||||
|
|
|
@ -1181,7 +1181,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
|
|||
pre_reset(drive);
|
||||
SELECT_DRIVE(drive);
|
||||
udelay (20);
|
||||
hwif->OUTB(WIN_SRST, IDE_COMMAND_REG);
|
||||
hwif->OUTBSYNC(drive, WIN_SRST, IDE_COMMAND_REG);
|
||||
ndelay(400);
|
||||
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
|
||||
hwgroup->polling = 1;
|
||||
__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
|
||||
|
|
|
@ -457,6 +457,40 @@ 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 = {
|
||||
|
@ -464,6 +498,7 @@ static struct pcmcia_driver ide_cs_driver = {
|
|||
},
|
||||
.attach = ide_attach,
|
||||
.detach = ide_detach,
|
||||
.id_table = ide_ids,
|
||||
};
|
||||
|
||||
static int __init init_ide_cs(void)
|
||||
|
|
|
@ -12,6 +12,7 @@ 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
|
||||
|
|
|
@ -39,6 +39,17 @@
|
|||
|
||||
#include <asm/io.h>
|
||||
|
||||
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) {
|
||||
|
@ -78,79 +89,85 @@ 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,
|
||||
},{ /* 1 */
|
||||
},{ /* 2 */
|
||||
.name = "SAMURAI",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
.autodma = AUTODMA,
|
||||
.bootable = ON_BOARD,
|
||||
},{ /* 2 */
|
||||
},{ /* 3 */
|
||||
.name = "HT6565",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
.autodma = AUTODMA,
|
||||
.bootable = ON_BOARD,
|
||||
},{ /* 3 */
|
||||
},{ /* 4 */
|
||||
.name = "UM8673F",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
.autodma = NODMA,
|
||||
.bootable = ON_BOARD,
|
||||
},{ /* 4 */
|
||||
},{ /* 5 */
|
||||
.name = "UM8886A",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
.autodma = NODMA,
|
||||
.bootable = ON_BOARD,
|
||||
},{ /* 5 */
|
||||
},{ /* 6 */
|
||||
.name = "UM8886BF",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
.autodma = NODMA,
|
||||
.bootable = ON_BOARD,
|
||||
},{ /* 6 */
|
||||
},{ /* 7 */
|
||||
.name = "HINT_IDE",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
.autodma = AUTODMA,
|
||||
.bootable = ON_BOARD,
|
||||
},{ /* 7 */
|
||||
},{ /* 8 */
|
||||
.name = "VIA_IDE",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
.autodma = NOAUTODMA,
|
||||
.bootable = ON_BOARD,
|
||||
},{ /* 8 */
|
||||
},{ /* 9 */
|
||||
.name = "OPTI621V",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
.autodma = NOAUTODMA,
|
||||
.bootable = ON_BOARD,
|
||||
},{ /* 9 */
|
||||
},{ /* 10 */
|
||||
.name = "VIA8237SATA",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
.autodma = AUTODMA,
|
||||
.bootable = OFF_BOARD,
|
||||
},{ /* 10 */
|
||||
},{ /* 11 */
|
||||
.name = "Piccolo0102",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
.autodma = NOAUTODMA,
|
||||
.bootable = ON_BOARD,
|
||||
},{ /* 11 */
|
||||
},{ /* 12 */
|
||||
.name = "Piccolo0103",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
.autodma = NOAUTODMA,
|
||||
.bootable = ON_BOARD,
|
||||
},{ /* 12 */
|
||||
},{ /* 13 */
|
||||
.name = "Piccolo0105",
|
||||
.init_hwif = init_hwif_generic,
|
||||
.channels = 2,
|
||||
|
@ -174,6 +191,10 @@ 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)))
|
||||
|
@ -195,21 +216,23 @@ out:
|
|||
}
|
||||
|
||||
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, 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},
|
||||
{ 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},
|
||||
#ifdef CONFIG_BLK_DEV_IDE_SATA
|
||||
{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
|
||||
{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237_SATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10},
|
||||
#endif
|
||||
{ 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},
|
||||
{ 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},
|
||||
{ 0, },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
* 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
|
||||
|
@ -446,44 +451,29 @@ static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = {
|
|||
#define F_LOW_PCI_50 0x2d
|
||||
#define F_LOW_PCI_66 0x42
|
||||
|
||||
/* 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);
|
||||
/*
|
||||
* Hold all the highpoint quirks and revision information in one
|
||||
* place.
|
||||
*/
|
||||
|
||||
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
|
||||
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;
|
||||
};
|
||||
|
||||
static u32 hpt_revision (struct pci_dev *dev)
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
static __devinit u32 hpt_revision (struct pci_dev *dev)
|
||||
{
|
||||
u32 class_rev;
|
||||
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
|
||||
|
@ -507,37 +497,33 @@ static 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)
|
||||
{
|
||||
struct pci_dev *dev = HWIF(drive)->pci_dev;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct hpt_info *info = ide_get_hwifdata(hwif);
|
||||
u8 mode = 0;
|
||||
|
||||
if (hpt_minimum_revision(dev, 8)) { /* HPT374 */
|
||||
/* FIXME: TODO - move this to set info->mode once at boot */
|
||||
|
||||
if (info->revision >= 8) { /* HPT374 */
|
||||
mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3;
|
||||
} else if (hpt_minimum_revision(dev, 7)) { /* HPT371 */
|
||||
} else if (info->revision >= 7) { /* HPT371 */
|
||||
mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3;
|
||||
} else if (hpt_minimum_revision(dev, 6)) { /* HPT302 */
|
||||
} else if (info->revision >= 6) { /* HPT302 */
|
||||
mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3;
|
||||
} else if (hpt_minimum_revision(dev, 5)) { /* HPT372 */
|
||||
} else if (info->revision >= 5) { /* HPT372 */
|
||||
mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3;
|
||||
} else if (hpt_minimum_revision(dev, 4)) { /* HPT370A */
|
||||
} else if (info->revision >= 4) { /* HPT370A */
|
||||
mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;
|
||||
} else if (hpt_minimum_revision(dev, 3)) { /* HPT370 */
|
||||
} else if (info->revision >= 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;
|
||||
}
|
||||
|
@ -549,7 +535,8 @@ static u8 hpt3xx_ratemask (ide_drive_t *drive)
|
|||
|
||||
static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
|
||||
{
|
||||
struct pci_dev *dev = HWIF(drive)->pci_dev;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct hpt_info *info = ide_get_hwifdata(hwif);
|
||||
u8 mode = hpt3xx_ratemask(drive);
|
||||
|
||||
if (drive->media != ide_disk)
|
||||
|
@ -561,7 +548,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
|
|||
break;
|
||||
case 0x03:
|
||||
speed = min(speed, (u8)XFER_UDMA_5);
|
||||
if (hpt_minimum_revision(dev, 5))
|
||||
if (info->revision >= 5)
|
||||
break;
|
||||
if (check_in_drive_lists(drive, bad_ata100_5))
|
||||
speed = min(speed, (u8)XFER_UDMA_4);
|
||||
|
@ -571,7 +558,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
|
|||
/*
|
||||
* CHECK ME, Does this need to be set to 5 ??
|
||||
*/
|
||||
if (hpt_minimum_revision(dev, 3))
|
||||
if (info->revision >= 3)
|
||||
break;
|
||||
if ((check_in_drive_lists(drive, bad_ata66_4)) ||
|
||||
(!(HPT366_ALLOW_ATA66_4)))
|
||||
|
@ -585,7 +572,7 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
|
|||
/*
|
||||
* CHECK ME, Does this need to be set to 5 ??
|
||||
*/
|
||||
if (hpt_minimum_revision(dev, 3))
|
||||
if (info->revision >= 3)
|
||||
break;
|
||||
if (check_in_drive_lists(drive, bad_ata33))
|
||||
speed = min(speed, (u8)XFER_MW_DMA_2);
|
||||
|
@ -624,11 +611,12 @@ 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)
|
||||
{
|
||||
struct pci_dev *dev = HWIF(drive)->pci_dev;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = hwif->pci_dev;
|
||||
struct hpt_info *info = ide_get_hwifdata(hwif);
|
||||
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(drive)->channel) ? 0x55 : 0x51;
|
||||
u8 regfast = (hwif->channel) ? 0x55 : 0x51;
|
||||
u8 drive_fast = 0;
|
||||
u32 reg1 = 0, reg2 = 0;
|
||||
|
||||
|
@ -636,16 +624,11 @@ 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,
|
||||
(struct chipset_bus_clock_list_entry *) pci_get_drvdata(dev));
|
||||
reg2 = pci_bus_clock_list(speed, info->speed);
|
||||
|
||||
/*
|
||||
* Disable on-chip PIO FIFO/buffer
|
||||
* (to avoid problems handling I/O errors later)
|
||||
|
@ -665,10 +648,11 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
|
|||
|
||||
static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
|
||||
{
|
||||
struct pci_dev *dev = HWIF(drive)->pci_dev;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = hwif->pci_dev;
|
||||
struct hpt_info *info = ide_get_hwifdata(hwif);
|
||||
u8 speed = hpt3xx_ratefilter(drive, xferspeed);
|
||||
// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);
|
||||
u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51;
|
||||
u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51;
|
||||
u8 drive_pci = 0x40 + (drive->dn * 4);
|
||||
u8 new_fast = 0, drive_fast = 0;
|
||||
u32 list_conf = 0, drive_conf = 0;
|
||||
|
@ -693,17 +677,13 @@ 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,
|
||||
(struct chipset_bus_clock_list_entry *)
|
||||
pci_get_drvdata(dev));
|
||||
list_conf = pci_bus_clock_list(speed, info->speed);
|
||||
|
||||
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);
|
||||
|
@ -711,10 +691,11 @@ static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
|
|||
|
||||
static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
|
||||
{
|
||||
struct pci_dev *dev = HWIF(drive)->pci_dev;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = hwif->pci_dev;
|
||||
struct hpt_info *info = ide_get_hwifdata(hwif);
|
||||
u8 speed = hpt3xx_ratefilter(drive, xferspeed);
|
||||
// u8 speed = ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);
|
||||
u8 regfast = (HWIF(drive)->channel) ? 0x55 : 0x51;
|
||||
u8 regfast = (drive->hwif->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;
|
||||
|
@ -726,10 +707,8 @@ 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,
|
||||
(struct chipset_bus_clock_list_entry *)
|
||||
pci_get_drvdata(dev));
|
||||
|
||||
list_conf = pci_bus_clock_list(speed, info->speed);
|
||||
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)
|
||||
|
@ -741,19 +720,14 @@ static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
|
|||
|
||||
static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed)
|
||||
{
|
||||
struct pci_dev *dev = HWIF(drive)->pci_dev;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct hpt_info *info = ide_get_hwifdata(hwif);
|
||||
|
||||
if (hpt_minimum_revision(dev, 8))
|
||||
if (info->revision >= 8)
|
||||
return hpt372_tune_chipset(drive, speed); /* not a typo */
|
||||
#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))
|
||||
else if (info->revision >= 5)
|
||||
return hpt372_tune_chipset(drive, speed);
|
||||
else if (hpt_minimum_revision(dev, 3))
|
||||
else if (info->revision >= 3)
|
||||
return hpt370_tune_chipset(drive, speed);
|
||||
else /* hpt368: hpt_minimum_revision(dev, 2) */
|
||||
return hpt36x_tune_chipset(drive, speed);
|
||||
|
@ -779,8 +753,14 @@ 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))
|
||||
if (!speed)
|
||||
return 0;
|
||||
|
||||
/* If we don't have any timings we can't do a lot */
|
||||
if (info->speed == NULL)
|
||||
return 0;
|
||||
|
||||
(void) hpt3xx_tune_chipset(drive, speed);
|
||||
|
@ -794,7 +774,7 @@ static int hpt3xx_quirkproc (ide_drive_t *drive)
|
|||
|
||||
static void hpt3xx_intrproc (ide_drive_t *drive)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
||||
if (drive->quirk_list)
|
||||
return;
|
||||
|
@ -804,24 +784,26 @@ static void hpt3xx_intrproc (ide_drive_t *drive)
|
|||
|
||||
static void hpt3xx_maskproc (ide_drive_t *drive, int mask)
|
||||
{
|
||||
struct pci_dev *dev = HWIF(drive)->pci_dev;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct hpt_info *info = ide_get_hwifdata(hwif);
|
||||
struct pci_dev *dev = hwif->pci_dev;
|
||||
|
||||
if (drive->quirk_list) {
|
||||
if (hpt_minimum_revision(dev,3)) {
|
||||
if (info->revision >= 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(drive)->irq);
|
||||
disable_irq(hwif->irq);
|
||||
} else {
|
||||
enable_irq(HWIF(drive)->irq);
|
||||
enable_irq(hwif->irq);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (IDE_CONTROL_REG)
|
||||
HWIF(drive)->OUTB(mask ? (drive->ctl | 2) :
|
||||
hwif->OUTB(mask ? (drive->ctl | 2) :
|
||||
(drive->ctl & ~2),
|
||||
IDE_CONTROL_REG);
|
||||
}
|
||||
|
@ -829,12 +811,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 = HWIF(drive);
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct hd_driveid *id = drive->id;
|
||||
|
||||
drive->init_speed = 0;
|
||||
|
||||
if (id && (id->capability & 1) && drive->autodma) {
|
||||
if ((id->capability & 1) && drive->autodma) {
|
||||
|
||||
if (ide_use_dma(drive)) {
|
||||
if (config_chipset_for_dma(drive))
|
||||
|
@ -868,15 +850,6 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -919,7 +892,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("%s: %d bytes in FIFO\n", drive->name, bfifo);
|
||||
printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo);
|
||||
hpt370_clear_engine(drive);
|
||||
/* get dma command mode */
|
||||
dma_cmd = hwif->INB(hwif->dma_command);
|
||||
|
@ -1047,15 +1020,6 @@ 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)
|
||||
|
@ -1065,8 +1029,6 @@ 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);
|
||||
|
||||
|
@ -1093,7 +1055,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 = HWIF(drive);
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
struct pci_dev *dev = hwif->pci_dev;
|
||||
u8 tristate = 0, resetmask = 0, bus_reg = 0;
|
||||
u16 tri_reg;
|
||||
|
@ -1148,33 +1110,44 @@ static int hpt370_busproc(ide_drive_t * drive, int state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit init_hpt37x(struct pci_dev *dev)
|
||||
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)
|
||||
{
|
||||
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.
|
||||
* 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 ?
|
||||
*/
|
||||
pci_write_config_byte(dev, 0x5b, 0x23);
|
||||
|
||||
|
@ -1197,9 +1170,7 @@ static int __devinit init_hpt37x(struct pci_dev *dev)
|
|||
* Currently we always set up the PLL for the 372N
|
||||
*/
|
||||
|
||||
pci_set_drvdata(dev, NULL);
|
||||
|
||||
if(is_372n)
|
||||
if(info->flags & IS_372N)
|
||||
{
|
||||
printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n");
|
||||
if(freq < 0x55)
|
||||
|
@ -1227,39 +1198,38 @@ static int __devinit init_hpt37x(struct pci_dev *dev)
|
|||
pll = F_LOW_PCI_66;
|
||||
|
||||
if (pll == F_LOW_PCI_33) {
|
||||
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);
|
||||
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;
|
||||
else
|
||||
pci_set_drvdata(dev, (void *) thirty_three_base_hpt370);
|
||||
printk("HPT37X: using 33MHz PCI clock\n");
|
||||
info->speed = thirty_three_base_hpt370;
|
||||
printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n");
|
||||
} else if (pll == F_LOW_PCI_40) {
|
||||
/* Unsupported */
|
||||
} else if (pll == F_LOW_PCI_50) {
|
||||
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);
|
||||
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;
|
||||
else
|
||||
pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
|
||||
printk("HPT37X: using 50MHz PCI clock\n");
|
||||
info->speed = fifty_base_hpt370a;
|
||||
printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n");
|
||||
} else {
|
||||
if (hpt_minimum_revision(dev,8))
|
||||
{
|
||||
if (info->revision >= 8) {
|
||||
printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
|
||||
}
|
||||
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 if (info->revision >= 5)
|
||||
info->speed = sixty_six_base_hpt372;
|
||||
else if (info->revision >= 4)
|
||||
info->speed = sixty_six_base_hpt370a;
|
||||
else
|
||||
pci_set_drvdata(dev, (void *) sixty_six_base_hpt370);
|
||||
printk("HPT37X: using 66MHz PCI clock\n");
|
||||
info->speed = sixty_six_base_hpt370;
|
||||
printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1269,11 +1239,19 @@ static int __devinit init_hpt37x(struct pci_dev *dev)
|
|||
* 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 (pci_get_drvdata(dev))
|
||||
if (info->speed)
|
||||
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.
|
||||
*/
|
||||
|
@ -1298,14 +1276,14 @@ static int __devinit init_hpt37x(struct pci_dev *dev)
|
|||
pci_write_config_dword(dev, 0x5c,
|
||||
pll & ~0x100);
|
||||
pci_write_config_byte(dev, 0x5b, 0x21);
|
||||
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);
|
||||
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;
|
||||
else
|
||||
pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
|
||||
info->speed = fifty_base_hpt370a;
|
||||
printk("HPT37X: using 50MHz internal PLL\n");
|
||||
goto init_hpt37X_done;
|
||||
}
|
||||
|
@ -1318,10 +1296,22 @@ pll_recal:
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1338,59 +1328,27 @@ 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;
|
||||
u8 test = 0;
|
||||
|
||||
/* FIXME: Not portable */
|
||||
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_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));
|
||||
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_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)) {
|
||||
if (hpt_revision(dev) >= 3)
|
||||
ret = init_hpt37x(dev);
|
||||
} else {
|
||||
ret =init_hpt366(dev);
|
||||
}
|
||||
else
|
||||
ret = init_hpt366(dev);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -1400,27 +1358,16 @@ 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(is_372n)
|
||||
if(info->flags & IS_372N)
|
||||
hwif->rw_disk = &hpt372n_rw_disk;
|
||||
|
||||
/*
|
||||
|
@ -1428,7 +1375,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 (hpt_minimum_revision(dev, 8) && PCI_FUNC(dev->devfn) & 1) {
|
||||
if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) {
|
||||
/*
|
||||
* HPT374 PCI function 1
|
||||
* - set bit 15 of reg 0x52 to enable TCBLID as input
|
||||
|
@ -1443,7 +1390,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 (hpt_minimum_revision(dev, 3)) {
|
||||
} else if (info->revision >= 3) {
|
||||
/*
|
||||
* HPT370/372 and 374 pcifn 0
|
||||
* - clear bit 0 of 0x5b to enable P/SCBLID as inputs
|
||||
|
@ -1470,7 +1417,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
|
|||
hwif->serialized = hwif->mate->serialized = 1;
|
||||
#endif
|
||||
|
||||
if (hpt_minimum_revision(dev,3)) {
|
||||
if (info->revision >= 3) {
|
||||
u8 reg5ah = 0;
|
||||
pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
|
||||
/*
|
||||
|
@ -1480,8 +1427,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
|
|||
*/
|
||||
hwif->resetproc = &hpt3xx_reset;
|
||||
hwif->busproc = &hpt370_busproc;
|
||||
// hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
|
||||
} else if (hpt_minimum_revision(dev,2)) {
|
||||
} else if (info->revision >= 2) {
|
||||
hwif->resetproc = &hpt3xx_reset;
|
||||
hwif->busproc = &hpt3xx_tristate;
|
||||
} else {
|
||||
|
@ -1502,18 +1448,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 (hpt_minimum_revision(dev,8)) {
|
||||
if (info->revision >= 8) {
|
||||
hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
|
||||
hwif->ide_dma_end = &hpt374_ide_dma_end;
|
||||
} else if (hpt_minimum_revision(dev,5)) {
|
||||
} else if (info->revision >= 5) {
|
||||
hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
|
||||
hwif->ide_dma_end = &hpt374_ide_dma_end;
|
||||
} else if (hpt_minimum_revision(dev,3)) {
|
||||
} else if (info->revision >= 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 (hpt_minimum_revision(dev,2))
|
||||
} else if (info->revision >= 2)
|
||||
hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
|
||||
else
|
||||
hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
|
||||
|
@ -1526,6 +1472,7 @@ 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;
|
||||
|
@ -1535,8 +1482,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
|
|||
if (!dmabase)
|
||||
return;
|
||||
|
||||
if(pci_get_drvdata(hwif->pci_dev) == NULL)
|
||||
{
|
||||
if(info->speed == NULL) {
|
||||
printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n");
|
||||
return;
|
||||
}
|
||||
|
@ -1559,6 +1505,40 @@ 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;
|
||||
|
@ -1646,6 +1626,7 @@ 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,
|
||||
|
@ -1656,6 +1637,7 @@ 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,
|
||||
|
@ -1665,6 +1647,7 @@ 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,
|
||||
|
@ -1674,6 +1657,7 @@ 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,
|
||||
|
@ -1683,6 +1667,7 @@ 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 */
|
||||
|
@ -1692,6 +1677,7 @@ 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 */
|
||||
|
|
|
@ -0,0 +1,812 @@
|
|||
|
||||
/*
|
||||
* linux/drivers/ide/pci/it821x.c Version 0.09 December 2004
|
||||
*
|
||||
* Copyright (C) 2004 Red Hat <alan@redhat.com>
|
||||
*
|
||||
* 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 <linux/config.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/ide.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
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");
|
|
@ -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 __init ata66_svwks_svwks (ide_hwif_t *hwif)
|
||||
static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -454,7 +454,7 @@ static unsigned int __init 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 __init ata66_svwks_dell (ide_hwif_t *hwif)
|
||||
static unsigned int __devinit 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 __init ata66_svwks_dell (ide_hwif_t *hwif)
|
|||
*
|
||||
* WARNING: this only works on Alpine hardware!
|
||||
*/
|
||||
static unsigned int __init ata66_svwks_cobalt (ide_hwif_t *hwif)
|
||||
static unsigned int __devinit 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 __init ata66_svwks_cobalt (ide_hwif_t *hwif)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int __init ata66_svwks (ide_hwif_t *hwif)
|
||||
static unsigned int __devinit 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 __init init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d)
|
||||
static int __devinit init_setup_csb6 (struct pci_dev *dev, ide_pci_device_t *d)
|
||||
{
|
||||
if (!(PCI_FUNC(dev->devfn) & 1)) {
|
||||
d->bootable = NEVER_BOARD;
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/gameport.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
/*#include <asm/io.h>*/
|
||||
|
||||
|
@ -238,8 +237,7 @@ 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 DECLARE_COMPLETION(gameport_exited);
|
||||
static int gameport_pid;
|
||||
static struct task_struct *gameport_task;
|
||||
|
||||
static void gameport_queue_event(void *object, struct module *owner,
|
||||
enum gameport_event_type event_type)
|
||||
|
@ -250,12 +248,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)
|
||||
|
@ -432,20 +430,15 @@ 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, !list_empty(&gameport_event_list));
|
||||
wait_event_interruptible(gameport_wait,
|
||||
kthread_should_stop() || !list_empty(&gameport_event_list));
|
||||
try_to_freeze();
|
||||
} while (!signal_pending(current));
|
||||
} while (!kthread_should_stop());
|
||||
|
||||
printk(KERN_DEBUG "gameport: kgameportd exiting\n");
|
||||
|
||||
unlock_kernel();
|
||||
complete_and_exit(&gameport_exited, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -773,9 +766,10 @@ void gameport_close(struct gameport *gameport)
|
|||
|
||||
static int __init gameport_init(void)
|
||||
{
|
||||
if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) {
|
||||
gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
|
||||
if (IS_ERR(gameport_task)) {
|
||||
printk(KERN_ERR "gameport: Failed to start kgameportd\n");
|
||||
return -1;
|
||||
return PTR_ERR(gameport_task);
|
||||
}
|
||||
|
||||
gameport_bus.dev_attrs = gameport_device_attrs;
|
||||
|
@ -789,8 +783,7 @@ static int __init gameport_init(void)
|
|||
static void __exit gameport_exit(void)
|
||||
{
|
||||
bus_unregister(&gameport_bus);
|
||||
kill_proc(gameport_pid, SIGTERM, 1);
|
||||
wait_for_completion(&gameport_exited);
|
||||
kthread_stop(gameport_task);
|
||||
}
|
||||
|
||||
module_init(gameport_init);
|
||||
|
|
|
@ -31,10 +31,9 @@
|
|||
#include <linux/serio.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
||||
MODULE_DESCRIPTION("Serio abstraction core");
|
||||
|
@ -43,6 +42,7 @@ 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,6 +68,37 @@ 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) {
|
||||
|
@ -91,7 +122,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 (drv->connect(serio, drv)) {
|
||||
if (serio_connect_driver(serio, drv)) {
|
||||
serio->dev.driver = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -138,8 +169,7 @@ 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 DECLARE_COMPLETION(serio_exited);
|
||||
static int serio_pid;
|
||||
static struct task_struct *serio_task;
|
||||
|
||||
static void serio_queue_event(void *object, struct module *owner,
|
||||
enum serio_event_type event_type)
|
||||
|
@ -150,12 +180,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)
|
||||
|
@ -337,20 +367,15 @@ 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, !list_empty(&serio_event_list));
|
||||
wait_event_interruptible(serio_wait,
|
||||
kthread_should_stop() || !list_empty(&serio_event_list));
|
||||
try_to_freeze();
|
||||
} while (!signal_pending(current));
|
||||
} while (!kthread_should_stop());
|
||||
|
||||
printk(KERN_DEBUG "serio: kseriod exiting\n");
|
||||
|
||||
unlock_kernel();
|
||||
complete_and_exit(&serio_exited, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -557,7 +582,7 @@ static void serio_destroy_port(struct serio *serio)
|
|||
static void serio_reconnect_port(struct serio *serio)
|
||||
{
|
||||
do {
|
||||
if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
|
||||
if (serio_reconnect_driver(serio)) {
|
||||
serio_disconnect_port(serio);
|
||||
serio_find_driver(serio);
|
||||
/* Ok, old children are now gone, we are done */
|
||||
|
@ -629,6 +654,19 @@ 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
|
||||
|
@ -686,15 +724,14 @@ 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 drv->connect(serio, drv);
|
||||
return serio_connect_driver(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);
|
||||
|
||||
drv->disconnect(serio);
|
||||
serio_disconnect_driver(serio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -730,11 +767,9 @@ start_over:
|
|||
|
||||
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)
|
||||
|
@ -794,7 +829,7 @@ static int serio_resume(struct device *dev)
|
|||
{
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
|
||||
if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
|
||||
if (serio_reconnect_driver(serio)) {
|
||||
/*
|
||||
* Driver re-probing can take a while, so better let kseriod
|
||||
* deal with it.
|
||||
|
@ -848,9 +883,10 @@ irqreturn_t serio_interrupt(struct serio *serio,
|
|||
|
||||
static int __init serio_init(void)
|
||||
{
|
||||
if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) {
|
||||
serio_task = kthread_run(serio_thread, NULL, "kseriod");
|
||||
if (IS_ERR(serio_task)) {
|
||||
printk(KERN_ERR "serio: Failed to start kseriod\n");
|
||||
return -1;
|
||||
return PTR_ERR(serio_task);
|
||||
}
|
||||
|
||||
serio_bus.dev_attrs = serio_device_attrs;
|
||||
|
@ -866,8 +902,7 @@ static int __init serio_init(void)
|
|||
static void __exit serio_exit(void)
|
||||
{
|
||||
bus_unregister(&serio_bus);
|
||||
kill_proc(serio_pid, SIGTERM, 1);
|
||||
wait_for_completion(&serio_exited);
|
||||
kthread_stop(serio_task);
|
||||
}
|
||||
|
||||
module_init(serio_init);
|
||||
|
|
|
@ -486,6 +486,14 @@ 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 = {
|
||||
|
@ -493,6 +501,7 @@ static struct pcmcia_driver avmcs_driver = {
|
|||
},
|
||||
.attach = avmcs_attach,
|
||||
.detach = avmcs_detach,
|
||||
.id_table = avmcs_ids,
|
||||
};
|
||||
|
||||
static int __init avmcs_init(void)
|
||||
|
|
|
@ -501,6 +501,13 @@ 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 = {
|
||||
|
@ -508,6 +515,7 @@ static struct pcmcia_driver avma1cs_driver = {
|
|||
},
|
||||
.attach = avma1cs_attach,
|
||||
.detach = avma1cs_detach,
|
||||
.id_table = avma1cs_ids,
|
||||
};
|
||||
|
||||
/*====================================================================*/
|
||||
|
|
|
@ -508,6 +508,13 @@ 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 = {
|
||||
|
@ -515,6 +522,7 @@ 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)
|
||||
|
|
|
@ -616,6 +616,18 @@ 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 = {
|
||||
|
@ -623,6 +635,7 @@ static struct pcmcia_driver sedlbauer_driver = {
|
|||
},
|
||||
.attach = sedlbauer_attach,
|
||||
.detach = sedlbauer_detach,
|
||||
.id_table = sedlbauer_ids,
|
||||
};
|
||||
|
||||
static int __init init_sedlbauer_cs(void)
|
||||
|
|
|
@ -489,6 +489,12 @@ 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 = {
|
||||
|
@ -496,6 +502,7 @@ static struct pcmcia_driver teles_cs_driver = {
|
|||
},
|
||||
.attach = teles_attach,
|
||||
.detach = teles_detach,
|
||||
.id_table = teles_ids,
|
||||
};
|
||||
|
||||
static int __init init_teles_cs(void)
|
||||
|
|
|
@ -607,6 +607,16 @@ 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
|
||||
|
|
|
@ -818,6 +818,32 @@ 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 = {
|
||||
|
@ -825,7 +851,8 @@ static struct pcmcia_driver pcmciamtd_driver = {
|
|||
},
|
||||
.attach = pcmciamtd_attach,
|
||||
.detach = pcmciamtd_detach,
|
||||
.owner = THIS_MODULE
|
||||
.owner = THIS_MODULE,
|
||||
.id_table = pcmciamtd_ids,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1286,6 +1286,13 @@ 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 = {
|
||||
|
@ -1293,6 +1300,7 @@ static struct pcmcia_driver tc574_driver = {
|
|||
},
|
||||
.attach = tc574_attach,
|
||||
.detach = tc574_detach,
|
||||
.id_table = tc574_ids,
|
||||
};
|
||||
|
||||
static int __init init_tc574(void)
|
||||
|
|
|
@ -1057,6 +1057,17 @@ 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 = {
|
||||
|
@ -1064,6 +1075,7 @@ static struct pcmcia_driver tc589_driver = {
|
|||
},
|
||||
.attach = tc589_attach,
|
||||
.detach = tc589_detach,
|
||||
.id_table = tc589_ids,
|
||||
};
|
||||
|
||||
static int __init init_tc589(void)
|
||||
|
|
|
@ -850,6 +850,34 @@ 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 = {
|
||||
|
@ -857,6 +885,7 @@ static struct pcmcia_driver axnet_cs_driver = {
|
|||
},
|
||||
.attach = axnet_attach,
|
||||
.detach = axnet_detach,
|
||||
.id_table = axnet_ids,
|
||||
};
|
||||
|
||||
static int __init init_axnet_cs(void)
|
||||
|
|
|
@ -483,7 +483,11 @@ 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,
|
||||
|
@ -492,6 +496,7 @@ static struct pcmcia_driver com20020_cs_driver = {
|
|||
},
|
||||
.attach = com20020_attach,
|
||||
.detach = com20020_detach,
|
||||
.id_table = com20020_ids,
|
||||
};
|
||||
|
||||
static int __init init_com20020_cs(void)
|
||||
|
|
|
@ -435,7 +435,9 @@ 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) {
|
||||
} 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) {
|
||||
/* MultiFunction Card */
|
||||
link->conf.ConfigBase = 0x800;
|
||||
link->conf.ConfigIndex = 0x47;
|
||||
|
@ -764,6 +766,31 @@ 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 = {
|
||||
|
@ -771,6 +798,7 @@ static struct pcmcia_driver fmvj18x_cs_driver = {
|
|||
},
|
||||
.attach = fmvj18x_attach,
|
||||
.detach = fmvj18x_detach,
|
||||
.id_table = fmvj18x_ids,
|
||||
};
|
||||
|
||||
static int __init init_fmvj18x_cs(void)
|
||||
|
|
|
@ -508,6 +508,13 @@ 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 = {
|
||||
|
@ -515,6 +522,7 @@ static struct pcmcia_driver ibmtr_cs_driver = {
|
|||
},
|
||||
.attach = ibmtr_attach,
|
||||
.detach = ibmtr_detach,
|
||||
.id_table = ibmtr_ids,
|
||||
};
|
||||
|
||||
static int __init init_ibmtr_cs(void)
|
||||
|
|
|
@ -1675,6 +1675,13 @@ 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 = {
|
||||
|
@ -1682,6 +1689,7 @@ static struct pcmcia_driver nmclan_cs_driver = {
|
|||
},
|
||||
.attach = nmclan_attach,
|
||||
.detach = nmclan_detach,
|
||||
.id_table = nmclan_ids,
|
||||
};
|
||||
|
||||
static int __init init_nmclan_cs(void)
|
||||
|
|
|
@ -1637,6 +1637,208 @@ failed:
|
|||
|
||||
/*====================================================================*/
|
||||
|
||||
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",
|
||||
|
@ -1644,6 +1846,7 @@ 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)
|
||||
|
|
|
@ -2327,6 +2327,38 @@ 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 = {
|
||||
|
@ -2334,6 +2366,7 @@ static struct pcmcia_driver smc91c92_cs_driver = {
|
|||
},
|
||||
.attach = smc91c92_attach,
|
||||
.detach = smc91c92_detach,
|
||||
.id_table = smc91c92_ids,
|
||||
};
|
||||
|
||||
static int __init init_smc91c92_cs(void)
|
||||
|
|
|
@ -1983,6 +1983,33 @@ 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 = {
|
||||
|
@ -1990,6 +2017,7 @@ static struct pcmcia_driver xirc2ps_cs_driver = {
|
|||
},
|
||||
.attach = xirc2ps_attach,
|
||||
.detach = xirc2ps_detach,
|
||||
.id_table = xirc2ps_ids,
|
||||
};
|
||||
|
||||
static int __init
|
||||
|
|
|
@ -559,6 +559,15 @@ 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 = {
|
||||
|
@ -566,6 +575,7 @@ static struct pcmcia_driver airo_driver = {
|
|||
},
|
||||
.attach = airo_attach,
|
||||
.detach = airo_detach,
|
||||
.id_table = airo_ids,
|
||||
};
|
||||
|
||||
static int airo_cs_init(void)
|
||||
|
|
|
@ -646,6 +646,27 @@ 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 = {
|
||||
|
@ -653,6 +674,7 @@ static struct pcmcia_driver atmel_driver = {
|
|||
},
|
||||
.attach = atmel_attach,
|
||||
.detach = atmel_detach,
|
||||
.id_table = atmel_ids,
|
||||
};
|
||||
|
||||
static int atmel_cs_init(void)
|
||||
|
|
|
@ -1668,6 +1668,12 @@ 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 = {
|
||||
|
@ -1675,6 +1681,7 @@ static struct pcmcia_driver netwave_driver = {
|
|||
},
|
||||
.attach = netwave_attach,
|
||||
.detach = netwave_detach,
|
||||
.id_table = netwave_ids,
|
||||
};
|
||||
|
||||
static int __init init_netwave_cs(void)
|
||||
|
|
|
@ -608,6 +608,56 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
|
|||
" (David Gibson <hermes@gibson.dropbear.id.au>, "
|
||||
"Pavel Roskin <proski@gnu.org>, 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 = {
|
||||
|
@ -615,6 +665,7 @@ static struct pcmcia_driver orinoco_driver = {
|
|||
},
|
||||
.attach = orinoco_cs_attach,
|
||||
.detach = orinoco_cs_detach,
|
||||
.id_table = orinoco_cs_ids,
|
||||
};
|
||||
|
||||
static int __init
|
||||
|
|
|
@ -2904,6 +2904,12 @@ 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 = {
|
||||
|
@ -2911,6 +2917,7 @@ static struct pcmcia_driver ray_driver = {
|
|||
},
|
||||
.attach = ray_attach,
|
||||
.detach = ray_detach,
|
||||
.id_table = ray_ids,
|
||||
};
|
||||
|
||||
static int __init init_ray_cs(void)
|
||||
|
|
|
@ -4895,6 +4895,15 @@ 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 = {
|
||||
|
@ -4902,6 +4911,7 @@ static struct pcmcia_driver wavelan_driver = {
|
|||
},
|
||||
.attach = wavelan_attach,
|
||||
.detach = wavelan_detach,
|
||||
.id_table = wavelan_ids,
|
||||
};
|
||||
|
||||
static int __init
|
||||
|
|
|
@ -2240,6 +2240,12 @@ 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 = {
|
||||
|
@ -2247,6 +2253,7 @@ static struct pcmcia_driver wl3501_driver = {
|
|||
},
|
||||
.attach = wl3501_attach,
|
||||
.detach = wl3501_detach,
|
||||
.id_table = wl3501_ids,
|
||||
};
|
||||
|
||||
static int __init wl3501_init_module(void)
|
||||
|
|
|
@ -373,6 +373,13 @@ 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 = {
|
||||
|
@ -380,6 +387,8 @@ static struct pcmcia_driver parport_cs_driver = {
|
|||
},
|
||||
.attach = parport_attach,
|
||||
.detach = parport_detach,
|
||||
.id_table = parport_ids,
|
||||
|
||||
};
|
||||
|
||||
static int __init init_parport_cs(void)
|
||||
|
|
|
@ -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: the older 16 bit PCMCIA cards
|
||||
and the newer 32 bit CardBus cards.
|
||||
actually two varieties of these cards: 16 bit PCMCIA and 32 bit
|
||||
CardBus cards.
|
||||
|
||||
To compile this driver as modules, choose M here: the
|
||||
module will be called pcmcia_core.
|
||||
|
@ -42,22 +42,51 @@ 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 from
|
||||
David Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
|
||||
for location). Please also read the PCMCIA-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>.
|
||||
To use 16-bit PCMCIA cards, you will need supporting software in
|
||||
most cases. (see the file <file:Documentation/Changes> for
|
||||
location and details).
|
||||
|
||||
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
|
||||
|
@ -77,8 +106,6 @@ 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---
|
||||
|
|
|
@ -10,7 +10,8 @@ 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-y += ds.o pcmcia_compat.o pcmcia_resource.o
|
||||
pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o
|
||||
obj-$(CONFIG_PCMCIA) += pcmcia.o
|
||||
|
||||
obj-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o
|
||||
|
|
|
@ -89,8 +89,10 @@ 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 = find_mem_region(0, s->map_size, s->map_size, 0, s);
|
||||
mem->res = pcmcia_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;
|
||||
|
@ -99,7 +101,12 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
|
|||
}
|
||||
mem->card_start = card_offset;
|
||||
mem->flags = flags;
|
||||
s->ops->set_mem_map(s, mem);
|
||||
ret = s->ops->set_mem_map(s, mem);
|
||||
if (ret) {
|
||||
iounmap(s->cis_virt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (s->features & SS_CAP_STATIC_MAP) {
|
||||
if (s->cis_virt)
|
||||
iounmap(s->cis_virt);
|
||||
|
@ -119,13 +126,13 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
|
|||
#define IS_ATTR 1
|
||||
#define IS_INDIRECT 8
|
||||
|
||||
int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
|
||||
int pcmcia_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, "read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
|
||||
cs_dbg(s, 3, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
|
||||
|
||||
if (attr & IS_INDIRECT) {
|
||||
/* Indirect accesses use a bunch of special registers at fixed
|
||||
|
@ -182,14 +189,16 @@ int 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 write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
|
||||
|
||||
void pcmcia_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, "write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
|
||||
cs_dbg(s, 3, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
|
||||
|
||||
if (attr & IS_INDIRECT) {
|
||||
/* Indirect accesses use a bunch of special registers at fixed
|
||||
|
@ -239,6 +248,8 @@ void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
|
|||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(pcmcia_write_cis_mem);
|
||||
|
||||
|
||||
/*======================================================================
|
||||
|
||||
|
@ -274,7 +285,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 = read_cis_mem(s, attr, addr, len, ptr);
|
||||
ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr);
|
||||
|
||||
if (ret == 0) {
|
||||
/* Copy data into the cache */
|
||||
|
@ -348,7 +359,7 @@ int verify_cis_cache(struct pcmcia_socket *s)
|
|||
read_cb_mem(s, cis->attr, cis->addr, len, buf);
|
||||
else
|
||||
#endif
|
||||
read_cis_mem(s, cis->attr, cis->addr, len, buf);
|
||||
pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);
|
||||
|
||||
if (memcmp(buf, cis->cache, len) != 0) {
|
||||
kfree(buf);
|
||||
|
@ -381,6 +392,7 @@ 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);
|
||||
|
||||
/*======================================================================
|
||||
|
||||
|
|
1164
drivers/pcmcia/cs.c
1164
drivers/pcmcia/cs.c
File diff suppressed because it is too large
Load Diff
|
@ -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 read_cis_mem(struct pcmcia_socket *s, int attr,
|
||||
int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr,
|
||||
u_int addr, u_int len, void *ptr);
|
||||
void write_cis_mem(struct pcmcia_socket *s, int attr,
|
||||
void pcmcia_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,13 +134,12 @@ 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 *find_io_region(unsigned long base, int num, unsigned long align,
|
||||
struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align,
|
||||
struct pcmcia_socket *s);
|
||||
int adjust_io_region(struct resource *res, unsigned long r_start,
|
||||
int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start,
|
||||
unsigned long r_end, struct pcmcia_socket *s);
|
||||
struct resource *find_mem_region(u_long base, u_long num, u_long align,
|
||||
struct resource *pcmcia_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 */
|
||||
|
@ -159,7 +158,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);
|
||||
int (*resources_done) (struct pcmcia_socket *s);
|
||||
void (*requery) (struct pcmcia_socket *s);
|
||||
};
|
||||
|
||||
int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
|
||||
|
|
1271
drivers/pcmcia/ds.c
1271
drivers/pcmcia/ds.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,21 @@
|
|||
/* 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
|
|
@ -669,11 +669,13 @@ 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)) &&
|
||||
(check_region(start, stop-start+1) != 0) &&
|
||||
((start & 0xfeef) != 0x02e8))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
((start & 0xfeef) != 0x02e8)) {
|
||||
if (!request_region(start, stop-start+1, "i82365"))
|
||||
return 1;
|
||||
release_region(start, stop-start+1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*====================================================================*/
|
||||
|
@ -696,7 +698,13 @@ static void __init add_pcic(int ns, int type)
|
|||
struct i82365_socket *t = &socket[sockets-ns];
|
||||
|
||||
base = sockets-ns;
|
||||
if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365");
|
||||
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 (base == 0) printk("\n");
|
||||
printk(KERN_INFO " %s", pcic[type].name);
|
||||
|
@ -803,7 +811,7 @@ static void __init isa_probe(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (check_region(i365_base, 2) != 0) {
|
||||
if (!request_region(i365_base, 2, "i82365")) {
|
||||
if (sockets == 0)
|
||||
printk("port conflict at %#lx\n", i365_base);
|
||||
return;
|
||||
|
@ -1441,6 +1449,7 @@ 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);
|
||||
|
|
|
@ -74,19 +74,6 @@ 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)
|
||||
{
|
||||
|
@ -102,24 +89,3 @@ 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);
|
||||
|
||||
|
|
|
@ -0,0 +1,786 @@
|
|||
/*
|
||||
* 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
|
||||
* <dahinds@users.sourceforge.net>. 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 <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define IN_CARD_SERVICES
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ds.h>
|
||||
#include <pcmcia/ss.h>
|
||||
|
||||
#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");
|
||||
}
|
|
@ -0,0 +1,998 @@
|
|||
/*
|
||||
* PCMCIA 16-bit resource management functions
|
||||
*
|
||||
* The initial developer of the original code is David A. Hinds
|
||||
* <dahinds@users.sourceforge.net>. 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 <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#define IN_CARD_SERVICES
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/ss.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/bulkmem.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/cisreg.h>
|
||||
#include <pcmcia/ds.h>
|
||||
|
||||
#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<<lines : 0) : 1;
|
||||
if (align && (align < num)) {
|
||||
if (*base) {
|
||||
ds_dbg(s, 0, "odd IO request: num %#x align %#lx\n",
|
||||
num, align);
|
||||
align = 0;
|
||||
} else
|
||||
while (align && (align < num)) align <<= 1;
|
||||
}
|
||||
if (*base & ~(align-1)) {
|
||||
ds_dbg(s, 0, "odd IO request: base %#x align %#lx\n",
|
||||
*base, align);
|
||||
align = 0;
|
||||
}
|
||||
if ((s->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);
|
|
@ -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_done) &&
|
||||
if ((s->resource_setup_new) &&
|
||||
!(s->resource_setup_old)) {
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
continue;
|
||||
|
@ -105,29 +105,32 @@ void pcmcia_validate_mem(struct pcmcia_socket *s)
|
|||
}
|
||||
EXPORT_SYMBOL(pcmcia_validate_mem);
|
||||
|
||||
int adjust_io_region(struct resource *res, unsigned long r_start,
|
||||
int pcmcia_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 *find_io_region(unsigned long base, int num,
|
||||
struct resource *pcmcia_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 *find_mem_region(u_long base, u_long num, u_long align,
|
||||
struct resource *pcmcia_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)
|
||||
{
|
||||
|
|
|
@ -372,6 +372,9 @@ 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;
|
||||
|
@ -465,8 +468,7 @@ 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;
|
||||
if (do_mem_probe(mm.base, mm.num, s))
|
||||
break;
|
||||
do_mem_probe(mm.base, mm.num, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,7 +603,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
|
|||
|
||||
======================================================================*/
|
||||
|
||||
struct resource *nonstatic_find_io_region(unsigned long base, int num,
|
||||
static 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);
|
||||
|
@ -635,8 +637,8 @@ struct resource *nonstatic_find_io_region(unsigned long base, int num,
|
|||
return res;
|
||||
}
|
||||
|
||||
struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long align,
|
||||
int low, struct pcmcia_socket *s)
|
||||
static 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;
|
||||
|
@ -683,27 +685,23 @@ struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long alig
|
|||
}
|
||||
|
||||
|
||||
static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj)
|
||||
static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
|
||||
{
|
||||
u_long base, num;
|
||||
struct socket_data *data = s->resource_data;
|
||||
int ret;
|
||||
unsigned long size = end - start + 1;
|
||||
int ret = 0;
|
||||
|
||||
base = adj->resource.memory.Base;
|
||||
num = adj->resource.memory.Size;
|
||||
if ((num == 0) || (base+num-1 < base))
|
||||
return CS_BAD_SIZE;
|
||||
|
||||
ret = CS_SUCCESS;
|
||||
if (end <= start)
|
||||
return -EINVAL;
|
||||
|
||||
down(&rsrc_sem);
|
||||
switch (adj->Action) {
|
||||
switch (action) {
|
||||
case ADD_MANAGED_RESOURCE:
|
||||
ret = add_interval(&data->mem_db, base, num);
|
||||
ret = add_interval(&data->mem_db, start, size);
|
||||
break;
|
||||
case REMOVE_MANAGED_RESOURCE:
|
||||
ret = sub_interval(&data->mem_db, base, num);
|
||||
if (ret == CS_SUCCESS) {
|
||||
ret = sub_interval(&data->mem_db, start, size);
|
||||
if (!ret) {
|
||||
struct pcmcia_socket *socket;
|
||||
down_read(&pcmcia_socket_list_rwsem);
|
||||
list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
|
||||
|
@ -712,7 +710,7 @@ static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
ret = CS_UNSUPPORTED_FUNCTION;
|
||||
ret = -EINVAL;
|
||||
}
|
||||
up(&rsrc_sem);
|
||||
|
||||
|
@ -720,36 +718,35 @@ static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj)
|
|||
}
|
||||
|
||||
|
||||
static int adjust_io(struct pcmcia_socket *s, adjust_t *adj)
|
||||
static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
|
||||
{
|
||||
struct socket_data *data = s->resource_data;
|
||||
kio_addr_t base, num;
|
||||
int ret = CS_SUCCESS;
|
||||
unsigned long size = end - start + 1;
|
||||
int ret = 0;
|
||||
|
||||
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;
|
||||
if (end <= start)
|
||||
return -EINVAL;
|
||||
|
||||
if (end > IO_SPACE_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
down(&rsrc_sem);
|
||||
switch (adj->Action) {
|
||||
switch (action) {
|
||||
case ADD_MANAGED_RESOURCE:
|
||||
if (add_interval(&data->io_db, base, num) != 0) {
|
||||
ret = CS_IN_USE;
|
||||
if (add_interval(&data->io_db, start, size) != 0) {
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_PCMCIA_PROBE
|
||||
if (probe_io)
|
||||
do_io_probe(s, base, num);
|
||||
do_io_probe(s, start, size);
|
||||
#endif
|
||||
break;
|
||||
case REMOVE_MANAGED_RESOURCE:
|
||||
sub_interval(&data->io_db, base, num);
|
||||
sub_interval(&data->io_db, start, size);
|
||||
break;
|
||||
default:
|
||||
ret = CS_UNSUPPORTED_FUNCTION;
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
up(&rsrc_sem);
|
||||
|
@ -760,15 +757,82 @@ static int adjust_io(struct pcmcia_socket *s, adjust_t *adj)
|
|||
|
||||
static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj)
|
||||
{
|
||||
unsigned long end;
|
||||
|
||||
switch (adj->Resource) {
|
||||
case RES_MEMORY_RANGE:
|
||||
return adjust_memory(s, adj);
|
||||
end = adj->resource.memory.Base + adj->resource.memory.Size - 1;
|
||||
return adjust_memory(s, adj->Action, adj->resource.memory.Base, end);
|
||||
case RES_IO_RANGE:
|
||||
return adjust_io(s, adj);
|
||||
end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1;
|
||||
return adjust_io(s, adj->Action, adj->resource.io.BasePort, end);
|
||||
}
|
||||
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;
|
||||
|
@ -783,6 +847,8 @@ static int nonstatic_init(struct pcmcia_socket *s)
|
|||
|
||||
s->resource_data = (void *) data;
|
||||
|
||||
nonstatic_autoadd_resources(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -845,17 +911,16 @@ 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 = 1;
|
||||
adjust_t adj;
|
||||
unsigned int add = ADD_MANAGED_RESOURCE;
|
||||
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 = 0;
|
||||
add = REMOVE_MANAGED_RESOURCE;
|
||||
if (ret != 2) {
|
||||
ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr);
|
||||
add = 1;
|
||||
add = ADD_MANAGED_RESOURCE;
|
||||
if (ret != 2)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -863,12 +928,9 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size
|
|||
if (end_addr <= start_addr)
|
||||
return -EINVAL;
|
||||
|
||||
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);
|
||||
ret = adjust_io(s, add, start_addr, end_addr);
|
||||
if (!ret)
|
||||
s->resource_setup_new = 1;
|
||||
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
@ -901,17 +963,16 @@ 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 = 1;
|
||||
adjust_t adj;
|
||||
unsigned int add = ADD_MANAGED_RESOURCE;
|
||||
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 = 0;
|
||||
add = REMOVE_MANAGED_RESOURCE;
|
||||
if (ret != 2) {
|
||||
ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr);
|
||||
add = 1;
|
||||
add = ADD_MANAGED_RESOURCE;
|
||||
if (ret != 2)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -919,12 +980,9 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz
|
|||
if (end_addr <= start_addr)
|
||||
return -EINVAL;
|
||||
|
||||
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);
|
||||
ret = adjust_memory(s, add, start_addr, end_addr);
|
||||
if (!ret)
|
||||
s->resource_setup_new = 1;
|
||||
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
|
|
@ -163,30 +163,166 @@ 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->resources_done(s);
|
||||
module_put(s->callback->owner);
|
||||
}
|
||||
}
|
||||
up(&s->skt_sem);
|
||||
|
||||
return count;
|
||||
}
|
||||
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);
|
||||
|
||||
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) &&
|
||||
!(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 (ret);
|
||||
}
|
||||
|
||||
|
||||
static struct class_device_attribute *pccard_socket_attributes[] = {
|
||||
&class_device_attr_card_type,
|
||||
&class_device_attr_card_voltage,
|
||||
|
@ -199,6 +335,13 @@ 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;
|
||||
|
@ -209,6 +352,8 @@ 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;
|
||||
}
|
||||
|
@ -217,6 +362,7 @@ 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);
|
||||
}
|
||||
|
|
|
@ -549,6 +549,11 @@ 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)
|
||||
|
@ -556,7 +561,6 @@ 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;
|
||||
|
|
|
@ -318,6 +318,16 @@ 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 = {
|
||||
|
@ -325,6 +335,7 @@ static struct pcmcia_driver aha152x_cs_driver = {
|
|||
},
|
||||
.attach = aha152x_attach,
|
||||
.detach = aha152x_detach,
|
||||
.id_table = aha152x_ids,
|
||||
};
|
||||
|
||||
static int __init init_aha152x_cs(void)
|
||||
|
|
|
@ -299,6 +299,15 @@ 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 = {
|
||||
|
@ -306,6 +315,7 @@ static struct pcmcia_driver fdomain_cs_driver = {
|
|||
},
|
||||
.attach = fdomain_attach,
|
||||
.detach = fdomain_detach,
|
||||
.id_table = fdomain_ids,
|
||||
};
|
||||
|
||||
static int __init init_fdomain_cs(void)
|
||||
|
|
|
@ -2125,6 +2125,18 @@ 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 = {
|
||||
|
@ -2132,6 +2144,7 @@ static struct pcmcia_driver nsp_driver = {
|
|||
},
|
||||
.attach = nsp_cs_attach,
|
||||
.detach = nsp_cs_detach,
|
||||
.id_table = nsp_cs_ids,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -395,6 +395,27 @@ 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,
|
||||
|
@ -403,6 +424,7 @@ static struct pcmcia_driver qlogic_cs_driver = {
|
|||
},
|
||||
.attach = qlogic_attach,
|
||||
.detach = qlogic_detach,
|
||||
.id_table = qlogic_ids,
|
||||
};
|
||||
|
||||
static int __init init_qlogic_cs(void)
|
||||
|
|
|
@ -999,6 +999,14 @@ MODULE_AUTHOR("Bob Tracy <rct@frus.com>");
|
|||
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 = {
|
||||
|
@ -1006,6 +1014,7 @@ static struct pcmcia_driver sym53c500_cs_driver = {
|
|||
},
|
||||
.attach = SYM53C500_attach,
|
||||
.detach = SYM53C500_detach,
|
||||
.id_table = sym53c500_ids,
|
||||
};
|
||||
|
||||
static int __init
|
||||
|
|
|
@ -772,6 +772,111 @@ 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 = {
|
||||
|
@ -779,6 +884,7 @@ static struct pcmcia_driver serial_cs_driver = {
|
|||
},
|
||||
.attach = serial_attach,
|
||||
.detach = serial_detach,
|
||||
.id_table = serial_ids,
|
||||
};
|
||||
|
||||
static int __init init_serial_cs(void)
|
||||
|
|
|
@ -295,6 +295,12 @@ 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 = {
|
||||
|
@ -302,6 +308,7 @@ static struct pcmcia_driver ixj_driver = {
|
|||
},
|
||||
.attach = ixj_attach,
|
||||
.detach = ixj_detach,
|
||||
.id_table = ixj_ids,
|
||||
};
|
||||
|
||||
static int __init ixj_pcmcia_init(void)
|
||||
|
|
|
@ -68,13 +68,6 @@ 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;
|
||||
|
@ -373,7 +366,7 @@ static dev_link_t *sl811_cs_attach(void)
|
|||
local_info_t *local;
|
||||
dev_link_t *link;
|
||||
client_reg_t client_reg;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
|
||||
if (!local)
|
||||
|
@ -385,11 +378,6 @@ 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;
|
||||
|
@ -418,6 +406,12 @@ 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 = {
|
||||
|
@ -425,6 +419,7 @@ static struct pcmcia_driver sl811_cs_driver = {
|
|||
},
|
||||
.attach = sl811_cs_attach,
|
||||
.detach = sl811_cs_detach,
|
||||
.id_table = sl811_ids,
|
||||
};
|
||||
|
||||
/*====================================================================*/
|
||||
|
|
|
@ -41,13 +41,17 @@ 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;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@
|
|||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
extern void __iomem *auxio_register;
|
||||
|
||||
#define AUXIO_LTE_ON 1
|
||||
#define AUXIO_LTE_OFF 0
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
char *pdma_vaddr;
|
||||
unsigned char *pdma_vaddr;
|
||||
unsigned long pdma_size;
|
||||
volatile int doing_pdma = 0;
|
||||
|
||||
|
@ -209,8 +209,7 @@ static void sun_fd_enable_dma(void)
|
|||
pdma_areasize = pdma_size;
|
||||
}
|
||||
|
||||
/* Our low-level entry point in arch/sparc/kernel/entry.S */
|
||||
extern irqreturn_t floppy_hardint(int irq, void *unused, struct pt_regs *regs);
|
||||
extern irqreturn_t sparc_floppy_irq(int, void *, struct pt_regs *);
|
||||
|
||||
static int sun_fd_request_irq(void)
|
||||
{
|
||||
|
@ -220,8 +219,8 @@ static int sun_fd_request_irq(void)
|
|||
if(!once) {
|
||||
once = 1;
|
||||
|
||||
error = request_fast_irq(FLOPPY_IRQ, floppy_hardint,
|
||||
SA_INTERRUPT, "floppy", NULL);
|
||||
error = request_irq(FLOPPY_IRQ, sparc_floppy_irq,
|
||||
SA_INTERRUPT, "floppy", NULL);
|
||||
|
||||
return ((error == 0) ? 0 : -1);
|
||||
}
|
||||
|
@ -615,7 +614,7 @@ static unsigned long __init sun_floppy_init(void)
|
|||
struct linux_ebus *ebus;
|
||||
struct linux_ebus_device *edev = NULL;
|
||||
unsigned long config = 0;
|
||||
unsigned long auxio_reg;
|
||||
void __iomem *auxio_reg;
|
||||
|
||||
for_each_ebus(ebus) {
|
||||
for_each_ebusdev(edev, ebus) {
|
||||
|
@ -642,7 +641,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 = edev->resource[2].start;
|
||||
auxio_reg = (void __iomem *) edev->resource[2].start;
|
||||
writel(readl(auxio_reg)|0x2, auxio_reg);
|
||||
|
||||
sun_pci_ebus_dev = ebus->self;
|
||||
|
@ -650,7 +649,8 @@ 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 = edev->resource[1].start;
|
||||
sun_pci_fd_ebus_dma.regs = (void __iomem *)
|
||||
edev->resource[1].start;
|
||||
if (!sun_pci_fd_ebus_dma.regs)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -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
|
||||
* SBUS/floppy interrupt handler in entry.S -DaveM
|
||||
* the vectored interrupt trap handler in entry.S -DaveM
|
||||
*
|
||||
* This is currently one DCACHE line, two buckets per L2 cache
|
||||
* line. Keep this in mind please.
|
||||
|
@ -122,11 +122,6 @@ 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"
|
||||
|
|
|
@ -55,8 +55,9 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore\n\t"
|
||||
" nop\n\t"
|
||||
"mov %%g7, %0\n\t"
|
||||
: "=&r" (tmp)
|
||||
: "0" (tmp), "r" (sem)
|
||||
|
|
|
@ -52,12 +52,14 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore\n"
|
||||
" nop\n"
|
||||
" .subsection 2\n"
|
||||
"2: ldub [%1], %0\n"
|
||||
" membar #LoadLoad\n"
|
||||
" brnz,pt %0, 2b\n"
|
||||
" membar #LoadLoad\n"
|
||||
" nop\n"
|
||||
" ba,a,pt %%xcc, 1b\n"
|
||||
" .previous"
|
||||
: "=&r" (tmp)
|
||||
|
@ -95,16 +97,18 @@ static inline void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
|
|||
|
||||
__asm__ __volatile__(
|
||||
"1: ldstub [%2], %0\n"
|
||||
" brnz,pn %0, 2f\n"
|
||||
" membar #StoreLoad | #StoreStore\n"
|
||||
" brnz,pn %0, 2f\n"
|
||||
" nop\n"
|
||||
" .subsection 2\n"
|
||||
"2: rdpr %%pil, %1\n"
|
||||
" wrpr %3, %%pil\n"
|
||||
"3: ldub [%2], %0\n"
|
||||
" brnz,pt %0, 3b\n"
|
||||
" membar #LoadLoad\n"
|
||||
" brnz,pt %0, 3b\n"
|
||||
" nop\n"
|
||||
" ba,pt %%xcc, 1b\n"
|
||||
" wrpr %1, %%pil\n"
|
||||
" wrpr %1, %%pil\n"
|
||||
" .previous"
|
||||
: "=&r" (tmp1), "=&r" (tmp2)
|
||||
: "r"(lock), "r"(flags)
|
||||
|
@ -162,12 +166,14 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore\n"
|
||||
" nop\n"
|
||||
" .subsection 2\n"
|
||||
"2: ldsw [%2], %0\n"
|
||||
" membar #LoadLoad\n"
|
||||
" brlz,pt %0, 2b\n"
|
||||
" membar #LoadLoad\n"
|
||||
" nop\n"
|
||||
" ba,a,pt %%xcc, 4b\n"
|
||||
" .previous"
|
||||
: "=&r" (tmp1), "=&r" (tmp2)
|
||||
|
@ -204,12 +210,14 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore\n"
|
||||
" nop\n"
|
||||
" .subsection 2\n"
|
||||
"2: lduw [%2], %0\n"
|
||||
" membar #LoadLoad\n"
|
||||
" brnz,pt %0, 2b\n"
|
||||
" membar #LoadLoad\n"
|
||||
" nop\n"
|
||||
" ba,a,pt %%xcc, 4b\n"
|
||||
" .previous"
|
||||
: "=&r" (tmp1), "=&r" (tmp2)
|
||||
|
@ -240,8 +248,9 @@ 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"
|
||||
" membar #StoreLoad | #StoreStore\n"
|
||||
" nop\n"
|
||||
" mov 1, %2\n"
|
||||
"2:"
|
||||
: "=&r" (tmp1), "=&r" (tmp2), "=&r" (result)
|
||||
|
|
|
@ -111,7 +111,6 @@ 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
|
||||
|
|
|
@ -175,4 +175,50 @@ 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 */
|
||||
|
|
|
@ -1815,6 +1815,8 @@
|
|||
#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
|
||||
|
||||
|
|
|
@ -112,6 +112,8 @@
|
|||
|
||||
#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
|
||||
|
|
|
@ -396,7 +396,6 @@ 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);
|
||||
|
@ -417,7 +416,6 @@ 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);
|
||||
|
|
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* Copyright (2003-2004) Dominik Brodowski <linux@brodo.de>
|
||||
* 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, }
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
#include <pcmcia/bulkmem.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/device_id.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
typedef struct tuple_parse_t {
|
||||
tuple_t tuple;
|
||||
|
@ -129,12 +131,11 @@ 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;
|
||||
};
|
||||
|
||||
|
@ -173,7 +174,9 @@ struct pcmcia_device {
|
|||
u8 has_manf_id:1;
|
||||
u8 has_card_id:1;
|
||||
u8 has_func_id:1;
|
||||
u8 reserved:5;
|
||||
|
||||
u8 allow_func_id_match:1;
|
||||
u8 reserved:4;
|
||||
|
||||
u8 func_id;
|
||||
u16 manf_id;
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
#ifndef _LINUX_SS_H
|
||||
#define _LINUX_SS_H
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/bulkmem.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
/* Definitions for card status flags for GetStatus */
|
||||
#define SS_WRPROT 0x0001
|
||||
|
@ -171,7 +173,7 @@ typedef struct window_t {
|
|||
|
||||
struct config_t;
|
||||
struct pcmcia_callback;
|
||||
|
||||
struct user_info_t;
|
||||
|
||||
struct pcmcia_socket {
|
||||
struct module *owner;
|
||||
|
@ -216,8 +218,9 @@ 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:6;
|
||||
u8 reserved:5;
|
||||
|
||||
/* socket operations */
|
||||
struct pccard_operations * ops;
|
||||
|
@ -241,9 +244,32 @@ 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;
|
||||
|
|
|
@ -287,6 +287,42 @@ 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)
|
||||
{
|
||||
|
@ -362,6 +398,9 @@ 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 */
|
||||
|
|
|
@ -380,13 +380,20 @@ 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
|
||||
.detach = snd_pdacf_detach,
|
||||
.id_table = snd_pdacf_ids,
|
||||
};
|
||||
|
||||
static int __init init_pdacf(void)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue