[svn-commits] fjoe: freebsd/trunk r8710 - /freebsd/trunk/drivers/dahdi/wcte11xp.c
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Sat May 29 03:22:08 CDT 2010
Author: fjoe
Date: Sat May 29 03:22:06 2010
New Revision: 8710
URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=8710
Log:
Initial FreeBSD port.
Modified:
freebsd/trunk/drivers/dahdi/wcte11xp.c
Modified: freebsd/trunk/drivers/dahdi/wcte11xp.c
URL: http://svnview.digium.com/svn/dahdi/freebsd/trunk/drivers/dahdi/wcte11xp.c?view=diff&rev=8710&r1=8709&r2=8710
==============================================================================
--- freebsd/trunk/drivers/dahdi/wcte11xp.c (original)
+++ freebsd/trunk/drivers/dahdi/wcte11xp.c Sat May 29 03:22:06 2010
@@ -23,6 +23,18 @@
* this program for more details.
*/
+#if defined(__FreeBSD__)
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#define set_current_state(x)
+#else /* !__FreeBSD__ */
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -32,6 +44,7 @@
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/moduleparam.h>
+#endif /* !__FreeBSD__ */
#include <dahdi/kernel.h>
@@ -136,6 +149,9 @@
#endif
struct t1 {
+#if defined(__FreeBSD__)
+ struct pci_dev _dev;
+#endif
struct pci_dev *dev;
spinlock_t lock;
int spantype;
@@ -146,7 +162,7 @@
int alarmdebounce;
/* Our offset for finding channel 1 */
int offset;
- char *variety;
+ const char *variety;
unsigned int intcount;
int usecount;
int clocktimeout;
@@ -168,8 +184,25 @@
unsigned long ioaddr;
unsigned short canary;
/* T1 signalling */
+#if defined(__FreeBSD__)
+ struct resource *io_res;
+ int io_rid;
+
+ struct resource *irq_res; /* resource for irq */
+ int irq_rid;
+ void *irq_handle;
+
+ uint32_t readdma;
+ bus_dma_tag_t read_dma_tag;
+ bus_dmamap_t read_dma_map;
+
+ uint32_t writedma;
+ bus_dma_tag_t write_dma_tag;
+ bus_dmamap_t write_dma_map;
+#else /* !__FreeBSD__ */
dma_addr_t readdma;
dma_addr_t writedma;
+#endif /* !__FreeBSD__ */
volatile unsigned char *writechunk; /* Double-word aligned write memory */
volatile unsigned char *readchunk; /* Double-word aligned read memory */
unsigned char ec_chunk1[32][DAHDI_CHUNKSIZE];
@@ -191,6 +224,39 @@
static struct t1 *cards[WC_MAX_CARDS];
+static inline u8
+t1xxp_inb(struct t1 *wc, int reg)
+{
+#if defined(__FreeBSD__)
+ return bus_space_read_1(rman_get_bustag(wc->io_res),
+ rman_get_bushandle(wc->io_res), reg);
+#else
+ return inb(wc->ioaddr + reg);
+#endif
+}
+
+static inline void
+t1xxp_outb(struct t1 *wc, int reg, u8 value)
+{
+#if defined(__FreeBSD__)
+ bus_space_write_1(rman_get_bustag(wc->io_res),
+ rman_get_bushandle(wc->io_res), reg, value);
+#else
+ outb(value, wc->ioaddr + reg);
+#endif
+}
+
+static inline void
+t1xxp_outl(struct t1 *wc, int reg, u32 value)
+{
+#if defined(__FreeBSD__)
+ bus_space_write_4(rman_get_bustag(wc->io_res),
+ rman_get_bushandle(wc->io_res), reg, value);
+#else
+ outl(value, wc->ioaddr + reg);
+#endif
+}
+
static inline void start_alarm(struct t1 *wc)
{
#ifdef FANCY_ALARM
@@ -213,14 +279,14 @@
wc->outbyte &= ~BIT_CS;
wc->outbyte &= ~BIT_ADDR;
wc->outbyte |= (reg & 0xf0) >> 1;
- outb(wc->outbyte, wc->ioaddr + WC_AUXD);
+ t1xxp_outb(wc, WC_AUXD, wc->outbyte);
}
static inline void __select_control(struct t1 *wc)
{
if (!(wc->outbyte & BIT_CS)) {
wc->outbyte |= BIT_CS;
- outb(wc->outbyte, wc->ioaddr + WC_AUXD);
+ t1xxp_outb(wc, WC_AUXD, wc->outbyte);
}
}
@@ -237,7 +303,7 @@
static int __control_set_reg(struct t1 *wc, int reg, unsigned char val)
{
__select_control(wc);
- outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
+ t1xxp_outb(wc, WC_USERREG + ((reg & 0xf) << 2), val);
return 0;
}
@@ -261,7 +327,7 @@
seems to get rid of the problem */
__control_set_reg(wc,3,0x69); /* do magic here */
/* now get the read byte from the Xilinx part */
- res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
+ res = t1xxp_inb(wc, WC_USERREG + ((reg & 0xf) << 2));
return res;
}
@@ -280,7 +346,7 @@
unsigned char res;
__select_framer(wc, reg);
/* Get value */
- res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
+ res = t1xxp_inb(wc, WC_USERREG + ((reg & 0xf) << 2));
return res;
#if 0
unsigned int ret;
@@ -309,7 +375,7 @@
printk(KERN_DEBUG "Writing %02x to address %02x\n", val, reg);
__select_framer(wc, reg);
/* Send address */
- outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2));
+ t1xxp_outb(wc, WC_USERREG + ((reg & 0xf) << 2), val);
#if 0
__t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff));
__t1_pci_out(wc, WC_LDATA, value);
@@ -363,36 +429,36 @@
static void t1xxp_enable_interrupts(struct t1 *wc)
{
/* Clear interrupts */
- outb(0xff, wc->ioaddr + WC_INTSTAT);
+ t1xxp_outb(wc, WC_INTSTAT, 0xff);
/* Enable interrupts (we care about all of them) */
- outb(0x3c /* 0x3f */, wc->ioaddr + WC_MASK0);
+ t1xxp_outb(wc, WC_MASK0, 0x3c /* 0x3f */);
/* No external interrupts */
- outb(0x00, wc->ioaddr + WC_MASK1);
+ t1xxp_outb(wc, WC_MASK1, 0x00);
if (debug) printk(KERN_DEBUG "Enabled interrupts!\n");
}
static void t1xxp_start_dma(struct t1 *wc)
{
/* Reset Master and TDM */
- outb(DELAY | 0x0f, wc->ioaddr + WC_CNTL);
+ t1xxp_outb(wc, WC_CNTL, DELAY | 0x0f);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
- outb(DELAY | 0x01, wc->ioaddr + WC_CNTL);
- outb(0x01, wc->ioaddr + WC_OPER);
+ t1xxp_outb(wc, WC_CNTL, DELAY | 0x01);
+ t1xxp_outb(wc, WC_OPER, 0x01);
if (debug) printk(KERN_DEBUG "Started DMA\n");
- outb(0x03, wc->ioaddr + WC_OPER);
- outb(0x01, wc->ioaddr + WC_OPER);
+ t1xxp_outb(wc, WC_OPER, 0x03);
+ t1xxp_outb(wc, WC_OPER, 0x01);
}
static void __t1xxp_stop_dma(struct t1 *wc)
{
- outb(0x00, wc->ioaddr + WC_OPER);
+ t1xxp_outb(wc, WC_OPER, 0x00);
}
static void __t1xxp_disable_interrupts(struct t1 *wc)
{
- outb(0x00, wc->ioaddr + WC_MASK0);
- outb(0x00, wc->ioaddr + WC_MASK1);
+ t1xxp_outb(wc, WC_MASK0, 0x00);
+ t1xxp_outb(wc, WC_MASK1, 0x00);
}
static void __t1xxp_set_clear(struct t1 *wc)
@@ -423,12 +489,12 @@
wc = chan->pvt;
for (x=0;x<NUM_PCI;x++)
#if 1
- regs.pci[x] = (inb(wc->ioaddr + (x << 2))) |
- (inb(wc->ioaddr + (x << 2) + 1) << 8) |
- (inb(wc->ioaddr + (x << 2) + 2) << 16) |
- (inb(wc->ioaddr + (x << 2) + 3) << 24);
+ regs.pci[x] = (t1xxp_inb(wc, (x << 2))) |
+ (t1xxp_inb(wc, (x << 2) + 1) << 8) |
+ (t1xxp_inb(wc, (x << 2) + 2) << 16) |
+ (t1xxp_inb(wc, (x << 2) + 3) << 24);
#else
- regs.pci[x] = (inb(wc->ioaddr + x));
+ regs.pci[x] = (t1xxp_inb(wc, x));
#endif
for (x=0;x<NUM_REGS;x++)
@@ -970,10 +1036,10 @@
wc->span.manufacturer = "Digium";
dahdi_copy_string(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
- "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
+ "PCI Bus %02d Slot %02d", dahdi_pci_get_bus(wc->dev), dahdi_pci_get_slot(wc->dev) + 1);
wc->span.spanconfig = t1xxp_spanconfig;
wc->span.chanconfig = t1xxp_chanconfig;
- wc->span.irq = wc->dev->irq;
+ wc->span.irq = dahdi_pci_get_irq(wc->dev);
wc->span.startup = t1xxp_startup;
wc->span.shutdown = t1xxp_shutdown;
wc->span.rbsbits = t1xxp_rbsbits;
@@ -1106,10 +1172,10 @@
if (ints & 0x04) {
/* Just received first buffer */
rxbuf = wc->readchunk;
- canary = (unsigned int *)(wc->readchunk + DAHDI_CHUNKSIZE * 64 - 4);
+ canary = (volatile unsigned int *)(wc->readchunk + DAHDI_CHUNKSIZE * 64 - 4);
} else {
rxbuf = wc->readchunk + DAHDI_CHUNKSIZE * 32;
- canary = (unsigned int *)(wc->readchunk + DAHDI_CHUNKSIZE * 32 - 4);
+ canary = (volatile unsigned int *)(wc->readchunk + DAHDI_CHUNKSIZE * 32 - 4);
}
oldcan = *canary;
if (((oldcan & 0xffff0000) >> 16) != CANARY) {
@@ -1160,7 +1226,7 @@
}
}
/* Store the next canary */
- canary = (unsigned int *)(rxbuf + DAHDI_CHUNKSIZE * 32 - 4);
+ canary = (volatile unsigned int *)(rxbuf + DAHDI_CHUNKSIZE * 32 - 4);
*canary = (wc->canary++) | (CANARY << 16);
for (x=0;x<wc->span.channels;x++) {
dahdi_ec_chunk(wc->chans[x], wc->chans[x]->readchunk, wc->ec_chunk2[x]);
@@ -1323,11 +1389,15 @@
unsigned long flags;
int x;
- ints = inb(wc->ioaddr + WC_INTSTAT);
+ ints = t1xxp_inb(wc, WC_INTSTAT);
if (!ints)
+#if defined(__FreeBSD__)
+ return FILTER_STRAY;
+#else
return IRQ_NONE;
-
- outb(ints, wc->ioaddr + WC_INTSTAT);
+#endif
+
+ t1xxp_outb(wc, WC_INTSTAT, ints);
if (!wc->intcount) {
if (debug) printk(KERN_DEBUG "Got interrupt: 0x%04x\n", ints);
@@ -1374,7 +1444,11 @@
if (ints & 0x20)
printk(KERN_NOTICE "PCI Target abort\n");
+#if defined(__FreeBSD__)
+ return FILTER_HANDLED;
+#else
return IRQ_RETVAL(1);
+#endif
}
static int t1xxp_hardware_init(struct t1 *wc)
@@ -1383,37 +1457,37 @@
unsigned int x;
/* Hardware PCI stuff */
/* Reset chip and registers */
- outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL);
+ t1xxp_outb(wc, WC_CNTL, DELAY | 0x0e);
/* Set all outputs to 0 */
- outb(0x00, wc->ioaddr + WC_AUXD);
+ t1xxp_outb(wc, WC_AUXD, 0x00);
/* Set all to outputs except AUX1 (TDO). */
- outb(0xfd, wc->ioaddr + WC_AUXC);
+ t1xxp_outb(wc, WC_AUXC, 0xfd);
/* Configure the serial port: double clock, 20ns width, no inversion,
MSB first */
- outb(0xc8, wc->ioaddr + WC_SERC);
+ t1xxp_outb(wc, WC_SERC, 0xc8);
/* Internally delay FSC by one */
- outb(0x01, wc->ioaddr + WC_FSCDELAY);
+ t1xxp_outb(wc, WC_FSCDELAY, 0x01);
/* Back to normal, with automatic DMA wrap around */
- outb(DELAY | 0x01, wc->ioaddr + WC_CNTL);
+ t1xxp_outb(wc, WC_CNTL, DELAY | 0x01);
/* Make sure serial port and DMA are out of reset */
- outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, WC_CNTL);
+ t1xxp_outb(wc, WC_CNTL, t1xxp_inb(wc, WC_CNTL) & 0xf9);
/* Setup DMA Addresses */
/* Start at writedma */
- outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */
+ t1xxp_outl(wc, WC_DMAWS, wc->writedma); /* Write start */
/* First frame */
- outl(wc->writedma + DAHDI_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */
+ t1xxp_outl(wc, WC_DMAWI, wc->writedma + DAHDI_CHUNKSIZE * 32 - 4); /* Middle (interrupt) */
/* Second frame */
- outl(wc->writedma + DAHDI_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMAWE); /* End */
-
- outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */
+ t1xxp_outl(wc, WC_DMAWE, wc->writedma + DAHDI_CHUNKSIZE * 32 * 2 - 4); /* End */
+
+ t1xxp_outl(wc, WC_DMARS, wc->readdma); /* Read start */
/* First frame */
- outl(wc->readdma + DAHDI_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */
+ t1xxp_outl(wc, WC_DMARI, wc->readdma + DAHDI_CHUNKSIZE * 32 - 4); /* Middle (interrupt) */
/* Second frame */
- outl(wc->readdma + DAHDI_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMARE); /* End */
+ t1xxp_outl(wc, WC_DMARE, wc->readdma + DAHDI_CHUNKSIZE * 32 * 2 - 4); /* End */
if (debug) printk(KERN_DEBUG "Setting up DMA (write/read = %08lx/%08lx)\n", (long)wc->writedma, (long)wc->readdma);
@@ -1465,6 +1539,17 @@
}
+static void t1xxp_stop_stuff(struct t1 *wc)
+{
+ /* Kill clock */
+ control_set_reg(wc, WC_CLOCK, 0);
+
+ /* Turn off LED's */
+ control_set_reg(wc, WC_LEDTEST, 0);
+
+}
+
+#if !defined(__FreeBSD__)
static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct t1 *wc;
@@ -1541,16 +1626,6 @@
return 0;
}
-static void t1xxp_stop_stuff(struct t1 *wc)
-{
- /* Kill clock */
- control_set_reg(wc, WC_CLOCK, 0);
-
- /* Turn off LED's */
- control_set_reg(wc, WC_LEDTEST, 0);
-
-}
-
static void __devexit t1xxp_remove_one(struct pci_dev *pdev)
{
struct t1 *wc = pci_get_drvdata(pdev);
@@ -1569,7 +1644,7 @@
free_irq(pdev->irq, wc);
/* Reset PCI chip and registers */
- outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL);
+ t1xxp_outb(wc, WC_CNTL, DELAY | 0x0e);
/* Release span, possibly delayed */
if (!wc->usecount)
@@ -1578,6 +1653,7 @@
wc->dead = 1;
}
}
+#endif /* !__FreeBSD__ */
static struct pci_device_id t1xxp_pci_tbl[] = {
{ 0xe159, 0x0001, 0x71fe, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" },
@@ -1588,6 +1664,262 @@
{ 0 }
};
+#if defined(__FreeBSD__)
+SYSCTL_NODE(_dahdi, OID_AUTO, wcte11xp, CTLFLAG_RW, 0, "DAHDI wcte11xp");
+#define MODULE_PARAM_PREFIX "dahdi.wcte11xp"
+#define MODULE_PARAM_PARENT _dahdi_wcte11xp
+
+static void t1xxp_dma_free(bus_dma_tag_t *ptag, bus_dmamap_t *pmap, void **pvaddr, uint32_t *ppaddr);
+
+static void
+t1xxp_release_resources(struct t1 *wc)
+{
+ /* disconnect the interrupt handler */
+ if (wc->irq_handle != NULL) {
+ bus_teardown_intr(wc->dev->dev, wc->irq_res, wc->irq_handle);
+ wc->irq_handle = NULL;
+ }
+
+ if (wc->irq_res != NULL) {
+ bus_release_resource(wc->dev->dev, SYS_RES_IRQ, wc->irq_rid, wc->irq_res);
+ wc->irq_res = NULL;
+ }
+
+ /* release DMA resources */
+ t1xxp_dma_free(&wc->write_dma_tag, &wc->write_dma_map, __DECONST(void **, &wc->writechunk), &wc->writedma);
+ t1xxp_dma_free(&wc->read_dma_tag, &wc->read_dma_map, __DECONST(void **, &wc->readchunk), &wc->readdma);
+
+ /* release memory window */
+ if (wc->io_res != NULL) {
+ bus_release_resource(wc->dev->dev, SYS_RES_IOPORT, wc->io_rid, wc->io_res);
+ wc->io_res = NULL;
+ }
+}
+
+static int
+t1xxp_setup_intr(struct t1 *wc)
+{
+ int error;
+
+ wc->irq_res = bus_alloc_resource_any(
+ wc->dev->dev, SYS_RES_IRQ, &wc->irq_rid, RF_SHAREABLE | RF_ACTIVE);
+ if (wc->irq_res == NULL) {
+ device_printf(wc->dev->dev, "Can't allocate irq resource\n");
+ return -ENXIO;
+ }
+
+ error = bus_setup_intr(
+ wc->dev->dev, wc->irq_res, INTR_TYPE_CLK | INTR_MPSAFE,
+ t1xxp_interrupt, NULL, wc, &wc->irq_handle);
+ if (error) {
+ device_printf(wc->dev->dev, "Can't setup interrupt handler (error %d)\n", error);
+ return -ENXIO;
+ }
+
+ return (0);
+}
+
+static void
+t1xxp_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ uint32_t *paddr = arg;
+ *paddr = segs->ds_addr;
+}
+
+static int
+t1xxp_dma_allocate(int size, bus_dma_tag_t *ptag, bus_dmamap_t *pmap, void **pvaddr, uint32_t *ppaddr)
+{
+ int res;
+
+ res = bus_dma_tag_create(NULL, 8, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ size, 1, size, BUS_DMA_ALLOCNOW, NULL, NULL, ptag);
+ if (res)
+ return (res);
+
+ res = bus_dmamem_alloc(*ptag, pvaddr, BUS_DMA_NOWAIT | BUS_DMA_ZERO, pmap);
+ if (res) {
+ bus_dma_tag_destroy(*ptag);
+ *ptag = NULL;
+ return (res);
+ }
+
+ res = bus_dmamap_load(*ptag, *pmap, *pvaddr, size, t1xxp_dma_map_addr, ppaddr, 0);
+ if (res) {
+ bus_dmamem_free(*ptag, *pvaddr, *pmap);
+ *pvaddr = NULL;
+
+ bus_dmamap_destroy(*ptag, *pmap);
+ *pmap = NULL;
+
+ bus_dma_tag_destroy(*ptag);
+ *ptag = NULL;
+ return (res);
+ }
+
+ return (0);
+}
+
+static void
+t1xxp_dma_free(bus_dma_tag_t *ptag, bus_dmamap_t *pmap, void **pvaddr, uint32_t *ppaddr)
+{
+ if (*ppaddr != 0) {
+ bus_dmamap_unload(*ptag, *pmap);
+ *ppaddr = 0;
+ }
+ if (*pvaddr != NULL) {
+ bus_dmamem_free(*ptag, *pvaddr, *pmap);
+ *pvaddr = NULL;
+
+ bus_dmamap_destroy(*ptag, *pmap);
+ *pmap = NULL;
+ }
+ if (*ptag != NULL) {
+ bus_dma_tag_destroy(*ptag);
+ *ptag = NULL;
+ }
+}
+
+static int
+t1xxp_device_probe(device_t dev)
+{
+ struct pci_device_id *id;
+
+ id = dahdi_pci_device_id_lookup(dev, t1xxp_pci_tbl);
+ if (id == NULL)
+ return (ENXIO);
+
+ /* found device */
+ device_printf(dev, "vendor=%x device=%x subvendor=%x\n",
+ id->vendor, id->device, id->subvendor);
+ device_set_desc(dev, (const char *) id->driver_data);
+ return (0);
+}
+
+static int
+t1xxp_device_attach(device_t dev)
+{
+ int res;
+ struct pci_device_id *id;
+ struct t1 *wc;
+ int x;
+ volatile unsigned int *canary;
+
+ id = dahdi_pci_device_id_lookup(dev, t1xxp_pci_tbl);
+ if (id == NULL)
+ return (ENXIO);
+
+ wc = device_get_softc(dev);
+ wc->dev = &wc->_dev;
+ wc->dev->dev = dev;
+ spin_lock_init(&wc->lock);
+ wc->offset = 28; /* And you thought 42 was the answer */
+ wc->variety = (const char *) id->driver_data;
+
+ /* allocate IO resource */
+ wc->io_rid = PCIR_BAR(0);
+ wc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &wc->io_rid, RF_ACTIVE);
+ if (wc->io_res == NULL) {
+ device_printf(dev, "Can't allocate IO resource\n");
+ res = ENXIO;
+ goto err;
+ }
+
+ /* enable bus mastering */
+ pci_enable_busmaster(dev);
+
+ res = t1xxp_setup_intr(wc);
+ if (res)
+ goto err;
+
+ res = t1xxp_dma_allocate(DAHDI_MAX_CHUNKSIZE * 32 * 2, &wc->write_dma_tag, &wc->write_dma_map,
+ __DECONST(void **, &wc->writechunk), &wc->writedma);
+ if (res)
+ goto err;
+
+ res = t1xxp_dma_allocate(DAHDI_MAX_CHUNKSIZE * 32 * 2, &wc->read_dma_tag, &wc->read_dma_map,
+ __DECONST(void **, &wc->readchunk), &wc->readdma);
+ if (res)
+ goto err;
+
+ /* initialize canary */
+ canary = (volatile unsigned int *)(wc->readchunk + DAHDI_CHUNKSIZE * 64 - 4);
+ *canary = (CANARY << 16) | (0xffff);
+
+ /* initialize hardware */
+ t1xxp_hardware_init(wc);
+
+ for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
+ if (!(wc->chans[x] = kmalloc(sizeof(*wc->chans[x]), GFP_KERNEL))) {
+ while (x) {
+ kfree(wc->chans[--x]);
+ }
+ goto err;
+ }
+ memset(wc->chans[x], 0, sizeof(*wc->chans[x]));
+ }
+
+ /* Misc. software stuff */
+ if (t1xxp_software_init(wc) < 0) {
+ res = ENXIO;
+ goto err;
+ }
+
+ printk(KERN_INFO "Found a Wildcard: %s\n", wc->variety);
+ return (0);
+
+err:
+ /* release resources */
+ t1xxp_release_resources(wc);
+ spin_lock_destroy(&wc->lock);
+ return (res);
+}
+
+static int
+t1xxp_device_detach(device_t dev)
+{
+ struct t1 *wc = device_get_softc(dev);
+
+ /* Stop any DMA */
+ __t1xxp_stop_dma(wc);
+
+ /* In case hardware is still there */
+ __t1xxp_disable_interrupts(wc);
+
+ t1xxp_stop_stuff(wc);
+
+ /* Reset PCI chip and registers */
+ t1xxp_outb(wc, WC_CNTL, DELAY | 0x0e);
+
+ /* Unregister */
+ dahdi_unregister(&wc->span);
+
+ /* Release resources */
+ t1xxp_release_resources(wc);
+ spin_lock_destroy(&wc->lock);
+
+ return (0);
+}
+
+static device_method_t t1xxp_methods[] = {
+ DEVMETHOD(device_probe, t1xxp_device_probe),
+ DEVMETHOD(device_attach, t1xxp_device_attach),
+ DEVMETHOD(device_detach, t1xxp_device_detach),
+ { 0, 0 }
+};
+
+static driver_t t1xxp_pci_driver = {
+ "t1xxp",
+ t1xxp_methods,
+ sizeof(struct t1)
+};
+
+static devclass_t t1xxp_devclass;
+
+DRIVER_MODULE(t1xxp, pci, t1xxp_pci_driver, t1xxp_devclass, 0, 0);
+MODULE_DEPEND(t1xxp, pci, 1, 1, 1);
+MODULE_DEPEND(t1xxp, dahdi, 1, 1, 1);
+#else /* !__FreeBSD__ */
MODULE_DEVICE_TABLE(pci,t1xxp_pci_tbl);
static struct pci_driver t1xxp_driver = {
@@ -1612,6 +1944,7 @@
{
pci_unregister_driver(&t1xxp_driver);
}
+#endif /* !__FreeBSD__ */
module_param(alarmdebounce, int, 0600);
module_param(loopback, int, 0600);
@@ -1621,9 +1954,11 @@
module_param(debug, int, 0600);
module_param(j1mode, int, 0600);
+#if !defined(__FreeBSD__)
MODULE_DESCRIPTION("Wildcard TE110P Driver");
MODULE_AUTHOR("Mark Spencer <markster at digium.com>");
MODULE_LICENSE("GPL v2");
module_init(t1xxp_init);
module_exit(t1xxp_cleanup);
+#endif /* !__FreeBSD__ */
More information about the svn-commits
mailing list