3c59x driver

Phillip Dillinger (Phillip.Dillinger@sealabs.com)
Mon, 9 Dec 1996 17:20:14 -0800


Here is a patch from v0.28-all to a new version of the 3c59x driver.

It includes features such as Early Tx and Rx start, and more robustness as
far as errors in the DMADone interrupt is concerned. It also corrects some
timing problems.

Here it is:
21a22
> #define REALLY_SLOW_IO 1
97c98
< #define VORTEX_DEBUG 2

---
> #define VORTEX_DEBUG 4
101c102
< #define WAIT_TX_AVAIL 200
---
> #define WAIT_TX_AVAIL 10
242c243
< 	EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
---
> 	EEPROM_Read = 0x80, EEPROM_Write = 0x40, EEPROM_Erase = 0xC0,
251c252
< 	DriverTune=13, Checksum=15};
---
> 	SWInfo=13, SWInfo2=15};
290c291
< 	  default_media:3,			/* Read from the EEPROM. */
---
> 	  default_media:3,			/* Read from the EEPROM */
314a316,317
> static int txstart=16,rxstart=8; /* Thresholds */
> 
353,373d355
< #ifdef MODULE
< static int debug = -1;
< /* A list of all installed Vortex devices, for removing the driver module. */
< static struct device *root_vortex_dev = NULL;
< 
< int
< init_module(void)
< {
< 	int cards_found;
< 
< 	if (debug >= 0)
< 		vortex_debug = debug;
< 	if (vortex_debug)
< 		printk(version);
< 
< 	root_vortex_dev = NULL;
< 	cards_found = vortex_scan(0);
< 	return cards_found ? 0 : -ENODEV;
< }
< 
< #else
385d366
< #endif  /* not MODULE */
398c379
< 				unsigned char pci_latency;
---
> 				unsigned char pci_latency,pci_mingnt,pci_maxlat;
403,404c384,385
< 										product_ids[board_index], pci_index,
< 										&pci_bus, &pci_device_fn))
---
> 					product_ids[board_index], pci_index,
> 					&pci_bus, &pci_device_fn))
407c388
< 										 PCI_INTERRUPT_LINE, &pci_irq_line);
---
> 					 PCI_INTERRUPT_LINE, &pci_irq_line);
409c390
< 										  PCI_BASE_ADDRESS_0, &pci_ioaddr);
---
> 					  PCI_BASE_ADDRESS_0, &pci_ioaddr);
413d393
< #ifdef VORTEX_BUS_MASTER
428c408,418
< 										 PCI_LATENCY_TIMER, &pci_latency);
---
> 					PCI_MIN_GNT, &pci_mingnt);
> 				pcibios_read_config_byte(pci_bus, pci_device_fn,
> 					PCI_MAX_LAT, &pci_maxlat);
> 				pcibios_write_config_byte(pci_bus, pci_device_fn,
> 					PCI_MIN_GNT, pci_mingnt*2);
> 				pcibios_write_config_byte(pci_bus, pci_device_fn,
> 					PCI_MAX_LAT, pci_maxlat*2);
> 				pcibios_read_config_byte(pci_bus, pci_device_fn,
> 					PCI_LATENCY_TIMER, &pci_latency);
> 				printk("MinGnt=%d MaxLat=%d Latency=%d\n",pci_mingnt,pci_maxlat,pci_latency);
> 
434c424,425
< 											  PCI_LATENCY_TIMER, 255);
---
> 						  PCI_LATENCY_TIMER, 255);
> 
436d426
< #endif  /* VORTEX_BUS_MASTER */
438,439c428
< 									dev && dev->mem_start ? dev->mem_start
< 									: options[cards_found]);
---
> 					dev && dev->mem_start ? dev->mem_start : options[cards_found]);
482,511d470
< #ifdef MODULE
< 	/* Allocate and fill new device structure. */
< 	int dev_size = sizeof(struct device) +
< 		sizeof(struct vortex_private);
< 	
< 	dev = (struct device *) kmalloc(dev_size, GFP_KERNEL);
< 	memset(dev, 0, dev_size);
< 	dev->priv = ((void *)dev) + sizeof(struct device);
< 	vp = (struct vortex_private *)dev->priv;
< 	dev->name = vp->devname; /* An empty string. */
< 	dev->base_addr = ioaddr;
< 	dev->irq = irq;
< 	dev->init = vortex_probe1;
< 	vp->product_name = product_names[product_index];
< 	vp->options = options;
< 	if (options >= 0) {
< 		vp->media_override = ((options & 7) == 2)  ?  0  :  options & 7;
< 		vp->full_duplex = (options & 8) ? 1 : 0;
< 		vp->bus_master = (options & 16) ? 1 : 0;
< 	} else {
< 		vp->media_override = 7;
< 		vp->full_duplex = 0;
< 		vp->bus_master = 0;
< 	}
< 	ether_setup(dev);
< 	vp->next_module = root_vortex_dev;
< 	root_vortex_dev = dev;
< 	if (register_netdev(dev) != 0)
< 		return -EIO;
< #else  /* not a MODULE */
522,530c481,484
< 	if (options >= 0) {
< 		vp->media_override = ((options & 7) == 2)  ?  0  :  options & 7;
< 		vp->full_duplex = (options & 8) ? 1 : 0;
< 		vp->bus_master = (options & 16) ? 1 : 0;
< 	} else {
< 		vp->media_override = 7;
< 		vp->full_duplex = 0;
< 		vp->bus_master = 0;
< 	}
---
> 
> 	vp->media_override = 7;
> 	vp->full_duplex = 1;
> 	vp->bus_master = 1;
533d486
< #endif /* MODULE */
541c494
< 	int i;
---
> 	int i,timer,swinfo;
550d502
< 		int timer;
559a512
> 	
586a540,541
> 	outw(SetIntrEnb+0x3fe,ioaddr+EL3_CMD); /* Enable all interrupts */
> 
730a686
> 	
737,740c693,700
< #ifdef MODULE
< 	MOD_INC_USE_COUNT;
< #endif
< 
---
> 	/* Set TxStartThreshold */
> 	outw(SetTxStart + (txstart>>2), ioaddr + EL3_CMD);
> 	/* Set RxEarlyThreshold */
> 	outw(SetRxThreshold + (rxstart>>2), ioaddr + EL3_CMD);
> 	/* Set TxAvailable Threshold */
> /*
> 	outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
> */
842,843c802
< 		if (tickssofar < 2)		/* We probably aren't empty. */
< 			return 1;
---
> 		if (tickssofar < TX_TIMEOUT-2 ) return 1;
846,847c805,808
< 			if (inw(ioaddr + TxFree) > skb->len)
< 			  break;
---
> 			if (inw(ioaddr + TxFree) > skb->len) {
> 				printk("FIFO was not full\n");
> 				break;
> 			}	
877,878c838,839
< #ifdef VORTEX_BUS_MASTER
< 	if (vp->bus_master) {
---
> 	if (skb->len>1000) {
> 		SLOW_DOWN_IO; SLOW_DOWN_IO; SLOW_DOWN_IO;
880,881c841,842
< 		outl((int)(skb->data), ioaddr + Wn7_MasterAddr);
< 		outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
---
> 		outl_p((int)(skb->data), ioaddr + Wn7_MasterAddr);
> 		outw_p((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
883c844
< 		outw(StartDMADown, ioaddr + EL3_CMD);
---
> 		outw_p(StartDMADown, ioaddr + EL3_CMD);
895,904d855
< #else
< 	/* ... and the packet rounded to a doubleword. */
< 	outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
< 	dev_kfree_skb (skb, FREE_WRITE);
< 	if (inw(ioaddr + TxFree) > 1536) {
< 		dev->tbusy = 0;
< 	} else
< 		/* Interrupt us when the FIFO has room for max-sized packet. */
< 		outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
< #endif  /* bus master */
921c872,876
< 					int j;
---
> 					if (tx_status&0x10) {
> 						txstart+=32;
> 						outw(SetTxStart + (txstart>>2), ioaddr + EL3_CMD);
> 						printk("Reseted TxStartThreshold to %d\n",txstart);
> 					}	
923c878
< 					for (j = 20; j >= 0 ; j--)
---
> 					for (;;)
982c937
< 		if (status & RxComplete)
---
> 		if (status & RxEarly) {
983a939,941
> 			outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
> 		}
> 		else if (status & RxComplete) vortex_rx(dev);
986,987c944
< 			if (vortex_debug > 5)
< 				printk("	TX room bit was handled.\n");
---
> 			printk("TX room bit was handled.\n");
990a948
> 			outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
993d950
< #ifdef VORTEX_BUS_MASTER
995,998c952,986
< 			outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
< 			dev->tbusy = 0;
< 			dev_kfree_skb (lp->tx_skb, FREE_WRITE); /* Release the transfered buffer */
< 			mark_bh(NET_BH);
---
> 			int ms,msr=0;
> 			ms=inw(ioaddr+Wn7_MasterStatus);
> 			if (ms&0x0001) {
> 				printk("masterAbort!\n");
> 				msr|=0x0001;
> 			}	
> 			if (ms&0x0002) {
> 				printk("targetAbort!\n");
> 				msr|=0x0002;
> 				outw(TotalReset+0x40,ioaddr+EL3_CMD);
> 			}	
> 			if (ms&0x0004) {
> 				msr|=0x0004;
> 			}	
> 			if (ms&0x0008) {
> 				msr|=0x0008;
> 			}	
> 			if (ms&0x1000) {
> 				msr|=0x1000;
> 				dev->tbusy = 0;
> 				dev_kfree_skb (lp->tx_skb, FREE_WRITE); /* Release the transfered buffer */
> 				mark_bh(NET_BH);
> 			}	
> 			if (ms&0x4000) {
> 				printk("Whoops: masterUpload!!!!!!\n");
> 				msr|=0x4000;
> 				/*
> 				mark_bh(NET_BH);
> 				*/
> 			}	
> 			SLOW_DOWN_IO; SLOW_DOWN_IO; SLOW_DOWN_IO;
> 			outw_p(msr,ioaddr+Wn7_MasterStatus); /* Ack the event. */
> /*
> 			outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
> */
1000,1001c988
< #endif
< 		if (status & (AdapterFailure | RxEarly | StatsFull)) {
---
> 		if (status & (AdapterFailure | StatsFull)) {
1003,1006d989
< 			if (status & RxEarly) {				/* Rx early is unused. */
< 				vortex_rx(dev);
< 				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
< 			}
1051d1033
< 
1167,1169d1148
< #ifdef MODULE
< 	MOD_DEC_USE_COUNT;
< #endif
1271,1289d1249
< 
< #ifdef MODULE
< void
< cleanup_module(void)
< {
< 	struct device *next_dev;
< 
< 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
< 	while (root_vortex_dev) {
< 		next_dev = ((struct vortex_private *)root_vortex_dev->priv)->next_module;
< 		unregister_netdev(root_vortex_dev);
< 		outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD);
< 		release_region(root_vortex_dev->base_addr, VORTEX_TOTAL_SIZE);
< 		kfree(root_vortex_dev);
< 		root_vortex_dev = next_dev;
< 	}
< }
< #endif /* MODULE */
< 

Phillip Dillinger phillip.dillinger@sealabs.com