⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 madgemc.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
 * * There's two ways we can check to see if the interrupt is ours, * both with their own disadvantages... * * 1)  	Read in the SIFSTS register from the TMS controller.  This *	is guarenteed to be accurate, however, there's a fairly *	large performance penalty for doing so: the Madge chips *	must request the register from the Eagle, the Eagle must *	read them from its internal bus, and then take the route *	back out again, for a 16bit read.   * * 2)	Use the MC_CONTROL_REG0_SINTR bit from the Madge ASICs. *	The major disadvantage here is that the accuracy of the *	bit is in question.  However, it cuts out the extra read *	cycles it takes to read the Eagle's SIF, as its only an *	8bit read, and theoretically the Madge bit is directly *	connected to the interrupt latch coming out of the Eagle *	hardware (that statement is not verified).   * * I can't determine which of these methods has the best win.  For now, * we make a compromise.  Use the Madge way for the first interrupt, * which should be the fast-path, and then once we hit the first  * interrupt, keep on trying using the SIF method until we've * exhausted all contiguous interrupts. * */static irqreturn_t madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs){	int pending,reg1;	struct net_device *dev;	if (!dev_id) {		printk("madgemc_interrupt: was not passed a dev_id!\n");		return IRQ_NONE;	}	dev = (struct net_device *)dev_id;	/* Make sure its really us. -- the Madge way */	pending = inb(dev->base_addr + MC_CONTROL_REG0);	if (!(pending & MC_CONTROL_REG0_SINTR))		return IRQ_NONE; /* not our interrupt */	/*	 * Since we're level-triggered, we may miss the rising edge	 * of the next interrupt while we're off handling this one,	 * so keep checking until the SIF verifies that it has nothing	 * left for us to do.	 */	pending = STS_SYSTEM_IRQ;	do {		if (pending & STS_SYSTEM_IRQ) {			/* Toggle the interrupt to reset the latch on card */			reg1 = inb(dev->base_addr + MC_CONTROL_REG1);			outb(reg1 ^ MC_CONTROL_REG1_SINTEN, 			     dev->base_addr + MC_CONTROL_REG1);			outb(reg1, dev->base_addr + MC_CONTROL_REG1);			/* Continue handling as normal */			tms380tr_interrupt(irq, dev_id, regs);			pending = SIFREADW(SIFSTS); /* restart - the SIF way */		} else			return IRQ_HANDLED; 	} while (1);	return IRQ_HANDLED; /* not reachable */}/* * Set the card to the prefered ring speed. * * Unlike newer cards, the MC16/32 have their speed selection * circuit connected to the Madge ASICs and not to the TMS380 * NSELOUT pins. Set the ASIC bits correctly here, and return  * zero to leave the TMS NSELOUT bits unaffected. * */unsigned short madgemc_setnselout_pins(struct net_device *dev){	unsigned char reg1;	struct net_local *tp = netdev_priv(dev);		reg1 = inb(dev->base_addr + MC_CONTROL_REG1);	if(tp->DataRate == SPEED_16)		reg1 |= MC_CONTROL_REG1_SPEED_SEL; /* add for 16mb */	else if (reg1 & MC_CONTROL_REG1_SPEED_SEL)		reg1 ^= MC_CONTROL_REG1_SPEED_SEL; /* remove for 4mb */	outb(reg1, dev->base_addr + MC_CONTROL_REG1);	return 0; /* no change */}/* * Set the register page.  This equates to the SRSX line * on the TMS380Cx6. * * Register selection is normally done via three contiguous * bits.  However, some boards (such as the MC16/32) use only * two bits, plus a separate bit in the glue chip.  This * sets the SRSX bit (the top bit).  See page 4-17 in the * Yellow Book for which registers are affected. * */static void madgemc_setregpage(struct net_device *dev, int page){		static int reg1;	reg1 = inb(dev->base_addr + MC_CONTROL_REG1);	if ((page == 0) && (reg1 & MC_CONTROL_REG1_SRSX)) {		outb(reg1 ^ MC_CONTROL_REG1_SRSX, 		     dev->base_addr + MC_CONTROL_REG1);	}	else if (page == 1) {		outb(reg1 | MC_CONTROL_REG1_SRSX, 		     dev->base_addr + MC_CONTROL_REG1);	}	reg1 = inb(dev->base_addr + MC_CONTROL_REG1);	return;}/* * The SIF registers are not mapped into register space by default * Set this to 1 to map them, 0 to map the BIA ROM. * */static void madgemc_setsifsel(struct net_device *dev, int val){	unsigned int reg0;	reg0 = inb(dev->base_addr + MC_CONTROL_REG0);	if ((val == 0) && (reg0 & MC_CONTROL_REG0_SIFSEL)) {		outb(reg0 ^ MC_CONTROL_REG0_SIFSEL, 		     dev->base_addr + MC_CONTROL_REG0);	} else if (val == 1) {		outb(reg0 | MC_CONTROL_REG0_SIFSEL, 		     dev->base_addr + MC_CONTROL_REG0);	}		reg0 = inb(dev->base_addr + MC_CONTROL_REG0);	return;}/* * Enable SIF interrupts * * This does not enable interrupts in the SIF, but rather * enables SIF interrupts to be passed onto the host. * */static void madgemc_setint(struct net_device *dev, int val){	unsigned int reg1;	reg1 = inb(dev->base_addr + MC_CONTROL_REG1);	if ((val == 0) && (reg1 & MC_CONTROL_REG1_SINTEN)) {		outb(reg1 ^ MC_CONTROL_REG1_SINTEN, 		     dev->base_addr + MC_CONTROL_REG1);	} else if (val == 1) {		outb(reg1 | MC_CONTROL_REG1_SINTEN, 		     dev->base_addr + MC_CONTROL_REG1);	}	return;}/* * Cable type is set via control register 7. Bit zero high * for UTP, low for STP. */static void madgemc_setcabletype(struct net_device *dev, int type){	outb((type==0)?MC_CONTROL_REG7_CABLEUTP:MC_CONTROL_REG7_CABLESTP,	     dev->base_addr + MC_CONTROL_REG7);}/* * Enable the functions of the Madge chipset needed for * full working order.  */static int madgemc_chipset_init(struct net_device *dev){	outb(0, dev->base_addr + MC_CONTROL_REG1); /* pull SRESET low */	tms380tr_wait(100); /* wait for card to reset */	/* bring back into normal operating mode */	outb(MC_CONTROL_REG1_NSRESET, dev->base_addr + MC_CONTROL_REG1);	/* map SIF registers */	madgemc_setsifsel(dev, 1);	/* enable SIF interrupts */	madgemc_setint(dev, 1); 	return 0;}/* * Disable the board, and put back into power-up state. */static void madgemc_chipset_close(struct net_device *dev){	/* disable interrupts */	madgemc_setint(dev, 0);	/* unmap SIF registers */	madgemc_setsifsel(dev, 0);	return;}/* * Read the card type (MC16 or MC32) from the card. * * The configuration registers are stored in two separate * pages.  Pages are flipped by clearing bit 3 of CONTROL_REG0 (PAGE) * for page zero, or setting bit 3 for page one. * * Page zero contains the following data: *	Byte 0: Manufacturer ID (0x4D -- ASCII "M") *	Byte 1: Card type: *			0x08 for MC16 *			0x0D for MC32 *	Byte 2: Card revision *	Byte 3: Mirror of POS config register 0 *	Byte 4: Mirror of POS 1 *	Byte 5: Mirror of POS 2 * * Page one contains the following data: *	Byte 0: Unused *	Byte 1-6: BIA, MSB to LSB. * * Note that to read the BIA, we must unmap the SIF registers * by clearing bit 2 of CONTROL_REG0 (SIFSEL), as the data * will reside in the same logical location.  For this reason, * _never_ read the BIA while the Eagle processor is running! * The SIF will be completely inaccessible until the BIA operation * is complete. * */static void madgemc_read_rom(struct net_device *dev, struct card_info *card){	unsigned long ioaddr;	unsigned char reg0, reg1, tmpreg0, i;	ioaddr = dev->base_addr;	reg0 = inb(ioaddr + MC_CONTROL_REG0);	reg1 = inb(ioaddr + MC_CONTROL_REG1);	/* Switch to page zero and unmap SIF */	tmpreg0 = reg0 & ~(MC_CONTROL_REG0_PAGE + MC_CONTROL_REG0_SIFSEL);	outb(tmpreg0, ioaddr + MC_CONTROL_REG0);		card->manid = inb(ioaddr + MC_ROM_MANUFACTURERID);	card->cardtype = inb(ioaddr + MC_ROM_ADAPTERID);	card->cardrev = inb(ioaddr + MC_ROM_REVISION);	/* Switch to rom page one */	outb(tmpreg0 | MC_CONTROL_REG0_PAGE, ioaddr + MC_CONTROL_REG0);	/* Read BIA */	dev->addr_len = 6;	for (i = 0; i < 6; i++)		dev->dev_addr[i] = inb(ioaddr + MC_ROM_BIA_START + i);		/* Restore original register values */	outb(reg0, ioaddr + MC_CONTROL_REG0);	outb(reg1, ioaddr + MC_CONTROL_REG1);		return;}static int madgemc_open(struct net_device *dev){  	/*	 * Go ahead and reinitialize the chipset again, just to 	 * make sure we didn't get left in a bad state.	 */	madgemc_chipset_init(dev);	tms380tr_open(dev);	return 0;}static int madgemc_close(struct net_device *dev){	tms380tr_close(dev);	madgemc_chipset_close(dev);	return 0;}/* * Give some details available from /proc/mca/slotX */static int madgemc_mcaproc(char *buf, int slot, void *d) {		struct net_device *dev = (struct net_device *)d;	struct net_local *tp = dev->priv;	struct card_info *curcard = tp->tmspriv;	int len = 0;		len += sprintf(buf+len, "-------\n");	if (curcard) {		struct net_local *tp = netdev_priv(dev);		int i;				len += sprintf(buf+len, "Card Revision: %d\n", curcard->cardrev);		len += sprintf(buf+len, "RAM Size: %dkb\n", curcard->ramsize);		len += sprintf(buf+len, "Cable type: %s\n", (curcard->cabletype)?"STP/DB9":"UTP/RJ-45");		len += sprintf(buf+len, "Configured ring speed: %dMb/sec\n", (curcard->ringspeed)?16:4);		len += sprintf(buf+len, "Running ring speed: %dMb/sec\n", (tp->DataRate==SPEED_16)?16:4);		len += sprintf(buf+len, "Device: %s\n", dev->name);		len += sprintf(buf+len, "IO Port: 0x%04lx\n", dev->base_addr);		len += sprintf(buf+len, "IRQ: %d\n", dev->irq);		len += sprintf(buf+len, "Arbitration Level: %d\n", curcard->arblevel);		len += sprintf(buf+len, "Burst Mode: ");		switch(curcard->burstmode) {		case 0: len += sprintf(buf+len, "Cycle steal"); break;		case 1: len += sprintf(buf+len, "Limited burst"); break;		case 2: len += sprintf(buf+len, "Delayed release"); break;		case 3: len += sprintf(buf+len, "Immediate release"); break;		}		len += sprintf(buf+len, " (%s)\n", (curcard->fairness)?"Unfair":"Fair");				len += sprintf(buf+len, "Ring Station Address: ");		len += sprintf(buf+len, "%2.2x", dev->dev_addr[0]);		for (i = 1; i < 6; i++)			len += sprintf(buf+len, " %2.2x", dev->dev_addr[i]);		len += sprintf(buf+len, "\n");	} else 		len += sprintf(buf+len, "Card not configured\n");	return len;}static int __devexit madgemc_remove(struct device *device){	struct net_device *dev = dev_get_drvdata(device);	struct net_local *tp;        struct card_info *card;	if (!dev)		BUG();	tp = dev->priv;	card = tp->tmspriv;	kfree(card);	tp->tmspriv = NULL;	unregister_netdev(dev);	release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT);	free_irq(dev->irq, dev);	tmsdev_term(dev);	free_netdev(dev);	dev_set_drvdata(device, NULL);	return 0;}static short madgemc_adapter_ids[] __initdata = {	0x002d,	0x0000};static struct mca_driver madgemc_driver = {	.id_table = madgemc_adapter_ids,	.driver = {		.name = "madgemc",		.bus = &mca_bus_type,		.probe = madgemc_probe,		.remove = __devexit_p(madgemc_remove),	},};static int __init madgemc_init (void){	return mca_register_driver (&madgemc_driver);}static void __exit madgemc_exit (void){	mca_unregister_driver (&madgemc_driver);}module_init(madgemc_init);module_exit(madgemc_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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