From c077a139b523bc15aae6526be1252d1f56befb0b Mon Sep 17 00:00:00 2001 From: russell Date: Mon, 25 Jul 2005 14:42:56 +0000 Subject: add support for dual span cards git-svn-id: http://svn.digium.com/svn/zaptel/branches/v1-0@704 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- Makefile | 8 +-- wct4xxp.c | 222 ++++++++++++++++++++++++++++++++++++-------------------------- 2 files changed, 135 insertions(+), 95 deletions(-) diff --git a/Makefile b/Makefile index 993a0fb..c1a86de 100755 --- a/Makefile +++ b/Makefile @@ -270,7 +270,6 @@ install: all devices install -D -m 755 sethdlc $(INSTALL_PREFIX)/sbin/sethdlc ; \ fi if [ -f zttool ]; then install -D -m 755 zttool $(INSTALL_PREFIX)/sbin/zttool; fi - if [ -f zaptel.ko ]; then \ for x in $(MODULESKO) ztdummy.ko; do \ install -D -m 644 $$x $(INSTALL_PREFIX)/lib/modules/`uname -r`/misc/$$x ; \ @@ -286,7 +285,6 @@ install: all devices rm -f $(INSTALL_PREFIX)/lib/modules/`uname -r`/misc/wcfxsusb.ko; \ fi; \ fi - install -D -m 755 $(LIBTONEZONE) $(INSTALL_PREFIX)/usr/lib/$(LIBTONEZONE) if [ -x /usr/sbin/sestatus ] && (/usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled") ; then restorecon -v $(INSTALL_PREFIX)/usr/lib/$(LIBTONEZONE); fi install -D -m 644 zaptel.h $(INSTALL_PREFIX)/usr/include/linux/zaptel.h @@ -318,8 +316,10 @@ install: all devices done if ! grep "alias wctdm" $(MODCONF); then \ echo "alias wctdm wcfxs" >> $(MODCONF); \ - fi \ - + fi + if ! grep "alias wct2xxp" $(MODCONF); then \ + echo "alias wct2xxp wct4xxp" >> $(MODCONF); \ + fi if [ -d /etc/modutils ]; then \ /sbin/update-modules ; \ fi diff --git a/wct4xxp.c b/wct4xxp.c index c81b0ae..e951197 100755 --- a/wct4xxp.c +++ b/wct4xxp.c @@ -56,7 +56,7 @@ /* Work queues are a way to better distribute load on SMP systems */ #ifdef LINUX26 -#define ENABLE_WORKQUEUES +#define ENABLE_WORKQUEUES #endif /* Enable prefetching may help performance */ @@ -192,6 +192,7 @@ static int altab[] = { #define TYPE_J1 3 /* is a running J1 */ #define FLAG_2NDGEN (1 << 3) +#define FLAG_2PORT (1 << 4) #define CANARY 0xc0de @@ -203,6 +204,8 @@ struct devtype { static struct devtype wct4xxp = { "Wildcard TE410P/TE405P (1st Gen)", 0 }; static struct devtype wct410p2 = { "Wildcard TE410P (2nd Gen)", FLAG_2NDGEN }; static struct devtype wct405p2 = { "Wildcard TE405P (2nd Gen)", FLAG_2NDGEN }; +static struct devtype wct205 = { "Wildcard TE205P ", FLAG_2NDGEN | FLAG_2PORT }; +static struct devtype wct210 = { "Wildcard TE210P ", FLAG_2NDGEN | FLAG_2PORT }; static int inirq = 0; @@ -256,6 +259,7 @@ struct t4 { int globalconfig; /* Whether global setup has been done */ int syncsrc; /* active sync source */ struct t4_span *tspans[4]; /* Individual spans */ + int numspans; /* Number of spans on the card */ #ifdef VPM_SUPPORT int vpm; #endif @@ -562,6 +566,10 @@ static void __t4_check_vpm(struct t4 *wc, unsigned int newio) energy = ZT_XLAW(energy, ts->chans); ts->dtmfactive |= (1 << base); ts->dtmfenergy[base] = energy; + if (ts->dtmfdigit[base]) { + if (ts->dtmfmask & (1 << base)) + zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base])); + } ts->dtmfdigit[base] = digit; if (ts->dtmfdigit[base]) { if (ts->dtmfmask & (1 << base)) @@ -774,7 +782,7 @@ static int t4_maint(struct zt_span *span, int cmd) printk("XXX Stop sending loop codes E1 XXX\n"); break; default: - printk("TE410P: Unknown E1 maint command: %d\n", cmd); + printk("TE%dXXP: Unknown E1 maint command: %d\n", wc->numspans, cmd); break; } } else { @@ -798,7 +806,7 @@ static int t4_maint(struct zt_span *span, int cmd) t4_framer_out(wc, span->offset, 0x21, 0x40); /* FMR5: Nothing but RBS mode */ break; default: - printk("TE410P: Unknown T1 maint command: %d\n", cmd); + printk("TE%dXXP: Unknown T1 maint command: %d\n", wc->numspans, cmd); break; } } @@ -869,7 +877,7 @@ static int t4_shutdown(struct zt_span *span) tspan = span->offset + 1; if (tspan < 0) { - printk("T4XXP: Span '%d' isn't us?\n", span->spanno); + printk("T%dXXP: Span '%d' isn't us?\n", wc->numspans, span->spanno); return -1; } @@ -880,12 +888,17 @@ static int t4_shutdown(struct zt_span *span) if (wasrunning) wc->spansstarted--; __t4_set_led(wc, span->offset, WC_OFF); - if ((!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) && + if (((wc->numspans == 4) && + (!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) && (!(wc->tspans[1]->span.flags & ZT_FLAG_RUNNING)) && (!(wc->tspans[2]->span.flags & ZT_FLAG_RUNNING)) && - (!(wc->tspans[3]->span.flags & ZT_FLAG_RUNNING))) { + (!(wc->tspans[3]->span.flags & ZT_FLAG_RUNNING))) + || + ((wc->numspans == 2) && + (!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) && + (!(wc->tspans[1]->span.flags & ZT_FLAG_RUNNING)))) { /* No longer in use, disable interrupts */ - printk("TE410P: Disabling interrupts since there are no active spans\n"); + printk("TE%dXXP: Disabling interrupts since there are no active spans\n", wc->numspans); wc->dmactrl = 0x0; __t4_pci_out(wc, WC_DMACTRL, 0x00000000); /* Acknowledge any pending interrupts */ @@ -906,7 +919,7 @@ static int t4_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) printk("About to enter spanconfig!\n"); if (debug & DEBUG_MAIN) - printk("TE410P: Configuring span %d\n", span->spanno); + printk("TE%dXXP: Configuring span %d\n", wc->numspans, span->spanno); /* XXX We assume lineconfig is okay and shouldn't XXX */ span->lineconfig = lc->lineconfig; span->txlevel = lc->lbo; @@ -917,7 +930,7 @@ static int t4_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) lc->sync = 0; /* remove this span number from the current sync sources, if there */ - for(i = 0; i < 4; i++) { + for(i = 0; i < wc->numspans; i++) { if (wc->tspans[i]->sync == span->spanno) { wc->tspans[i]->sync = 0; wc->tspans[i]->psync = 0; @@ -946,9 +959,9 @@ static int t4_chanconfig(struct zt_chan *chan, int sigtype) alreadyrunning = wc->tspans[chan->span->offset]->span.flags & ZT_FLAG_RUNNING; if (debug & DEBUG_MAIN) { if (alreadyrunning) - printk("TE410P: Reconfigured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); + printk("TE%dXXP: Reconfigured channel %d (%s) sigtype %d\n", wc->numspans, chan->channo, chan->name, sigtype); else - printk("TE410P: Configured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); + printk("TE%dXXP: Configured channel %d (%s) sigtype %d\n", wc->numspans, chan->channo, chan->name, sigtype); } spin_lock_irqsave(&wc->reglock, flags); if (alreadyrunning) @@ -988,11 +1001,11 @@ static void init_spans(struct t4 *wc) gen2 = (wc->tspans[0]->spanflags & FLAG_2NDGEN); if (!wc->t1e1) offset += 4; - for (x=0;x<4;x++) { + for (x=0;xnumspans;x++) { ts = wc->tspans[x]; - sprintf(ts->span.name, "TE4/%d/%d", + sprintf(ts->span.name, "TE%d/%d/%d", wc->numspans, wc->num, x + 1); - sprintf(ts->span.desc, "TE410P (PCI) Card %d Span %d", wc->num, x+1); + sprintf(ts->span.desc, "T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, x+1); ts->span.spanconfig = t4_spanconfig; ts->span.chanconfig = t4_chanconfig; ts->span.startup = t4_startup; @@ -1026,7 +1039,7 @@ static void init_spans(struct t4 *wc) init_waitqueue_head(&ts->span.maintq); for (y=0;ytspans[x]->span.channels;y++) { struct zt_chan *mychans = ts->chans + y; - sprintf(mychans->name, "TE4/%d/%d/%d", wc->num, x + 1, y + 1); + sprintf(mychans->name, "TE%d/%d/%d/%d", wc->numspans, wc->num, x + 1, y + 1); mychans->sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_EM_E1 | ZT_SIG_DACS_RBS; c = (x * ts->span.channels) + y; @@ -1044,7 +1057,7 @@ static void t4_serial_setup(struct t4 *wc, int unit) { if (!wc->globalconfig) { wc->globalconfig = 1; - printk("TE410P: Setting up global serial parameters\n"); + printk("TE%dXXP: Setting up global serial parameters\n", wc->numspans); t4_framer_out(wc, 0, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */ t4_framer_out(wc, 0, 0x08, 0x01); /* IPC: Interrupt push/pull active low */ @@ -1100,12 +1113,12 @@ static void __t4_set_timing_source(struct t4 *wc, int unit) 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<4;x++) /* set all 4 receive reference clocks to unit */ + for (x=0;xnumspans;x++) /* set all 4 receive reference clocks to unit */ __t4_framer_out(wc, x, 0x44, timing); wc->dmactrl |= (1 << 29); __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); } else { - for (x=0;x<4;x++) /* set each receive reference clock to itself */ + for (x=0;xnumspans;x++) /* set each receive reference clock to itself */ __t4_framer_out(wc, x, 0x44, timing | (x << 6)); wc->dmactrl &= ~(1 << 29); __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); @@ -1115,11 +1128,11 @@ static void __t4_set_timing_source(struct t4 *wc, int unit) unit = 0; else unit++; - for (x=0;x<4;x++) + for (x=0;xnumspans;x++) wc->tspans[x]->span.syncsrc = unit; } else { if (debug & DEBUG_MAIN) - printk("TE410P: Timing source already set to %d\n", unit); + printk("TE%dXXP: Timing source already set to %d\n", wc->numspans, unit); } #if 0 printk("wct4xxp: Timing source set to %d\n",unit); @@ -1130,7 +1143,7 @@ static void __t4_set_timing_source_auto(struct t4 *wc) { int x; wc->checktiming = 0; - for (x=0;x<4;x++) { + for (x=0;xnumspans;x++) { if (wc->tspans[x]->sync) { if ((wc->tspans[wc->tspans[x]->psync - 1]->span.flags & ZT_FLAG_RUNNING) && !(wc->tspans[wc->tspans[x]->psync - 1]->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE) )) { @@ -1232,7 +1245,7 @@ static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlev __t4_check_sigbits(wc, unit); } - printk("TE410P: Span %d configured for %s/%s\n", unit + 1, framing, line); + printk("TE%dXXP: Span %d configured for %s/%s\n", wc->numspans, unit + 1, framing, line); } static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig) @@ -1318,7 +1331,7 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig) __t4_check_alarms(wc, unit); __t4_check_sigbits(wc, unit); } - printk("TE410P: Span %d configured for %s/%s%s\n", unit + 1, framing, line, crc4); + printk("TE%dXXP: Span %d configured for %s/%s%s\n", wc->numspans, unit + 1, framing, line, crc4); } static int t4_startup(struct zt_span *span) @@ -1335,7 +1348,7 @@ static int t4_startup(struct zt_span *span) printk("About to enter startup!\n"); tspan = span->offset + 1; if (tspan < 0) { - printk("TE410P: Span '%d' isn't us?\n", span->spanno); + printk("TE%dXXP: Span '%d' isn't us?\n", wc->numspans, span->spanno); return -1; } @@ -1394,8 +1407,10 @@ static int t4_startup(struct zt_span *span) spin_unlock_irqrestore(&wc->reglock, flags); if (wc->tspans[0]->sync == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno); if (wc->tspans[1]->sync == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno); - if (wc->tspans[2]->sync == span->spanno) printk("SPAN %d: Tertiary Sync Source\n",span->spanno); - if (wc->tspans[3]->sync == span->spanno) printk("SPAN %d: Quaternary Sync Source\n",span->spanno); + if (wc->numspans == 4) { + if (wc->tspans[2]->sync == span->spanno) printk("SPAN %d: Tertiary Sync Source\n",span->spanno); + if (wc->tspans[3]->sync == span->spanno) printk("SPAN %d: Quaternary Sync Source\n",span->spanno); + } #ifdef VPM_SUPPORT if (!alreadyrunning && !wc->vpm) { wait_a_little(); @@ -1421,7 +1436,9 @@ static inline void e1_check(struct t4 *wc, int span, int val) if (ts->e1check > 100) { /* Wait 1000 ms */ wc->e1recover = 1000 * 8; - wc->tspans[0]->e1check = wc->tspans[1]->e1check = wc->tspans[2]->e1check = wc->tspans[3]->e1check = 0; + wc->tspans[0]->e1check = wc->tspans[1]->e1check = 0; + if (wc->numspans == 4) + wc->tspans[2]->e1check = wc->tspans[3]->e1check = 0; if (debug & DEBUG_MAIN) printk("Detected loss of E1 alignment on span %d!\n", span); t4_reset_dma(wc); @@ -1451,17 +1468,19 @@ static void t4_receiveprep(struct t4 *wc, int irq) wc->last0 = 1; } if (dbl) { - for (x=0;x<4;x++) + for (x=0;xnumspans;x++) wc->tspans[x]->irqmisses++; if (debug & DEBUG_MAIN) - printk("TE410P: Double/missed interrupt detected\n"); + printk("TE%dXXP: Double/missed interrupt detected\n", wc->numspans); } for (x=0;xtspans[3]->span.chans[z].readchunk[x] = tmp & 0xff; - wc->tspans[2]->span.chans[z].readchunk[x] = (tmp & 0xff00) >> 8; + if (wc->numspans == 4) { + wc->tspans[3]->span.chans[z].readchunk[x] = tmp & 0xff; + wc->tspans[2]->span.chans[z].readchunk[x] = (tmp & 0xff00) >> 8; + } wc->tspans[1]->span.chans[z].readchunk[x] = (tmp & 0xff0000) >> 16; wc->tspans[0]->span.chans[z].readchunk[x] = tmp >> 24; } @@ -1469,17 +1488,21 @@ static void t4_receiveprep(struct t4 *wc, int irq) if (wc->e1recover > 0) wc->e1recover--; tmp = readchunk[0]; - e1_check(wc, 3, (tmp & 0x7f)); - e1_check(wc, 2, (tmp & 0x7f00) >> 8); + if (wc->numspans == 4) { + e1_check(wc, 3, (tmp & 0x7f)); + e1_check(wc, 2, (tmp & 0x7f00) >> 8); + } e1_check(wc, 1, (tmp & 0x7f0000) >> 16); e1_check(wc, 0, (tmp & 0x7f000000) >> 24); for (z=24;z<31;z++) { /* Only E1 channels now */ tmp = readchunk[z+1]; - if (wc->tspans[3]->span.channels > 24) - wc->tspans[3]->span.chans[z].readchunk[x] = tmp & 0xff; - if (wc->tspans[2]->span.channels > 24) - wc->tspans[2]->span.chans[z].readchunk[x] = (tmp & 0xff00) >> 8; + if (wc->numspans == 4) { + if (wc->tspans[3]->span.channels > 24) + wc->tspans[3]->span.chans[z].readchunk[x] = tmp & 0xff; + if (wc->tspans[2]->span.channels > 24) + wc->tspans[2]->span.chans[z].readchunk[x] = (tmp & 0xff00) >> 8; + } if (wc->tspans[1]->span.channels > 24) wc->tspans[1]->span.chans[z].readchunk[x] = (tmp & 0xff0000) >> 16; if (wc->tspans[0]->span.channels > 24) @@ -1489,7 +1512,7 @@ static void t4_receiveprep(struct t4 *wc, int irq) /* Advance pointer by 4 TDM frame lengths */ readchunk += 32; } - for (x=0;x<4;x++) { + for (x=0;xnumspans;x++) { if (wc->tspans[x]->span.flags & ZT_FLAG_RUNNING) { for (y=0;ytspans[x]->span.channels;y++) { /* Echo cancel double buffered data */ @@ -1570,7 +1593,7 @@ static void workq_handlespan(void *data) static void t4_prep_gen2(struct t4 *wc) { int x; - for (x=0;x<4;x++) { + for (x=0;xnumspans;x++) { if (wc->tspans[x]->span.flags & ZT_FLAG_RUNNING) { __receive_span(wc->tspans[x]); __transmit_span(wc->tspans[x]); @@ -1594,7 +1617,7 @@ static void t4_transmitprep(struct t4 *wc, int irq) } else { writechunk = wc->writechunk + ZT_CHUNKSIZE * 32 + 1; } - for (y=0;y<4;y++) { + for (y=0;ynumspans;y++) { if (wc->tspans[y]->span.flags & ZT_FLAG_RUNNING) zt_transmit(&wc->tspans[y]->span); } @@ -1613,10 +1636,12 @@ static void t4_transmitprep(struct t4 *wc, int irq) for (z=24;z<31;z++) { /* Only E1 channels now */ tmp = 0; - if (wc->tspans[3]->span.channels > 24) - tmp |= wc->tspans[3]->span.chans[z].writechunk[x]; - if (wc->tspans[2]->span.channels > 24) - tmp |= (wc->tspans[2]->span.chans[z].writechunk[x] << 8); + if (wc->numspans == 4) { + if (wc->tspans[3]->span.channels > 24) + tmp |= wc->tspans[3]->span.chans[z].writechunk[x]; + if (wc->tspans[2]->span.channels > 24) + tmp |= (wc->tspans[2]->span.chans[z].writechunk[x] << 8); + } if (wc->tspans[1]->span.channels > 24) tmp |= (wc->tspans[1]->span.chans[z].writechunk[x] << 16); if (wc->tspans[0]->span.channels > 24) @@ -1798,7 +1823,7 @@ static void __t4_check_alarms(struct t4 *wc, int span) if (alarms && !(ts->spanflags & FLAG_SENDINGYELLOW)) { unsigned char fmr4; #if 1 - printk("wct4xxp: Setting yellow alarm on span %d\n", span + 1); + printk("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 */ fmr4 = __t4_framer_in(wc, span, 0x20); @@ -1807,7 +1832,7 @@ static void __t4_check_alarms(struct t4 *wc, int span) } else if ((!alarms) && (ts->spanflags & FLAG_SENDINGYELLOW)) { unsigned char fmr4; #if 1 - printk("wct4xxp: Clearing yellow alarm on span %d\n", span + 1); + printk("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); @@ -1828,7 +1853,7 @@ static void __t4_check_alarms(struct t4 *wc, int span) static void __t4_do_counters(struct t4 *wc) { int span; - for (span=0;span<4;span++) { + for (span=0;spannumspans;span++) { struct t4_span *ts = wc->tspans[span]; if (ts->alarmtimer) { if (!--ts->alarmtimer) { @@ -1846,7 +1871,7 @@ static inline void __handle_leds(struct t4 *wc) int x; wc->blinktimer++; - for (x=0;x<4;x++) { + for (x=0;xnumspans;x++) { struct t4_span *ts = wc->tspans[x]; if (ts->span.flags & ZT_FLAG_RUNNING) { if (ts->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { @@ -2047,17 +2072,17 @@ static inline void __t4_framer_interrupt(struct t4 *wc, int span) } if (debugslips && !ts->span.alarms) { if (isr3 & 0x02) - printk("TE410P: RECEIVE slip NEGATIVE on span %d\n", span + 1); + printk("TE%d10P: RECEIVE slip NEGATIVE on span %d\n", wc->numspans, span + 1); if (isr3 & 0x01) - printk("TE410P: RECEIVE slip POSITIVE on span %d\n", span + 1); + printk("TE%d10P: RECEIVE slip POSITIVE on span %d\n", wc->numspans, span + 1); if (gis & 0x10) isr4 = __t4_framer_in(wc, span, 0x6c); else isr4 = 0; if (isr4 & 0x80) - printk("TE410P: TRANSMIT slip POSITIVE on span %d\n", span + 1); + printk("TE%dXXP: TRANSMIT slip POSITIVE on span %d\n", wc->numspans, span + 1); if (isr4 & 0x40) - printk("TE410P: TRANSMIT slip NEGATIVE on span %d\n", span + 1); + printk("TE%d10P: TRANSMIT slip NEGATIVE on span %d\n", wc->numspans, span + 1); } } @@ -2115,7 +2140,7 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs) if (status & 0x2) { #ifdef ENABLE_WORKQUEUES int cpus = num_online_cpus(); - atomic_set(&wc->worklist, 4); + atomic_set(&wc->worklist, wc->numspans); if (wc->tspans[0]->span.flags & ZT_FLAG_RUNNING) t4_queue_work(wc->workq, &wc->tspans[0]->swork, 0); else @@ -2124,14 +2149,16 @@ static void t4_interrupt_gen2(int irq, void *dev_id, struct pt_regs *regs) t4_queue_work(wc->workq, &wc->tspans[1]->swork, 1 % cpus); else atomic_dec(&wc->worklist); - if (wc->tspans[2]->span.flags & ZT_FLAG_RUNNING) - t4_queue_work(wc->workq, &wc->tspans[2]->swork, 2 % cpus); - else - atomic_dec(&wc->worklist); - if (wc->tspans[3]->span.flags & ZT_FLAG_RUNNING) - t4_queue_work(wc->workq, &wc->tspans[3]->swork, 3 % cpus); - else - atomic_dec(&wc->worklist); + if (wc->numspans == 4) { + if (wc->tspans[2]->span.flags & ZT_FLAG_RUNNING) + t4_queue_work(wc->workq, &wc->tspans[2]->swork, 2 % cpus); + else + atomic_dec(&wc->worklist); + if (wc->tspans[3]->span.flags & ZT_FLAG_RUNNING) + t4_queue_work(wc->workq, &wc->tspans[3]->swork, 3 % cpus); + else + atomic_dec(&wc->worklist); + } #else t4_prep_gen2(wc); #endif @@ -2423,9 +2450,9 @@ static int t4_hardware_init_1(struct t4 *wc, int gen2) unsigned int version; version = t4_pci_in(wc, WC_VERSION); - printk("TE410P version %08x, burst %s, slip debug: %s\n", version, noburst ? "OFF" : "ON", debugslips ? "ON" : "OFF"); + printk("TE%dXXP version %08x, burst %s, slip debug: %s\n", wc->numspans, version, noburst ? "OFF" : "ON", debugslips ? "ON" : "OFF"); #ifdef ENABLE_WORKQUEUES - printk("TE410P running with work queues.\n"); + printk("TE%dXXP running with work queues.\n", wc->numspans); #endif /* Make sure DMA engine is not running and interrupts are acknowledged */ @@ -2481,10 +2508,10 @@ static int __devinit t4_launch(struct t4 *wc) unsigned long flags; if (wc->tspans[0]->span.flags & ZT_FLAG_REGISTERED) return 0; - printk("TE410P: Launching card: %d\n", wc->order); + printk("TE%dXXP: Launching card: %d\n", wc->numspans, wc->order); /* Setup serial parameters and system interface */ - for (x=0;x<4;x++) + for (x=0;xnumspans;x++) t4_serial_setup(wc, x); if (zt_register(&wc->tspans[0]->span, 0)) { @@ -2496,18 +2523,21 @@ static int __devinit t4_launch(struct t4 *wc) zt_unregister(&wc->tspans[0]->span); return -1; } - if (zt_register(&wc->tspans[2]->span, 0)) { - printk(KERN_ERR "Unable to register span %s\n", wc->tspans[2]->span.name); - zt_unregister(&wc->tspans[0]->span); - zt_unregister(&wc->tspans[1]->span); - return -1; - } - if (zt_register(&wc->tspans[3]->span, 0)) { - printk(KERN_ERR "Unable to register span %s\n", wc->tspans[3]->span.name); - zt_unregister(&wc->tspans[0]->span); - zt_unregister(&wc->tspans[1]->span); - zt_unregister(&wc->tspans[2]->span); - return -1; + + if (wc->numspans == 4) { + if (zt_register(&wc->tspans[2]->span, 0)) { + printk(KERN_ERR "Unable to register span %s\n", wc->tspans[2]->span.name); + zt_unregister(&wc->tspans[0]->span); + zt_unregister(&wc->tspans[1]->span); + return -1; + } + if (zt_register(&wc->tspans[3]->span, 0)) { + printk(KERN_ERR "Unable to register span %s\n", wc->tspans[3]->span.name); + zt_unregister(&wc->tspans[0]->span); + zt_unregister(&wc->tspans[1]->span); + zt_unregister(&wc->tspans[2]->span); + return -1; + } } wc->checktiming = 1; spin_lock_irqsave(&wc->reglock, flags); @@ -2544,6 +2574,12 @@ static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_i basesize = ZT_MAX_CHUNKSIZE * 32 * 4; else basesize = ZT_MAX_CHUNKSIZE * 32 * 2 * 4; + + if (dt->flags & FLAG_2PORT) + wc->numspans = 2; + else + wc->numspans = 4; + wc->variety = dt->desc; wc->memaddr = pci_resource_start(pdev, 0); @@ -2556,9 +2592,9 @@ static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_i printk("wct4: Unable to request memory region :(, using anyway...\n"); #endif if (pci_request_regions(pdev, wc->variety)) - printk("wct4xxp: Unable to request regions\n"); + printk("wct%dxxp: Unable to request regions\n", wc->numspans); - printk("Found TE410P at base address %08lx, remapped to %p\n", wc->memaddr, wc->membase); + printk("Found TE%dXXP at base address %08lx, remapped to %p\n", wc->numspans, wc->memaddr, wc->membase); wc->dev = pdev; @@ -2566,7 +2602,7 @@ static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_i /* 32 channels, Double-buffer, Read/Write, 4 spans */ (unsigned int *)pci_alloc_consistent(pdev, basesize * 2, &wc->writedma); if (!wc->writechunk) { - printk("wct4xxp: Unable to allocate DMA-able memory\n"); + printk("wct%dxxp: Unable to allocate DMA-able memory\n", wc->numspans); return -ENOMEM; } @@ -2611,13 +2647,13 @@ static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_i #ifdef ENABLE_WORKQUEUES if (dt->flags & FLAG_2NDGEN) { char tmp[20]; - sprintf(tmp, "te4xxp[%d]", wc->num); + sprintf(tmp, "te%dxxp[%d]", wc->numspans, wc->num); wc->workq = create_workqueue(tmp); } #endif /* Allocate pieces we need here */ - for (x=0;x<4;x++) { + for (x=0;xnumspans;x++) { if (wc->t1e1 & (1 << x)) { wc->tspans[x] = kmalloc(sizeof(struct t4_span) + sizeof(struct zt_chan) * 31, GFP_KERNEL); if (wc->tspans[x]) { @@ -2648,7 +2684,7 @@ static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_i #ifdef SUPPORT_GEN1 - if (request_irq(pdev->irq, (dt->flags & FLAG_2NDGEN) ? t4_interrupt_gen2 :t4_interrupt, SA_INTERRUPT | SA_SHIRQ, "t4xxp", wc)) + if (request_irq(pdev->irq, (dt->flags & FLAG_2NDGEN) ? t4_interrupt_gen2 :t4_interrupt, SA_INTERRUPT | SA_SHIRQ, (wc->numspans == 2) ? "wct2xxp" : "wct4xxp", wc)) #else if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN)) { printk("This driver does not support 1st gen modules\n"); @@ -2715,7 +2751,7 @@ static int t4_hardware_stop(struct t4 *wc) t4_pci_out(wc, WC_GPIO, 0x0000000); t4_pci_out(wc, WC_LEDS, 0x00000000); - printk("\nStopped TE410P, Turned off DMA\n"); + printk("\nStopped TE%dXXP, Turned off DMA\n", wc->numspans); return 0; } @@ -2732,10 +2768,12 @@ static void __devexit t4_remove_one(struct pci_dev *pdev) zt_unregister(&wc->tspans[0]->span); if (wc->tspans[1]->span.flags & ZT_FLAG_REGISTERED) zt_unregister(&wc->tspans[1]->span); - if (wc->tspans[2]->span.flags & ZT_FLAG_REGISTERED) - zt_unregister(&wc->tspans[2]->span); - if (wc->tspans[3]->span.flags & ZT_FLAG_REGISTERED) - zt_unregister(&wc->tspans[3]->span); + if (wc->numspans == 4) { + if (wc->tspans[2]->span.flags & ZT_FLAG_REGISTERED) + zt_unregister(&wc->tspans[2]->span); + if (wc->tspans[3]->span.flags & ZT_FLAG_REGISTERED) + zt_unregister(&wc->tspans[3]->span); + } #ifdef ENABLE_WORKQUEUES if (wc->workq) { flush_workqueue(wc->workq); @@ -2768,7 +2806,7 @@ static void __devexit t4_remove_one(struct pci_dev *pdev) #endif cards[wc->num] = NULL; pci_set_drvdata(pdev, NULL); - for (x=0;x<4;x++) { + for (x=0;xnumspans;x++) { if (wc->tspans[x]) kfree(wc->tspans[x]); } @@ -2782,11 +2820,13 @@ static struct pci_device_id t4_pci_tbl[] __devinitdata = { 0x10ee, 0x0314, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct4xxp }, { 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, 0x0205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct205 }, + { 0xd161, 0x0210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct210 }, { 0, } }; static struct pci_driver t4_driver = { - name: "t4xxp", + name: "Unified t4xxp/t2xxp driver", probe: t4_init_one, #ifdef LINUX26 remove: __devexit_p(t4_remove_one), @@ -2814,7 +2854,7 @@ static void __exit t4_cleanup(void) MODULE_AUTHOR("Mark Spencer"); -MODULE_DESCRIPTION("TE410P PCI Driver"); +MODULE_DESCRIPTION("Unified TE4XXP/TE2XXP PCI Driver"); #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif -- cgit v1.2.3