diff options
-rw-r--r-- | drivers/dahdi/wct4xxp/base.c | 266 |
1 files changed, 186 insertions, 80 deletions
diff --git a/drivers/dahdi/wct4xxp/base.c b/drivers/dahdi/wct4xxp/base.c index 809a122..ab1c8e4 100644 --- a/drivers/dahdi/wct4xxp/base.c +++ b/drivers/dahdi/wct4xxp/base.c @@ -212,6 +212,7 @@ static int altab[] = { #define FLAG_3RDGEN (1 << 7) #define FLAG_BURST (1 << 8) #define FLAG_EXPRESS (1 << 9) +#define FLAG_5THGEN (1 << 10) #define CANARY 0xc0de @@ -223,6 +224,12 @@ struct devtype { unsigned int flags; }; +static struct devtype wct420p5 = { "Wildcard TE420 (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_EXPRESS }; +static struct devtype wct410p5 = { "Wildcard TE410P (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN }; +static struct devtype wct405p5 = { "Wildcard TE405P (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN }; +static struct devtype wct220p5 = { "Wildcard TE220 (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT | FLAG_EXPRESS }; +static struct devtype wct210p5 = { "Wildcard TE210P (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; +static struct devtype wct205p5 = { "Wildcard TE205P (5th Gen)", FLAG_5THGEN | FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; static struct devtype wct4xxp = { "Wildcard TE410P/TE405P (1st Gen)", 0 }; static struct devtype wct420p4 = { "Wildcard TE420 (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_EXPRESS }; static struct devtype wct410p4 = { "Wildcard TE410P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN }; @@ -308,7 +315,7 @@ struct t4 { #endif int irq; /* IRQ used by device */ int order; /* Order */ - int flags; /* Device flags */ + unsigned int falc31 : 1; /* are we falc v3.1 (atomic not necessary) */ int master; /* Are we master */ int ledreg; /* LED Register */ unsigned int gpio; @@ -396,7 +403,8 @@ static void t4_hdlc_hard_xmit(struct dahdi_chan *chan); static int t4_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data); static void t4_tsi_assign(struct t4 *wc, int fromspan, int fromchan, int tospan, int tochan); static void t4_tsi_unassign(struct t4 *wc, int tospan, int tochan); -static void __t4_set_timing_source(struct t4 *wc, int unit, int master, int slave); +static void __t4_set_rclk_src(struct t4 *wc, int span); +static void __t4_set_sclk_src(struct t4 *wc, int mode, int master, int slave); static void t4_check_alarms(struct t4 *wc, int span); static void t4_check_sigbits(struct t4 *wc, int span); @@ -425,6 +433,9 @@ static void t4_check_sigbits(struct t4 *wc, int span); #define WC_GREEN (2) #define WC_YELLOW (3) +#define WC_RECOVER 0 +#define WC_SELF 1 + #define MAX_T4_CARDS 64 static void t4_isr_bh(unsigned long data); @@ -548,6 +559,8 @@ static inline unsigned int __t4_framer_in(struct t4 *wc, int unit, const unsigne } ret = __t4_pci_in(wc, WC_LDATA); __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); + if (unlikely(debug & DEBUG_REGS)) + printk(KERN_INFO "Reading unit %d address %02x is %02x\n", unit, addr, ret & 0xff); return ret & 0xff; } @@ -1748,9 +1761,15 @@ static void t4_serial_setup(struct t4 *wc, int unit) /* Configure ports */ t4_framer_out(wc, unit, 0x80, 0x00); /* PC1: SPYR/SPYX input on RPA/XPA */ - t4_framer_out(wc, unit, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */ - t4_framer_out(wc, unit, 0x82, 0x65); /* PC3: Some unused stuff */ - t4_framer_out(wc, unit, 0x83, 0x35); /* PC4: Some more unused stuff */ + if (wc->falc31) { + t4_framer_out(wc, unit, 0x81, 0xBB); /* PC2: RMFB/XSIG output/input on RPB/XPB */ + t4_framer_out(wc, unit, 0x82, 0xBB); /* PC3: Some unused stuff */ + t4_framer_out(wc, unit, 0x83, 0xBB); /* PC4: Some more unused stuff */ + } else { + t4_framer_out(wc, unit, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */ + t4_framer_out(wc, unit, 0x82, 0x65); /* PC3: Some unused stuff */ + t4_framer_out(wc, unit, 0x83, 0x35); /* PC4: Some more unused stuff */ + } t4_framer_out(wc, unit, 0x84, 0x01); /* PC5: XMFS active low, SCLKR is input, RCLK is output */ if (debug & DEBUG_MAIN) printk(KERN_DEBUG "Successfully initialized serial bus for unit %d\n", unit); @@ -1765,48 +1784,40 @@ static DEFINE_SPINLOCK(synclock); static spinlock_t synclock = SPIN_LOCK_UNLOCKED; #endif -static void __t4_set_timing_source(struct t4 *wc, int unit, int master, int slave) +static void __t4_set_rclk_src(struct t4 *wc, int span) { - unsigned int timing; - int x; - if (unit != wc->syncsrc) { - timing = 0x34; /* CMR1: RCLK unit, 8.192 Mhz TCLK, RCLK is 8.192 Mhz */ - if ((unit > -1) && (unit < 4)) { - timing |= (unit << 6); - for (x=0;x<wc->numspans;x++) /* set all 4 receive reference clocks to unit */ - __t4_framer_out(wc, x, 0x44, timing); - wc->dmactrl |= (1 << 29); - } else { - for (x=0;x<wc->numspans;x++) /* set each receive reference clock to itself */ - __t4_framer_out(wc, x, 0x44, timing | (x << 6)); - wc->dmactrl &= ~(1 << 29); - } - if (slave) - wc->dmactrl |= (1 << 25); - else - wc->dmactrl &= ~(1 << 25); - if (master) - wc->dmactrl |= (1 << 24); - else - wc->dmactrl &= ~(1 << 24); - __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - if (!master && !slave) - wc->syncsrc = unit; - if ((unit < 0) || (unit > 3)) - unit = 0; - else - unit++; - if (!master && !slave) { - for (x=0;x<wc->numspans;x++) - wc->tspans[x]->span.syncsrc = unit; - } + int cmr1 = 0x38; /* Clock Mode: RCLK sourced by DCO-R1 + by default, Disable Clock-Switching */ + + cmr1 |= (span << 6); + __t4_framer_out(wc, 0, 0x44, cmr1); + + dev_info(&wc->dev->dev, "RCLK source set to span %d\n", span+1); +} + +static void __t4_set_sclk_src(struct t4 *wc, int mode, int master, int slave) +{ + if (slave) { + wc->dmactrl |= (1 << 25); + dev_info(&wc->dev->dev, "SCLK is slaved to timing cable\n"); } else { - if (debug & DEBUG_MAIN) - printk(KERN_DEBUG "TE%dXXP: Timing source already set to %d\n", wc->numspans, unit); + wc->dmactrl &= ~(1 << 25); } -#if 0 - printk(KERN_DEBUG "wct4xxp: Timing source set to %d\n",unit); -#endif + + if (master) { + wc->dmactrl |= (1 << 24); + dev_info(&wc->dev->dev, "SCLK is master to timing cable\n"); + } else { + wc->dmactrl &= ~(1 << 24); + } + + if (mode == WC_RECOVER) + wc->dmactrl |= (1 << 29); /* Recover timing from RCLK */ + + if (mode == WC_SELF) + wc->dmactrl &= ~(1 << 29);/* Provide timing from MCLK */ + + __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); } static inline void __t4_update_timing(struct t4 *wc) @@ -1821,10 +1832,11 @@ static inline void __t4_update_timing(struct t4 *wc) wc->tspans[i]->span.syncsrc = wc->syncsrc; } if (syncnum == wc->num) { - __t4_set_timing_source(wc, syncspan-1, 1, 0); + __t4_set_rclk_src(wc, syncspan-1); + __t4_set_sclk_src(wc, WC_RECOVER, 1, 0); if (debug) printk(KERN_DEBUG "Card %d, using sync span %d, master\n", wc->num, syncspan); } else { - __t4_set_timing_source(wc, syncspan-1, 0, 1); + __t4_set_sclk_src(wc, WC_RECOVER, 0, 1); if (debug) printk(KERN_DEBUG "Card %d, using Timing Bus, NOT master\n", wc->num); } } @@ -1890,22 +1902,60 @@ found: static void __t4_set_timing_source_auto(struct t4 *wc) { int x; - printk(KERN_INFO "timing source auto card %d!\n", wc->num); + int firstprio, secondprio; + firstprio = secondprio = 4; + + dev_info(&wc->dev->dev, "timing source auto\n"); clear_bit(T4_CHECK_TIMING, &wc->checkflag); if (timingcable) { __t4_findsync(wc); } else { + dev_info(&wc->dev->dev, "Evaluating spans for timing source\n"); for (x=0;x<wc->numspans;x++) { - if (wc->tspans[x]->sync) { - if ((wc->tspans[wc->tspans[x]->psync - 1]->span.flags & DAHDI_FLAG_RUNNING) && - !(wc->tspans[wc->tspans[x]->psync - 1]->span.alarms & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE) )) { - /* Valid timing source */ - __t4_set_timing_source(wc, wc->tspans[x]->psync - 1, 0, 0); - return; + if ((wc->tspans[x]->span.flags & DAHDI_FLAG_RUNNING) && + !(wc->tspans[x]->span.alarms & (DAHDI_ALARM_RED | + DAHDI_ALARM_BLUE))) { + dev_info(&wc->dev->dev, "span %d is green : "\ + "syncpos %d\n", + x+1, wc->tspans[x]->syncpos); + if (wc->tspans[x]->syncpos) { + /* Valid rsync source in recovered + timing mode */ + if (firstprio == 4) + firstprio = x; + else if (wc->tspans[x]->syncpos < + wc->tspans[firstprio]->syncpos) + firstprio = x; + } else { + /* Valid rsync source in system timing + mode */ + if (secondprio == 4) + secondprio = x; } } } - __t4_set_timing_source(wc, 4, 0, 0); + if (firstprio != 4) { + wc->syncsrc = firstprio; + __t4_set_rclk_src(wc, firstprio); + __t4_set_sclk_src(wc, WC_RECOVER, 0, 0); + dev_info(&wc->dev->dev, "Recovered timing mode, "\ + "RCLK set to span %d\n", + firstprio+1); + } else if (secondprio != 4) { + wc->syncsrc = -1; + __t4_set_rclk_src(wc, secondprio); + __t4_set_sclk_src(wc, WC_SELF, 0, 0); + dev_info(&wc->dev->dev, "System timing mode, "\ + "RCLK set to span %d\n", + secondprio+1); + } else { + wc->syncsrc = -1; + dev_info(&wc->dev->dev, "All spans in alarm : No valid"\ + "span to source RCLK from\n"); + /* Default rclk to lock with span 1 */ + __t4_set_rclk_src(wc, 0); + __t4_set_sclk_src(wc, WC_SELF, 0, 0); + } } } @@ -1953,6 +2003,15 @@ static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlev __t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ __t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ + if (wc->falc31) { + if (debug) + printk(KERN_INFO "card %d span %d: setting Rtx to 0ohm for T1\n", wc->num, unit); + __t4_framer_out(wc, unit, 0x86, 0x00); /* PC6: set Rtx to 0ohm for T1 */ + + // Hitting the bugfix register to fix errata #3 + __t4_framer_out(wc, unit, 0xbd, 0x05); + } + __t4_framer_out(wc, unit, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */ __t4_framer_out(wc, unit, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ __t4_framer_out(wc, unit, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ @@ -2034,6 +2093,12 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig) __t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ __t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ + if (wc->falc31) { + if (debug) + printk(KERN_INFO "setting Rtx to 7.5ohm for E1\n"); + __t4_framer_out(wc, unit, 0x86, 0x40); /* PC6: turn on 7.5ohm Rtx for E1 */ + } + /* Condition receive line interface for E1 after reset */ __t4_framer_out(wc, unit, 0xbb, 0x17); __t4_framer_out(wc, unit, 0xbc, 0x55); @@ -2103,9 +2168,9 @@ static int t4_startup(struct dahdi_span *span) DAHDI_LIN2X(0,span->chans[i]),DAHDI_CHUNKSIZE); } #endif - /* Force re-evaluation fo timing source */ - if (timingcable) - wc->syncsrc = -1; + /* Force re-evaluation of timing source */ + wc->syncsrc = -1; + set_bit(T4_CHECK_TIMING, &wc->checkflag); if (ts->spantype == TYPE_E1) { /* if this is an E1 card */ __t4_configure_e1(wc, span->offset, span->lineconfig); @@ -2122,7 +2187,6 @@ static int t4_startup(struct dahdi_span *span) wc->spansstarted++; /* enable interrupts */ /* Start DMA, enabling DMA interrupts on read only */ - wc->dmactrl = 1 << 29; #if 0 /* Enable framer only interrupts */ wc->dmactrl |= 1 << 27; @@ -2489,7 +2553,7 @@ static void t4_check_sigbits(struct t4 *wc, int span) static void t4_check_alarms(struct t4 *wc, int span) { - unsigned char c,d; + unsigned char c, d, e; int alarms; int x,j; struct t4_span *ts = wc->tspans[span]; @@ -2561,10 +2625,15 @@ static void t4_check_alarms(struct t4 *wc, int span) alarms |= DAHDI_ALARM_NOTOPEN; } - if (c & 0x20) { /* LOF/LFA */ - if (ts->alarmcount >= alarmdebounce) + if (c & 0x20) { + if (ts->alarmcount >= alarmdebounce) { + + /* Disable Slip Interrupts */ + e = __t4_framer_in(wc, span, 0x17); + __t4_framer_out(wc, span, 0x17, (e|0x03)); + alarms |= DAHDI_ALARM_RED; - else { + } else { if (unlikely(debug && !ts->alarmcount)) { /* starting to debounce LOF/LFA */ printk(KERN_INFO "wct%dxxp: LOF/LFA detected " @@ -2577,9 +2646,13 @@ static void t4_check_alarms(struct t4 *wc, int span) ts->alarmcount = 0; if (c & 0x80) { /* LOS */ - if (ts->losalarmcount >= losalarmdebounce) + if (ts->losalarmcount >= losalarmdebounce) { + /* Disable Slip Interrupts */ + e = __t4_framer_in(wc, span, 0x17); + __t4_framer_out(wc, span, 0x17, (e|0x03)); + alarms |= DAHDI_ALARM_RED; - else { + } else { if (unlikely(debug && !ts->losalarmcount)) { /* starting to debounce LOS */ printk(KERN_INFO "wct%dxxp: LOS detected on " @@ -2619,24 +2692,26 @@ static void t4_check_alarms(struct t4 *wc, int span) /* If receiving alarms, go into Yellow alarm state */ if (alarms && !(ts->spanflags & FLAG_SENDINGYELLOW)) { - unsigned char fmr4; -#if 1 - printk(KERN_INFO "wct%dxxp: Setting yellow alarm on span %d\n", - wc->numspans, span + 1); -#endif /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */ + unsigned char fmr4; fmr4 = __t4_framer_in(wc, span, 0x20); __t4_framer_out(wc, span, 0x20, fmr4 | 0x20); + dev_info(&wc->dev->dev, "Setting yellow alarm span %d\n", + span+1); ts->spanflags |= FLAG_SENDINGYELLOW; } else if ((!alarms) && (ts->spanflags & FLAG_SENDINGYELLOW)) { unsigned char fmr4; -#if 1 - printk(KERN_INFO "wct%dxxp: Clearing yellow alarm on span %d\n", - wc->numspans, span + 1); -#endif /* We manually do yellow alarm to handle RECOVER */ fmr4 = __t4_framer_in(wc, span, 0x20); __t4_framer_out(wc, span, 0x20, fmr4 & ~0x20); + dev_info(&wc->dev->dev, "Clearing yellow alarm span %d\n", + span+1); + + /* Re-enable timing slip interrupts */ + e = __t4_framer_in(wc, span, 0x17); + + __t4_framer_out(wc, span, 0x17, (e & ~(0x03))); + ts->spanflags &= ~FLAG_SENDINGYELLOW; } @@ -2776,7 +2851,9 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span) isr4 = (gis & FRMR_GIS_ISR4) ? t4_framer_in(wc, span, FRMR_ISR4) : 0; if (debug & DEBUG_FRAMER) - printk(KERN_DEBUG "gis: %02x, isr0: %02x, isr1: %02x, isr2: %02x, isr3: %02x, isr4: %02x\n", gis, isr0, isr1, isr2, isr3, isr4); + printk(KERN_DEBUG "gis: %02x, isr0: %02x, isr1: %02x, isr2: "\ + "%02x, isr3: %02x, isr4: %02x, intcount= %u\n", + gis, isr0, isr1, isr2, isr3, isr4, wc->intcount); if (isr0) t4_check_sigbits(wc, span); @@ -2787,8 +2864,10 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span) t4_check_alarms(wc, span); } else { /* T1 checks */ - if (isr2 || (isr3 & 0x08)) + if (isr2 || (isr3 & 0x08)) { + printk("card %d span %d: isr2=%x isr3=%x\n", wc->num, span, isr2, isr3); t4_check_alarms(wc, span); + } } if (!ts->span.alarms) { if ((isr3 & 0x3) || (isr4 & 0xc0)) @@ -3026,7 +3105,7 @@ DAHDI_IRQ_HANDLER(t4_interrupt_gen2) /* Acknowledge any pending interrupts */ t4_pci_out(wc, WC_INTR, 0x00000000); spin_lock(&wc->reglock); - __t4_set_timing_source(wc, 4, 0, 0); + __t4_set_sclk_src(wc, WC_SELF, 0, 0); spin_unlock(&wc->reglock); return IRQ_RETVAL(1); } @@ -3561,7 +3640,7 @@ static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags) static int t4_hardware_init_2(struct t4 *wc) { int x; - unsigned int falcver; + unsigned int regval; if (t4_pci_in(wc, WC_VERSION) >= 0xc01a0165) { wc->tspans[0]->spanflags |= FLAG_OCTOPT; @@ -3570,10 +3649,31 @@ static int t4_hardware_init_2(struct t4 *wc) /* Setup LEDS, take out of reset */ t4_pci_out(wc, WC_LEDS, 0x000000ff); t4_activate(wc); + + /* + * In order to find out the QFALC framer version, we have to temporarily term off compat + * mode and take a peak at VSTR. We turn compat back on when we are done. + */ + if (t4_framer_in(wc, 0, 0x4a) != 0x05) + printk(KERN_INFO "WARNING: FALC framer not intialized in compatibility mode.\n"); + regval = t4_framer_in(wc, 0 ,0xd6); + regval |= (1 << 5); /* set COMP_DIS*/ + t4_framer_out(wc, 0, 0xd6, regval); + if (t4_framer_in(wc, 0, 0x4a) == 0x05) + printk(KERN_INFO "card %d: FALC framer is v2.1 or earlier.\n", wc->num); + else if (t4_framer_in(wc, 0, 0x4a) == 0x20) { + printk(KERN_INFO "card %d: FALC framer is v3.1.\n", wc->num); + wc->falc31 = 1; + } else + printk(KERN_INFO "ERROR: FALC framer version is unknown (VSTR = 0x%02x).\n", + t4_framer_in(wc, 0, 0x4a)); + regval = t4_framer_in(wc, 0 ,0xd6); + regval &= ~(1 << 5); /* clear COMP_DIS*/ + t4_framer_out(wc, 0, 0xd6, regval); t4_framer_out(wc, 0, 0x4a, 0xaa); - falcver = t4_framer_in(wc, 0 ,0x4a); - printk(KERN_INFO "FALC version: %08x, Board ID: %02x\n", falcver, wc->order); + regval = t4_framer_in(wc, 0 ,0x4a); + printk(KERN_INFO "FALC version: %08x, Board ID: %02x\n", regval, wc->order); for (x=0;x< 11;x++) printk(KERN_INFO "Reg %d: 0x%08x\n", x, t4_pci_in(wc, x)); @@ -3619,7 +3719,7 @@ static int __devinit t4_launch(struct t4 *wc) } set_bit(T4_CHECK_TIMING, &wc->checkflag); spin_lock_irqsave(&wc->reglock, flags); - __t4_set_timing_source(wc,4, 0, 0); + __t4_set_sclk_src(wc, WC_SELF, 0, 0); spin_unlock_irqrestore(&wc->reglock, flags); tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc); return 0; @@ -3932,6 +4032,9 @@ static struct pci_device_id t4_pci_tbl[] __devinitdata = { { 0x10ee, 0x0314, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct4xxp }, + { 0xd161, 0x1420, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct420p5 }, + { 0xd161, 0x1410, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p5 }, + { 0xd161, 0x1405, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p5 }, { 0xd161, 0x0420, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct420p4 }, { 0xd161, 0x0410, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p4 }, { 0xd161, 0x0405, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p4 }, @@ -3940,6 +4043,9 @@ static struct pci_device_id t4_pci_tbl[] __devinitdata = { 0xd161, 0x0410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p2 }, { 0xd161, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p2 }, + { 0xd161, 0x1220, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct220p5 }, + { 0xd161, 0x1205, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct205p5 }, + { 0xd161, 0x1210, 0x0005, PCI_ANY_ID, 0, 0, (unsigned long)&wct210p5 }, { 0xd161, 0x0220, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct220p4 }, { 0xd161, 0x0205, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct205p4 }, { 0xd161, 0x0210, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct210p4 }, |