in zatm.c [1263:1368]
static int zatm_start(struct atm_dev *dev)
{
struct zatm_dev *zatm_dev = ZATM_DEV(dev);
struct pci_dev *pdev = zatm_dev->pci_dev;
unsigned long curr;
int pools,vccs,rx;
int error, i, ld;
DPRINTK("zatm_start\n");
zatm_dev->rx_map = zatm_dev->tx_map = NULL;
for (i = 0; i < NR_MBX; i++)
zatm_dev->mbx_start[i] = 0;
error = request_irq(zatm_dev->irq, zatm_int, IRQF_SHARED, DEV_LABEL, dev);
if (error < 0) {
printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
dev->number,zatm_dev->irq);
goto done;
}
/* define memory regions */
pools = NR_POOLS;
if (NR_SHAPERS*SHAPER_SIZE > pools*POOL_SIZE)
pools = NR_SHAPERS*SHAPER_SIZE/POOL_SIZE;
vccs = (zatm_dev->mem-NR_SHAPERS*SHAPER_SIZE-pools*POOL_SIZE)/
(2*VC_SIZE+RX_SIZE);
ld = -1;
for (rx = 1; rx < vccs; rx <<= 1) ld++;
dev->ci_range.vpi_bits = 0; /* @@@ no VPI for now */
dev->ci_range.vci_bits = ld;
dev->link_rate = ATM_OC3_PCR;
zatm_dev->chans = vccs; /* ??? */
curr = rx*RX_SIZE/4;
DPRINTK("RX pool 0x%08lx\n",curr);
zpokel(zatm_dev,curr,uPD98401_PMA); /* receive pool */
zatm_dev->pool_base = curr;
curr += pools*POOL_SIZE/4;
DPRINTK("Shapers 0x%08lx\n",curr);
zpokel(zatm_dev,curr,uPD98401_SMA); /* shapers */
curr += NR_SHAPERS*SHAPER_SIZE/4;
DPRINTK("Free 0x%08lx\n",curr);
zpokel(zatm_dev,curr,uPD98401_TOS); /* free pool */
printk(KERN_INFO DEV_LABEL "(itf %d): %d shapers, %d pools, %d RX, "
"%ld VCs\n",dev->number,NR_SHAPERS,pools,rx,
(zatm_dev->mem-curr*4)/VC_SIZE);
/* create mailboxes */
for (i = 0; i < NR_MBX; i++) {
void *mbx;
dma_addr_t mbx_dma;
if (!mbx_entries[i])
continue;
mbx = dma_alloc_coherent(&pdev->dev,
2 * MBX_SIZE(i), &mbx_dma, GFP_KERNEL);
if (!mbx) {
error = -ENOMEM;
goto out;
}
/*
* Alignment provided by dma_alloc_coherent() isn't enough
* for this device.
*/
if (((unsigned long)mbx ^ mbx_dma) & 0xffff) {
printk(KERN_ERR DEV_LABEL "(itf %d): system "
"bus incompatible with driver\n", dev->number);
dma_free_coherent(&pdev->dev, 2*MBX_SIZE(i), mbx, mbx_dma);
error = -ENODEV;
goto out;
}
DPRINTK("mbx@0x%08lx-0x%08lx\n", mbx, mbx + MBX_SIZE(i));
zatm_dev->mbx_start[i] = (unsigned long)mbx;
zatm_dev->mbx_dma[i] = mbx_dma;
zatm_dev->mbx_end[i] = (zatm_dev->mbx_start[i] + MBX_SIZE(i)) &
0xffff;
zout(mbx_dma >> 16, MSH(i));
zout(mbx_dma, MSL(i));
zout(zatm_dev->mbx_end[i], MBA(i));
zout((unsigned long)mbx & 0xffff, MTA(i));
zout((unsigned long)mbx & 0xffff, MWA(i));
}
error = start_tx(dev);
if (error)
goto out;
error = start_rx(dev);
if (error)
goto out_tx;
error = dev->phy->start(dev);
if (error)
goto out_rx;
zout(0xffffffff,IMR); /* enable interrupts */
/* enable TX & RX */
zout(zin(GMR) | uPD98401_GMR_SE | uPD98401_GMR_RE,GMR);
done:
return error;
out_rx:
kfree(zatm_dev->rx_map);
out_tx:
kfree(zatm_dev->tx_map);
out:
while (i-- > 0) {
dma_free_coherent(&pdev->dev, 2 * MBX_SIZE(i),
(void *)zatm_dev->mbx_start[i],
zatm_dev->mbx_dma[i]);
}
free_irq(zatm_dev->irq, dev);
goto done;
}