defxx.c

来自「linux 内核源代码」· C语言 代码 · 共 2,079 行 · 第 1/5 页

C
2,079
字号
 * Overview: *   Retrieves the address range used to access control and status *   registers. * * Returns: *   None * * Arguments: *   bdev	- pointer to device information *   bar_start	- pointer to store the start address *   bar_len	- pointer to store the length of the area * * Assumptions: *   I am sure there are some. * * Side Effects: *   None */static void dfx_get_bars(struct device *bdev,			 resource_size_t *bar_start, resource_size_t *bar_len){	int dfx_bus_pci = DFX_BUS_PCI(bdev);	int dfx_bus_eisa = DFX_BUS_EISA(bdev);	int dfx_bus_tc = DFX_BUS_TC(bdev);	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;	if (dfx_bus_pci) {		int num = dfx_use_mmio ? 0 : 1;		*bar_start = pci_resource_start(to_pci_dev(bdev), num);		*bar_len = pci_resource_len(to_pci_dev(bdev), num);	}	if (dfx_bus_eisa) {		unsigned long base_addr = to_eisa_device(bdev)->base_addr;		resource_size_t bar;		if (dfx_use_mmio) {			bar = inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_2);			bar <<= 8;			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_1);			bar <<= 8;			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_0);			bar <<= 16;			*bar_start = bar;			bar = inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_2);			bar <<= 8;			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_1);			bar <<= 8;			bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_0);			bar <<= 16;			*bar_len = (bar | PI_MEM_ADD_MASK_M) + 1;		} else {			*bar_start = base_addr;			*bar_len = PI_ESIC_K_CSR_IO_LEN;		}	}	if (dfx_bus_tc) {		*bar_start = to_tc_dev(bdev)->resource.start +			     PI_TC_K_CSR_OFFSET;		*bar_len = PI_TC_K_CSR_LEN;	}}/* * ================ * = dfx_register = * ================ * * Overview: *   Initializes a supported FDDI controller * * Returns: *   Condition code * * Arguments: *   bdev - pointer to device information * * Functional Description: * * Return Codes: *   0		 - This device (fddi0, fddi1, etc) configured successfully *   -EBUSY      - Failed to get resources, or dfx_driver_init failed. * * Assumptions: *   It compiles so it should work :-( (PCI cards do :-) * * Side Effects: *   Device structures for FDDI adapters (fddi0, fddi1, etc) are *   initialized and the board resources are read and stored in *   the device structure. */static int __devinit dfx_register(struct device *bdev){	static int version_disp;	int dfx_bus_pci = DFX_BUS_PCI(bdev);	int dfx_bus_tc = DFX_BUS_TC(bdev);	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;	char *print_name = bdev->bus_id;	struct net_device *dev;	DFX_board_t	  *bp;			/* board pointer */	resource_size_t bar_start = 0;		/* pointer to port */	resource_size_t bar_len = 0;		/* resource length */	int alloc_size;				/* total buffer size used */	struct resource *region;	int err = 0;	if (!version_disp) {	/* display version info if adapter is found */		version_disp = 1;	/* set display flag to TRUE so that */		printk(version);	/* we only display this string ONCE */	}	dev = alloc_fddidev(sizeof(*bp));	if (!dev) {		printk(KERN_ERR "%s: Unable to allocate fddidev, aborting\n",		       print_name);		return -ENOMEM;	}	/* Enable PCI device. */	if (dfx_bus_pci && pci_enable_device(to_pci_dev(bdev))) {		printk(KERN_ERR "%s: Cannot enable PCI device, aborting\n",		       print_name);		goto err_out;	}	SET_NETDEV_DEV(dev, bdev);	bp = netdev_priv(dev);	bp->bus_dev = bdev;	dev_set_drvdata(bdev, dev);	dfx_get_bars(bdev, &bar_start, &bar_len);	if (dfx_use_mmio)		region = request_mem_region(bar_start, bar_len, print_name);	else		region = request_region(bar_start, bar_len, print_name);	if (!region) {		printk(KERN_ERR "%s: Cannot reserve I/O resource "		       "0x%lx @ 0x%lx, aborting\n",		       print_name, (long)bar_len, (long)bar_start);		err = -EBUSY;		goto err_out_disable;	}	/* Set up I/O base address. */	if (dfx_use_mmio) {		bp->base.mem = ioremap_nocache(bar_start, bar_len);		if (!bp->base.mem) {			printk(KERN_ERR "%s: Cannot map MMIO\n", print_name);			err = -ENOMEM;			goto err_out_region;		}	} else {		bp->base.port = bar_start;		dev->base_addr = bar_start;	}	/* Initialize new device structure */	dev->get_stats			= dfx_ctl_get_stats;	dev->open			= dfx_open;	dev->stop			= dfx_close;	dev->hard_start_xmit		= dfx_xmt_queue_pkt;	dev->set_multicast_list		= dfx_ctl_set_multicast_list;	dev->set_mac_address		= dfx_ctl_set_mac_address;	if (dfx_bus_pci)		pci_set_master(to_pci_dev(bdev));	if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) {		err = -ENODEV;		goto err_out_unmap;	}	err = register_netdev(dev);	if (err)		goto err_out_kfree;	printk("%s: registered as %s\n", print_name, dev->name);	return 0;err_out_kfree:	alloc_size = sizeof(PI_DESCR_BLOCK) +		     PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +#ifndef DYNAMIC_BUFFERS		     (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +#endif		     sizeof(PI_CONSUMER_BLOCK) +		     (PI_ALIGN_K_DESC_BLK - 1);	if (bp->kmalloced)		dma_free_coherent(bdev, alloc_size,				  bp->kmalloced, bp->kmalloced_dma);err_out_unmap:	if (dfx_use_mmio)		iounmap(bp->base.mem);err_out_region:	if (dfx_use_mmio)		release_mem_region(bar_start, bar_len);	else		release_region(bar_start, bar_len);err_out_disable:	if (dfx_bus_pci)		pci_disable_device(to_pci_dev(bdev));err_out:	free_netdev(dev);	return err;}/* * ================ * = dfx_bus_init = * ================ * * Overview: *   Initializes the bus-specific controller logic. * * Returns: *   None * * Arguments: *   dev - pointer to device information * * Functional Description: *   Determine and save adapter IRQ in device table, *   then perform bus-specific logic initialization. * * Return Codes: *   None * * Assumptions: *   bp->base has already been set with the proper *	 base I/O address for this device. * * Side Effects: *   Interrupts are enabled at the adapter bus-specific logic. *   Note:  Interrupts at the DMA engine (PDQ chip) are not *   enabled yet. */static void __devinit dfx_bus_init(struct net_device *dev){	DFX_board_t *bp = netdev_priv(dev);	struct device *bdev = bp->bus_dev;	int dfx_bus_pci = DFX_BUS_PCI(bdev);	int dfx_bus_eisa = DFX_BUS_EISA(bdev);	int dfx_bus_tc = DFX_BUS_TC(bdev);	int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;	u8 val;	DBG_printk("In dfx_bus_init...\n");	/* Initialize a pointer back to the net_device struct */	bp->dev = dev;	/* Initialize adapter based on bus type */	if (dfx_bus_tc)		dev->irq = to_tc_dev(bdev)->interrupt;	if (dfx_bus_eisa) {		unsigned long base_addr = to_eisa_device(bdev)->base_addr;		/* Get the interrupt level from the ESIC chip.  */		val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);		val &= PI_CONFIG_STAT_0_M_IRQ;		val >>= PI_CONFIG_STAT_0_V_IRQ;		switch (val) {		case PI_CONFIG_STAT_0_IRQ_K_9:			dev->irq = 9;			break;		case PI_CONFIG_STAT_0_IRQ_K_10:			dev->irq = 10;			break;		case PI_CONFIG_STAT_0_IRQ_K_11:			dev->irq = 11;			break;		case PI_CONFIG_STAT_0_IRQ_K_15:			dev->irq = 15;			break;		}		/*		 * Enable memory decoding (MEMCS0) and/or port decoding		 * (IOCS1/IOCS0) as appropriate in Function Control		 * Register.  One of the port chip selects seems to be		 * used for the Burst Holdoff register, but this bit of		 * documentation is missing and as yet it has not been		 * determined which of the two.  This is also the reason		 * the size of the decoded port range is twice as large		 * as one required by the PDQ.		 */		/* Set the decode range of the board.  */		val = ((bp->base.port >> 12) << PI_IO_CMP_V_SLOT);		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_1, val);		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_0, 0);		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_1, val);		outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_0, 0);		val = PI_ESIC_K_CSR_IO_LEN - 1;		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_1, (val >> 8) & 0xff);		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_0, val & 0xff);		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_1, (val >> 8) & 0xff);		outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_0, val & 0xff);		/* Enable the decoders.  */		val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0;		if (dfx_use_mmio)			val |= PI_FUNCTION_CNTRL_M_MEMCS0;		outb(base_addr + PI_ESIC_K_FUNCTION_CNTRL, val);		/*		 * Enable access to the rest of the module		 * (including PDQ and packet memory).		 */		val = PI_SLOT_CNTRL_M_ENB;		outb(base_addr + PI_ESIC_K_SLOT_CNTRL, val);		/*		 * Map PDQ registers into memory or port space.  This is		 * done with a bit in the Burst Holdoff register.		 */		val = inb(base_addr + PI_DEFEA_K_BURST_HOLDOFF);		if (dfx_use_mmio)			val |= PI_BURST_HOLDOFF_V_MEM_MAP;		else			val &= ~PI_BURST_HOLDOFF_V_MEM_MAP;		outb(base_addr + PI_DEFEA_K_BURST_HOLDOFF, val);		/* Enable interrupts at EISA bus interface chip (ESIC) */		val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);		val |= PI_CONFIG_STAT_0_M_INT_ENB;		outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);	}	if (dfx_bus_pci) {		struct pci_dev *pdev = to_pci_dev(bdev);		/* Get the interrupt level from the PCI Configuration Table */		dev->irq = pdev->irq;		/* Check Latency Timer and set if less than minimal */		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val);		if (val < PFI_K_LAT_TIMER_MIN) {			val = PFI_K_LAT_TIMER_DEF;			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val);		}		/* Enable interrupts at PCI bus interface chip (PFI) */		val = PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB;		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, val);	}}/* * ================== * = dfx_bus_uninit = * ================== * * Overview: *   Uninitializes the bus-specific controller logic. * * Returns: *   None * * Arguments: *   dev - pointer to device information * * Functional Description: *   Perform bus-specific logic uninitialization. * * Return Codes: *   None * * Assumptions: *   bp->base has already been set with the proper *	 base I/O address for this device. * * Side Effects: *   Interrupts are disabled at the adapter bus-specific logic. */static void __devexit dfx_bus_uninit(struct net_device *dev){	DFX_board_t *bp = netdev_priv(dev);	struct device *bdev = bp->bus_dev;	int dfx_bus_pci = DFX_BUS_PCI(bdev);	int dfx_bus_eisa = DFX_BUS_EISA(bdev);	u8 val;	DBG_printk("In dfx_bus_uninit...\n");	/* Uninitialize adapter based on bus type */	if (dfx_bus_eisa) {		unsigned long base_addr = to_eisa_device(bdev)->base_addr;		/* Disable interrupts at EISA bus interface chip (ESIC) */		val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);		val &= ~PI_CONFIG_STAT_0_M_INT_ENB;		outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);	}	if (dfx_bus_pci) {		/* Disable interrupts at PCI bus interface chip (PFI) */		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, 0);	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?