struct net_device_stats *islpci_statistics(struct net_device *nwdev) { islpci_private *private_config = nwdev->priv; char firmware[64]; DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics \n"); #ifdef CONFIG_ARCH_ISL3893 if ( ! firmware_uploaded ) { if( private_config->pci_dev_id == PCIDEVICE_ISL3890 ) strcpy( firmware, ISL3890_IMAGE_FILE ); else strcpy( firmware, ISL3877_IMAGE_FILE ); #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Upload firmware: %s, %p, %p \n", firmware, private_config->remapped_device_base, private_config->device_host_address ); #endif if (isl38xx_upload_firmware( firmware, private_config->remapped_device_base, private_config->device_host_address ) == -1) { DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not upload the firmware \n", DRIVER_NAME ); } else { /* set the firmware uploaded flag for skipping the firmware upload the next time this function is called and for activating the device on the open call */ firmware_uploaded = 1; } } #endif return &private_config->statistics; }
int islpci_probe_pci(struct net_device *nw_device, struct pci_dev *pci_device, const struct pci_device_id *id) { #else int islpci_probe_pci(struct pci_dev *pci_device, const struct pci_device_id *id) { struct net_device *nw_device=NULL; #endif void *phymem; u16 irq; u8 bus, devfn, latency_tmr; islpci_private *private_config; int rvalue, dev_id; int dma_mask = 0xffffffff; char firmware[256]; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "islpci_probe_pci\n"); #endif // Enable the pci device if (pci_enable_device(pci_device)) { DEBUG(SHOW_ERROR_MESSAGES, "%s: pci_enable_device() failed.\n", DRIVER_NAME ); return -EIO; } // Figure out our resources irq = pci_device->irq; bus = pci_device->bus->number; devfn = pci_device->devfn; dev_id = pci_device->device; // check whether the latency timer is set correctly #ifdef CONFIG_ARCH_ISL3893 pcibios_write_config_byte(bus, devfn, PCI_TRDY_TIMEOUT_VALUE, 0 ); pcibios_write_config_byte(bus, devfn, PCI_RETRY_TIMEOUT_VALUE, 0 ); #else pcibios_read_config_byte(bus, devfn, PCI_LATENCY_TIMER, &latency_tmr); #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG( SHOW_TRACING, "latency timer: %x\n", latency_tmr ); #endif if( latency_tmr < PCIDEVICE_LATENCY_TIMER_MIN ) { // set the latency timer pcibios_write_config_byte(bus, devfn, PCI_LATENCY_TIMER, PCIDEVICE_LATENCY_TIMER_VAL ); } #endif // determine what the supported DMA memory region is while( pci_set_dma_mask( pci_device, dma_mask ) != 0 ) { // range not supported, shift the mask and check again if( dma_mask >>= 1, dma_mask == 0 ) { // mask is zero, DMA memory not supported by PCI DEBUG(SHOW_ERROR_MESSAGES, "DMA Memory not supported\n" ); return -EIO; } } #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "DMA Memory support mask is 0x%x \n", dma_mask ); #endif // call for the physical address to address the PCI device phymem = (void *) pci_resource_start(pci_device, 0); #ifdef CONFIG_ARCH_ISL3893 // FIXme printk("!!pci_resource_start = %p, shound be 0x10000000\n", phymem ); phymem = 0x10000000; #endif // request the pci device for regions ??? if (rvalue = pci_request_regions(pci_device, DRIVER_NAME ), rvalue) { DEBUG(SHOW_ERROR_MESSAGES, "pci_request_regions failure, rvalue %i\n", rvalue ); return -EIO; } // enable PCI bus-mastering pci_set_master(pci_device); // Log the device resources information #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "islpci device: phymem:0x%lx, irq:%d \n", (long) phymem, irq); #endif // setup the network device interface and its structure if (nw_device = islpci_probe(nw_device, pci_device, (long) phymem, (int) irq), nw_device == NULL) { // error configuring the driver as a network device DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not configure " "network device \n", DRIVER_NAME ); return -EIO; } // save the interrupt request line and use the remapped device base address // as the device identification both for uniqueness and parameter passing // to the interrupt handler private_config = nw_device->priv; private_config->pci_irq = irq; private_config->pci_dev_id = dev_id; private_config->device_id = private_config->remapped_device_base; spin_lock_init( &private_config->slock ); // request for the interrupt before uploading the firmware printk("request_irq(%d)\n", irq ); if ( rvalue = request_irq(irq, &islpci_interrupt, SA_INTERRUPT | SA_SHIRQ, DRIVER_NAME, private_config), rvalue != 0 ) { // error, could not hook the handler to the irq DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not install IRQ-handler \n", DRIVER_NAME ); return -EIO; } #ifdef CONFIG_ARCH_ISL3893 uPCI->ARMIntEnReg = 0x20000FF; #endif #ifndef CONFIG_ARCH_ISL3893 // select the firmware file depending on the device id, take for default // the 3877 firmware file if( dev_id == PCIDEVICE_ISL3890 ) strcpy( firmware, ISL3890_IMAGE_FILE ); else strcpy( firmware, ISL3877_IMAGE_FILE ); #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Firmware file: %s \n", firmware ); #endif if (isl38xx_upload_firmware( firmware, private_config->remapped_device_base, private_config->device_host_address ) == -1) { DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not upload the " "firmware \n", DRIVER_NAME ); return -EIO; } #endif #ifdef CONFIG_ARCH_ISL3893 mgt_initialize(); #endif #ifdef INTERSIL_EVENTS mgt_indication_handler ( DEV_NETWORK, nw_device->name, 0, islpci_mgt_indication ); #endif #ifdef WDS_LINKS mgt_indication_handler ( DEV_NETWORK, nw_device->name, DOT11_OID_WDSLINKADD, islpci_wdslink_add_hndl ); mgt_indication_handler ( DEV_NETWORK, nw_device->name, DOT11_OID_WDSLINKREMOVE, islpci_wdslink_del_hndl ); #endif return 0; } void islpci_remove_pci( struct pci_dev *pci_device ) { struct net_device **devp, **next; islpci_private *private_config; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "islpci_remove_pci\n"); #endif for (devp = &root_islpci_device; *devp; devp = next) { next = &((islpci_private *) (*devp)->priv)->next_module; private_config = (*devp)->priv; // free the interrupt request writel(0, private_config->remapped_device_base + ISL38XX_INT_EN_REG); free_irq(private_config->pci_irq, private_config); } } int init_module( void ) { DEBUG(SHOW_ANYTHING, "Loaded %s, version %s\n", DRIVER_NAME, VERSIONID ); if (pci_register_driver(&islpci_pci_drv_id) <= 0) { DEBUG(SHOW_ERROR_MESSAGES, "%s: No devices found, driver not " "installed.\n", DRIVER_NAME); pci_unregister_driver(&islpci_pci_drv_id); return -ENODEV; } return 0; }
/****************************************************************************** Module initialization functions ******************************************************************************/ dev_node_t *islpci_attach(dev_locator_t * loc) { u32 io; u16 dev_id; u8 bus, devfn, irq, latency_tmr; struct pci_dev *pci_device; struct net_device *nw_device; dev_node_t *node; islpci_private *private_config; int rvalue; int dma_mask = 0xffffffff; char firmware[256]; // perform some initial setting checks if (loc->bus != LOC_PCI) return NULL; bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "islpci_attach(bus %d, function %d)\n", bus, devfn); #endif // get some pci settings for verification pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io); pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq); pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id); // check whether the latency timer is set correctly pcibios_read_config_byte(bus, devfn, PCI_LATENCY_TIMER, &latency_tmr); #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG( SHOW_TRACING, "latency timer: %x\n", latency_tmr ); #endif if( latency_tmr < PCIDEVICE_LATENCY_TIMER_MIN ) { // set the latency timer pcibios_write_config_byte(bus, devfn, PCI_LATENCY_TIMER, PCIDEVICE_LATENCY_TIMER_VAL ); } if (io &= ~3, io == 0 || irq == 0) { DEBUG(SHOW_ERROR_MESSAGES, "The ISL38XX Ethernet interface was not " "assigned an %s.\n" KERN_ERR " It will not be activated.\n", io == 0 ? "I/O address" : "IRQ"); return NULL; } // get pci device information by loading the pci_dev structure if (pci_device = pci_find_slot(bus, devfn), pci_device == NULL) { // error reading the pci device structure DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not get PCI device " "information \n", DRIVER_NAME ); return NULL; } // determine what the supported DMA memory region is while( pci_set_dma_mask( pci_device, dma_mask ) != 0 ) { // range not supported, shift the mask and check again if( dma_mask >>= 1, dma_mask == 0 ) { // mask is zero, DMA memory not supported by PCI DEBUG(SHOW_ERROR_MESSAGES, "DMA Memory not supported\n" ); return NULL; } } #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "DMA Memory support mask is 0x%x \n", dma_mask ); #endif // setup the network device interface and its structure if (nw_device = islpci_probe(NULL, pci_device, (long) io, (int) irq), nw_device == NULL) { // error configuring the driver as a network device DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not configure " "network device \n", DRIVER_NAME ); return NULL; } #ifdef WDS_LINKS mgt_indication_handler ( DEV_NETWORK, nw_device->name, DOT11_OID_WDSLINKADD, islpci_wdslink_add_hndl ); mgt_indication_handler ( DEV_NETWORK, nw_device->name, DOT11_OID_WDSLINKREMOVE, islpci_wdslink_del_hndl ); #endif // save the interrupt request line and use the remapped device base address // as the device identification both for uniqueness and parameter passing // to the interrupt handler private_config = nw_device->priv; private_config->pci_irq = irq; private_config->pci_dev_id = dev_id; private_config->device_id = private_config->remapped_device_base; spin_lock_init( &private_config->slock ); // request for the interrupt before uploading the firmware if (rvalue = request_irq(irq, &islpci_interrupt, SA_INTERRUPT | SA_SHIRQ, DRIVER_NAME, private_config), rvalue != 0) { // error, could not hook the handler to the irq DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not install " "IRQ-handler \n", DRIVER_NAME ); return NULL; } // select the firmware file depending on the device id, take for default // the 3877 firmware file if( dev_id == PCIDEVICE_ISL3890 ) strcpy( firmware, ISL3890_IMAGE_FILE ); else strcpy( firmware, ISL3877_IMAGE_FILE ); #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Device %x, firmware file: %s \n", dev_id, firmware ); #endif if (isl38xx_upload_firmware( firmware, private_config->remapped_device_base, private_config->device_host_address ) == -1) { // error uploading the firmware DEBUG(SHOW_ERROR_MESSAGES, "ERROR: %s could not upload the " "firmware \n", DRIVER_NAME ); return NULL; } // finally setup the node structure with the device information node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); strcpy(node->dev_name, nw_device->name); node->major = 0; node->minor = 0; node->next = NULL; MOD_INC_USE_COUNT; return node; }
int islpci_reset(islpci_private * private_config, char *firmware ) { isl38xx_control_block *control_block = private_config->control_block; queue_entry *entry; // unsigned long flags; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_reset \n"); #endif // lock the driver code //driver_lock( &private_config->slock, &flags ); // stop the transmission of network frames to the driver netif_stop_queue(private_config->my_module); // disable all device interrupts writel(0, private_config->remapped_device_base + ISL38XX_INT_EN_REG); // flush all management queues while( isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ) != 0 ) { islpci_get_queue(private_config->remapped_device_base, &private_config->mgmt_tx_shadowq, &entry); islpci_put_queue(private_config->remapped_device_base, &private_config->mgmt_tx_freeq, entry); // decrement the real management index private_config->index_mgmt_tx--; } // while( isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ) != 0 ) // { // islpci_get_queue(private_config->remapped_device_base, // &private_config->mgmt_rx_shadowq, &entry); // islpci_put_queue(private_config->remapped_device_base, // &private_config->mgmt_rx_freeq, entry); // decrement the real management index // private_config->index_mgmt_rx--; // } #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_TRACING, "Firmware file: %s \n", firmware ); #endif if (isl38xx_upload_firmware( firmware, private_config->remapped_device_base, private_config->device_host_address ) == -1) { // error uploading the firmware DEBUG(SHOW_ERROR_MESSAGES, "ERROR: could not upload the firmware \n" ); // unlock the driver code //driver_unlock( &private_config->slock, &flags ); return -1; } // unlock the driver code //driver_unlock( &private_config->slock, &flags ); return 0; }