in horizon.c [2607:2759]
static int hrz_probe(struct pci_dev *pci_dev,
const struct pci_device_id *pci_ent)
{
hrz_dev * dev;
int err = 0;
// adapter slot free, read resources from PCI configuration space
u32 iobase = pci_resource_start (pci_dev, 0);
u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 1));
unsigned int irq;
unsigned char lat;
PRINTD (DBG_FLOW, "hrz_probe");
if (pci_enable_device(pci_dev))
return -EINVAL;
/* XXX DEV_LABEL is a guess */
if (!request_region(iobase, HRZ_IO_EXTENT, DEV_LABEL)) {
err = -EINVAL;
goto out_disable;
}
dev = kzalloc(sizeof(hrz_dev), GFP_KERNEL);
if (!dev) {
// perhaps we should be nice: deregister all adapters and abort?
PRINTD(DBG_ERR, "out of memory");
err = -ENOMEM;
goto out_release;
}
pci_set_drvdata(pci_dev, dev);
// grab IRQ and install handler - move this someplace more sensible
irq = pci_dev->irq;
if (request_irq(irq,
interrupt_handler,
IRQF_SHARED, /* irqflags guess */
DEV_LABEL, /* name guess */
dev)) {
PRINTD(DBG_WARN, "request IRQ failed!");
err = -EINVAL;
goto out_free;
}
PRINTD(DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p",
iobase, irq, membase);
dev->atm_dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &hrz_ops, -1,
NULL);
if (!(dev->atm_dev)) {
PRINTD(DBG_ERR, "failed to register Madge ATM adapter");
err = -EINVAL;
goto out_free_irq;
}
PRINTD(DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p",
dev->atm_dev->number, dev, dev->atm_dev);
dev->atm_dev->dev_data = (void *) dev;
dev->pci_dev = pci_dev;
// enable bus master accesses
pci_set_master(pci_dev);
// frobnicate latency (upwards, usually)
pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &lat);
if (pci_lat) {
PRINTD(DBG_INFO, "%s PCI latency timer from %hu to %hu",
"changing", lat, pci_lat);
pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, pci_lat);
} else if (lat < MIN_PCI_LATENCY) {
PRINTK(KERN_INFO, "%s PCI latency timer from %hu to %hu",
"increasing", lat, MIN_PCI_LATENCY);
pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, MIN_PCI_LATENCY);
}
dev->iobase = iobase;
dev->irq = irq;
dev->membase = membase;
dev->rx_q_entry = dev->rx_q_reset = &memmap->rx_q_entries[0];
dev->rx_q_wrap = &memmap->rx_q_entries[RX_CHANS-1];
// these next three are performance hacks
dev->last_vc = -1;
dev->tx_last = -1;
dev->tx_idle = 0;
dev->tx_regions = 0;
dev->tx_bytes = 0;
dev->tx_skb = NULL;
dev->tx_iovec = NULL;
dev->tx_cell_count = 0;
dev->rx_cell_count = 0;
dev->hec_error_count = 0;
dev->unassigned_cell_count = 0;
dev->noof_spare_buffers = 0;
{
unsigned int i;
for (i = 0; i < TX_CHANS; ++i)
dev->tx_channel_record[i] = -1;
}
dev->flags = 0;
// Allocate cell rates and remember ASIC version
// Fibre: ATM_OC3_PCR = 1555200000/8/270*260/53 - 29/53
// Copper: (WRONG) we want 6 into the above, close to 25Mb/s
// Copper: (plagarise!) 25600000/8/270*260/53 - n/53
if (hrz_init(dev)) {
// to be really pedantic, this should be ATM_OC3c_PCR
dev->tx_avail = ATM_OC3_PCR;
dev->rx_avail = ATM_OC3_PCR;
set_bit(ultra, &dev->flags); // NOT "|= ultra" !
} else {
dev->tx_avail = ((25600000/8)*26)/(27*53);
dev->rx_avail = ((25600000/8)*26)/(27*53);
PRINTD(DBG_WARN, "Buggy ASIC: no TX bus-mastering.");
}
// rate changes spinlock
spin_lock_init(&dev->rate_lock);
// on-board memory access spinlock; we want atomic reads and
// writes to adapter memory (handles IRQ and SMP)
spin_lock_init(&dev->mem_lock);
init_waitqueue_head(&dev->tx_queue);
// vpi in 0..4, vci in 6..10
dev->atm_dev->ci_range.vpi_bits = vpi_bits;
dev->atm_dev->ci_range.vci_bits = 10-vpi_bits;
timer_setup(&dev->housekeeping, do_housekeeping, 0);
mod_timer(&dev->housekeeping, jiffies);
out:
return err;
out_free_irq:
free_irq(irq, dev);
out_free:
kfree(dev);
out_release:
release_region(iobase, HRZ_IO_EXTENT);
out_disable:
pci_disable_device(pci_dev);
goto out;
}