📄 skfddi.c
字号:
/* * If we're at this point we're going through skfp_probe() for the * first time. Return success (0) if we've initialized 1 or more * boards. Otherwise, return failure (-ENODEV). */ if (num_boards > 0) return (0); else { printk("no SysKonnect FDDI adapter found\n"); return (-ENODEV); }} // skfp_probe/************************ * * Search the entire 'fddi' device list for a fixed probe. If a match isn't * found then check for an autoprobe or unused device location. If they * are not available then insert a new device structure at the end of * the current list. * ************************/static struct net_device *alloc_device(struct net_device *dev, u_long iobase){ struct net_device *adev = NULL; int fixed = 0, new_dev = 0; PRINTK(KERN_INFO "entering alloc_device\n"); if (!dev) return dev; num_fddi = fddi_dev_index(dev->name); if (loading_module) { num_fddi++; dev = insert_device(dev, skfp_probe); return dev; } while (1) { if (((dev->base_addr == NO_ADDRESS) || (dev->base_addr == 0)) && !adev) { adev = dev; } else if ((dev->priv == NULL) && (dev->base_addr == iobase)) { fixed = 1; } else { if (dev->next == NULL) { new_dev = 1; } else if (strncmp(dev->next->name, "fddi", 4) != 0) { new_dev = 1; } } if ((dev->next == NULL) || new_dev || fixed) break; dev = dev->next; num_fddi++; } // while (1) if (adev && !fixed) { dev = adev; num_fddi = fddi_dev_index(dev->name); new_dev = 0; } if (((dev->next == NULL) && ((dev->base_addr != NO_ADDRESS) && (dev->base_addr != 0)) && !fixed) || new_dev) { num_fddi++; /* New device */ dev = insert_device(dev, skfp_probe); } if (dev) { if (!dev->priv) { /* Allocate space for private board structure */ dev->priv = (void *) kmalloc(sizeof(struct s_smc), GFP_KERNEL); if (dev->priv == NULL) { printk("%s: Could not allocate memory for", dev->name); printk(" private board structure!\n"); return (NULL); } /* clear structure */ memset(dev->priv, 0, sizeof(struct s_smc)); } } return dev;} // alloc_device/************************ * * Initialize device structure * ************************/static void init_dev(struct net_device *dev, u_long iobase){ /* Initialize new device structure */ dev->rmem_end = 0; /* shared memory isn't used */ dev->rmem_start = 0; /* shared memory isn't used */ dev->mem_end = 0; /* shared memory isn't used */ dev->mem_start = 0; /* shared memory isn't used */ dev->base_addr = iobase; /* save port (I/O) base address */ dev->if_port = 0; /* not applicable to FDDI adapters */ dev->dma = 0; /* Bus Master DMA doesn't require channel */ dev->irq = 0; netif_start_queue(dev); dev->get_stats = &skfp_ctl_get_stats; dev->open = &skfp_open; dev->stop = &skfp_close; dev->hard_start_xmit = &skfp_send_pkt; dev->hard_header = NULL; /* set in fddi_setup() */ dev->rebuild_header = NULL; /* set in fddi_setup() */ dev->set_multicast_list = &skfp_ctl_set_multicast_list; dev->set_mac_address = &skfp_ctl_set_mac_address; dev->do_ioctl = &skfp_ioctl; dev->set_config = NULL; /* not supported for now &&& */ dev->header_cache_update = NULL; /* not supported */ dev->change_mtu = NULL; /* set in fddi_setup() */ /* Initialize remaining device structure information */ fddi_setup(dev);} // init_device/************************ * * If at end of fddi device list and can't use current entry, malloc * one up. If memory could not be allocated, print an error message. *************************/static struct net_device *insert_device(struct net_device *dev, int (*init) (struct net_device *)){ struct net_device *new; int len; PRINTK(KERN_INFO "entering insert_device\n"); len = sizeof(struct net_device) + sizeof(struct s_smc); new = (struct net_device *) kmalloc(len, GFP_KERNEL); if (new == NULL) { printk("fddi%d: Device not initialised, insufficient memory\n", num_fddi); return NULL; } else { memset((char *) new, 0, len); new->priv = (struct s_smc *) (new + 1); new->init = init; /* initialisation routine */ if (!loading_module) { new->next = dev->next; dev->next = new; } /* create new device name */ if (num_fddi > 999) { sprintf(new->name, "fddi????"); } else { sprintf(new->name, "fddi%d", num_fddi); } } return new;} // insert_device/************************ * * Get the number of a "fddiX" string * ************************/static int fddi_dev_index(unsigned char *s){ int i = 0, j = 0; for (; *s; s++) { if (isdigit(*s)) { j = 1; i = (i * 10) + (*s - '0'); } else if (j) break; } return i;} // fddi_dev_index/************************ * * Used if loaded as module only. Link the device structures * together. Needed to release them all at unload. *************************/static void link_modules(struct net_device *dev, struct net_device *tmp){ struct net_device *p = dev; if (p) { while (((struct s_smc *) (p->priv))->os.next_module) { p = ((struct s_smc *) (p->priv))->os.next_module; } if (dev != tmp) { ((struct s_smc *) (p->priv))->os.next_module = tmp; } else { ((struct s_smc *) (p->priv))->os.next_module = NULL; } } return;} // link_modules/* * ==================== * = skfp_driver_init = * ==================== * * Overview: * Initializes remaining adapter board structure information * and makes sure adapter is in a safe state prior to skfp_open(). * * Returns: * Condition code * * Arguments: * dev - pointer to device information * * Functional Description: * This function allocates additional resources such as the host memory * blocks needed by the adapter. * The adapter is also reset. The OS must call skfp_open() to open * the adapter and bring it on-line. * * Return Codes: * 0 - initialization succeeded * -1 - initialization failed */static int skfp_driver_init(struct net_device *dev){ struct s_smc *smc = (struct s_smc *) dev->priv; skfddi_priv *bp = PRIV(dev); u8 val; /* used for I/O read/writes */ PRINTK(KERN_INFO "entering skfp_driver_init\n"); // set the io address in private structures bp->base_addr = dev->base_addr; smc->hw.iop = dev->base_addr; // Get the interrupt level from the PCI Configuration Table val = dev->irq; smc->hw.irq = val; spin_lock_init(&bp->DriverLock); // Allocate invalid frame bp->LocalRxBuffer = pci_alloc_consistent(&bp->pdev, MAX_FRAME_SIZE, &bp->LocalRxBufferDMA); if (!bp->LocalRxBuffer) { printk("could not allocate mem for "); printk("LocalRxBuffer: %d byte\n", MAX_FRAME_SIZE); goto fail; } // Determine the required size of the 'shared' memory area. bp->SharedMemSize = mac_drv_check_space(); PRINTK(KERN_INFO "Memory for HWM: %ld\n", bp->SharedMemSize); if (bp->SharedMemSize > 0) { bp->SharedMemSize += 16; // for descriptor alignment bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev, bp->SharedMemSize, &bp->SharedMemDMA); if (!bp->SharedMemSize) { printk("could not allocate mem for "); printk("hardware module: %ld byte\n", bp->SharedMemSize); goto fail; } bp->SharedMemHeap = 0; // Nothing used yet. } else { bp->SharedMemAddr = NULL; bp->SharedMemHeap = 0; } // SharedMemSize > 0 memset(bp->SharedMemAddr, 0, bp->SharedMemSize); card_stop(smc); // Reset adapter. PRINTK(KERN_INFO "mac_drv_init()..\n"); if (mac_drv_init(smc) != 0) { PRINTK(KERN_INFO "mac_drv_init() failed.\n"); goto fail; } read_address(smc, NULL); PRINTK(KERN_INFO "HW-Addr: %02x %02x %02x %02x %02x %02x\n", smc->hw.fddi_canon_addr.a[0], smc->hw.fddi_canon_addr.a[1], smc->hw.fddi_canon_addr.a[2], smc->hw.fddi_canon_addr.a[3], smc->hw.fddi_canon_addr.a[4], smc->hw.fddi_canon_addr.a[5]); memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6); smt_reset_defaults(smc, 0); return (0);fail: if (bp->SharedMemAddr) { pci_free_consistent(&bp->pdev, bp->SharedMemSize, bp->SharedMemAddr, bp->SharedMemDMA); bp->SharedMemAddr = NULL; } if (bp->LocalRxBuffer) { pci_free_consistent(&bp->pdev, MAX_FRAME_SIZE, bp->LocalRxBuffer, bp->LocalRxBufferDMA); bp->LocalRxBuffer = NULL; } return (-1);} // skfp_driver_init/* * ============= * = skfp_open = * ============= * * Overview: * Opens the adapter * * Returns: * Condition code * * Arguments: * dev - pointer to device information * * Functional Description: * This function brings the adapter to an operational state. * * Return Codes: * 0 - Adapter was successfully opened * -EAGAIN - Could not register IRQ */static int skfp_open(struct net_device *dev){ struct s_smc *smc = (struct s_smc *) dev->priv; PRINTK(KERN_INFO "entering skfp_open\n"); /* Register IRQ - support shared interrupts by passing device ptr */ if (request_irq(dev->irq, (void *) skfp_interrupt, SA_SHIRQ, dev->name, dev)) { printk("%s: Requested IRQ %d is busy\n", dev->name, dev->irq); return (-EAGAIN); } /* * Set current address to factory MAC address * * Note: We've already done this step in skfp_driver_init. * However, it's possible that a user has set a node * address override, then closed and reopened the * adapter. Unless we reset the device address field * now, we'll continue to use the existing modified * address. */ read_address(smc, NULL); memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6); init_smt(smc, NULL); smt_online(smc, 1); STI_FBI(); MOD_INC_USE_COUNT; /* Clear local multicast address tables */ mac_clear_multicast(smc); /* Disable promiscuous filter settings */ mac_drv_rx_mode(smc, RX_DISABLE_PROMISC); return (0);} // skfp_open/* * ============== * = skfp_close = * ============== * * Overview: * Closes the device/module. * * Returns: * Condition code * * Arguments: * dev - pointer to device information * * Functional Description: * This routine closes the adapter and brings it to a safe state. * The interrupt service routine is deregistered with the OS. * The adapter can be opened again with another call to skfp_open(). * * Return Codes: * Always return 0. * * Assumptions: * No further requests for this adapter are made after this routine is * called. skfp_open() can be called to reset and reinitialize the * adapter. */static int skfp_close(struct net_device *dev){ struct s_smc *smc = (struct s_smc *) dev->priv; struct sk_buff *skb; skfddi_priv *bp = PRIV(dev); CLI_FBI(); smt_reset_defaults(smc, 1); card_stop(smc); mac_drv_clear_tx_queue(smc); mac_drv_clear_rx_queue(smc); netif_stop_queue(dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -