1755 lines · 43.0 KB · C
RawDownload
/* * rrunner.c: Linux driver for the Essential RoadRunner HIPPI board. * * Copyright (C) 1998-2002 by Jes Sorensen, <jes@wildopensource.com>. * * Thanks to Essential Communication for providing us with hardware * and very comprehensive documentation without which I would not have * been able to write this driver. A special thank you to John Gibbon * for sorting out the legal issues, with the NDA, allowing the code to * be released under the GPL. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Thanks to Jayaram Bhat from ODS/Essential for fixing some of the * stupid bugs in my code. * * Softnet support and various other patches from Val Henson of * ODS/Essential. * * PCI DMA mapping code partly based on work by Francois Romieu. */  #define DEBUG 1#define RX_DMA_SKBUFF 1#define PKT_COPY_THRESHOLD 512 #include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/pci.h>#include <linux/kernel.h>#include <linux/netdevice.h>#include <linux/hippidevice.h>#include <linux/skbuff.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/mm.h>#include <net/sock.h> #include <asm/system.h>#include <asm/cache.h>#include <asm/byteorder.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/uaccess.h> #define rr_if_busy(dev)     netif_queue_stopped(dev)#define rr_if_running(dev)  netif_running(dev) #include "rrunner.h" #define RUN_AT(x) (jiffies + (x))  MODULE_AUTHOR("Jes Sorensen <jes@wildopensource.com>");MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");MODULE_LICENSE("GPL"); static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002  Jes Sorensen (jes@wildopensource.com)\n"; /* * Implementation notes: * * The DMA engine only allows for DMA within physical 64KB chunks of * memory. The current approach of the driver (and stack) is to use * linear blocks of memory for the skbuffs. However, as the data block * is always the first part of the skb and skbs are 2^n aligned so we * are guarantted to get the whole block within one 64KB align 64KB * chunk. * * On the long term, relying on being able to allocate 64KB linear * chunks of memory is not feasible and the skb handling code and the * stack will need to know about I/O vectors or something similar. */ /* * These are checked at init time to see if they are at least 256KB * and increased to 256KB if they are not. This is done to avoid ending * up with socket buffers smaller than the MTU size, */extern __u32 sysctl_wmem_max;extern __u32 sysctl_rmem_max; static int __devinit rr_init_one(struct pci_dev *pdev,	const struct pci_device_id *ent){	struct net_device *dev;	static int version_disp;	u8 pci_latency;	struct rr_private *rrpriv;	void *tmpptr;	dma_addr_t ring_dma;	int ret = -ENOMEM; 	dev = alloc_hippi_dev(sizeof(struct rr_private));	if (!dev)		goto out3; 	ret = pci_enable_device(pdev);	if (ret) {		ret = -ENODEV;		goto out2;	} 	rrpriv = netdev_priv(dev); 	SET_MODULE_OWNER(dev);	SET_NETDEV_DEV(dev, &pdev->dev); 	if (pci_request_regions(pdev, "rrunner")) {		ret = -EIO;		goto out;	} 	pci_set_drvdata(pdev, dev); 	rrpriv->pci_dev = pdev; 	spin_lock_init(&rrpriv->lock); 	dev->irq = pdev->irq;	dev->open = &rr_open;	dev->hard_start_xmit = &rr_start_xmit;	dev->stop = &rr_close;	dev->get_stats = &rr_get_stats;	dev->do_ioctl = &rr_ioctl; 	dev->base_addr = pci_resource_start(pdev, 0); 	/* display version info if adapter is found */	if (!version_disp) {		/* set display flag to TRUE so that */		/* we only display this string ONCE */		version_disp = 1;		printk(version);	} 	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);	if (pci_latency <= 0x58){		pci_latency = 0x58;		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, pci_latency);	} 	pci_set_master(pdev); 	printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI "	       "at 0x%08lx, irq %i, PCI latency %i\n", dev->name,	       dev->base_addr, dev->irq, pci_latency); 	/*	 * Remap the regs into kernel space.	 */ 	rrpriv->regs = ioremap(dev->base_addr, 0x1000); 	if (!rrpriv->regs){		printk(KERN_ERR "%s:  Unable to map I/O register, "			"RoadRunner will be disabled.\n", dev->name);		ret = -EIO;		goto out;	} 	tmpptr = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);	rrpriv->tx_ring = tmpptr;	rrpriv->tx_ring_dma = ring_dma; 	if (!tmpptr) {		ret = -ENOMEM;		goto out;	} 	tmpptr = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);	rrpriv->rx_ring = tmpptr;	rrpriv->rx_ring_dma = ring_dma; 	if (!tmpptr) {		ret = -ENOMEM;		goto out;	} 	tmpptr = pci_alloc_consistent(pdev, EVT_RING_SIZE, &ring_dma);	rrpriv->evt_ring = tmpptr;	rrpriv->evt_ring_dma = ring_dma; 	if (!tmpptr) {		ret = -ENOMEM;		goto out;	} 	/*	 * Don't access any register before this point!	 */#ifdef __BIG_ENDIAN	writel(readl(&rrpriv->regs->HostCtrl) | NO_SWAP,		&rrpriv->regs->HostCtrl);#endif	/*	 * Need to add a case for little-endian 64-bit hosts here.	 */ 	rr_init(dev); 	dev->base_addr = 0; 	ret = register_netdev(dev);	if (ret)		goto out;	return 0;  out:	if (rrpriv->rx_ring)		pci_free_consistent(pdev, RX_TOTAL_SIZE, rrpriv->rx_ring, 				    rrpriv->rx_ring_dma);	if (rrpriv->tx_ring)		pci_free_consistent(pdev, TX_TOTAL_SIZE, rrpriv->tx_ring,				    rrpriv->tx_ring_dma);	if (rrpriv->regs)		iounmap(rrpriv->regs);		if (pdev) {		pci_release_regions(pdev);		pci_set_drvdata(pdev, NULL);	} out2:	free_netdev(dev); out3:	return ret;} static void __devexit rr_remove_one (struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev); 	if (dev) {		struct rr_private *rr = netdev_priv(dev); 		if (!(readl(&rr->regs->HostCtrl) & NIC_HALTED)){			printk(KERN_ERR "%s: trying to unload running NIC\n",			       dev->name);			writel(HALT_NIC, &rr->regs->HostCtrl);		} 		pci_free_consistent(pdev, EVT_RING_SIZE, rr->evt_ring,				    rr->evt_ring_dma);		pci_free_consistent(pdev, RX_TOTAL_SIZE, rr->rx_ring,				    rr->rx_ring_dma);		pci_free_consistent(pdev, TX_TOTAL_SIZE, rr->tx_ring,				    rr->tx_ring_dma);		unregister_netdev(dev);		iounmap(rr->regs);		free_netdev(dev);		pci_release_regions(pdev);		pci_disable_device(pdev);		pci_set_drvdata(pdev, NULL);	}}  /* * Commands are considered to be slow, thus there is no reason to * inline this. */static void rr_issue_cmd(struct rr_private *rrpriv, struct cmd *cmd){	struct rr_regs __iomem *regs;	u32 idx; 	regs = rrpriv->regs;	/*	 * This is temporary - it will go away in the final version.	 * We probably also want to make this function inline.	 */	if (readl(&regs->HostCtrl) & NIC_HALTED){		printk("issuing command for halted NIC, code 0x%x, "		       "HostCtrl %08x\n", cmd->code, readl(&regs->HostCtrl));		if (readl(&regs->Mode) & FATAL_ERR)			printk("error codes Fail1 %02x, Fail2 %02x\n",			       readl(&regs->Fail1), readl(&regs->Fail2));	} 	idx = rrpriv->info->cmd_ctrl.pi; 	writel(*(u32*)(cmd), &regs->CmdRing[idx]);	wmb(); 	idx = (idx - 1) % CMD_RING_ENTRIES;	rrpriv->info->cmd_ctrl.pi = idx;	wmb(); 	if (readl(&regs->Mode) & FATAL_ERR)		printk("error code %02x\n", readl(&regs->Fail1));}  /* * Reset the board in a sensible manner. The NIC is already halted * when we get here and a spin-lock is held. */static int rr_reset(struct net_device *dev){	struct rr_private *rrpriv;	struct rr_regs __iomem *regs;	struct eeprom *hw = NULL;	u32 start_pc;	int i; 	rrpriv = netdev_priv(dev);	regs = rrpriv->regs; 	rr_load_firmware(dev); 	writel(0x01000000, &regs->TX_state);	writel(0xff800000, &regs->RX_state);	writel(0, &regs->AssistState);	writel(CLEAR_INTA, &regs->LocalCtrl);	writel(0x01, &regs->BrkPt);	writel(0, &regs->Timer);	writel(0, &regs->TimerRef);	writel(RESET_DMA, &regs->DmaReadState);	writel(RESET_DMA, &regs->DmaWriteState);	writel(0, &regs->DmaWriteHostHi);	writel(0, &regs->DmaWriteHostLo);	writel(0, &regs->DmaReadHostHi);	writel(0, &regs->DmaReadHostLo);	writel(0, &regs->DmaReadLen);	writel(0, &regs->DmaWriteLen);	writel(0, &regs->DmaWriteLcl);	writel(0, &regs->DmaWriteIPchecksum);	writel(0, &regs->DmaReadLcl);	writel(0, &regs->DmaReadIPchecksum);	writel(0, &regs->PciState);#if (BITS_PER_LONG == 64) && defined __LITTLE_ENDIAN	writel(SWAP_DATA | PTR64BIT | PTR_WD_SWAP, &regs->Mode);#elif (BITS_PER_LONG == 64)	writel(SWAP_DATA | PTR64BIT | PTR_WD_NOSWAP, &regs->Mode);#else	writel(SWAP_DATA | PTR32BIT | PTR_WD_NOSWAP, &regs->Mode);#endif #if 0	/*	 * Don't worry, this is just black magic.	 */	writel(0xdf000, &regs->RxBase);	writel(0xdf000, &regs->RxPrd);	writel(0xdf000, &regs->RxCon);	writel(0xce000, &regs->TxBase);	writel(0xce000, &regs->TxPrd);	writel(0xce000, &regs->TxCon);	writel(0, &regs->RxIndPro);	writel(0, &regs->RxIndCon);	writel(0, &regs->RxIndRef);	writel(0, &regs->TxIndPro);	writel(0, &regs->TxIndCon);	writel(0, &regs->TxIndRef);	writel(0xcc000, &regs->pad10[0]);	writel(0, &regs->DrCmndPro);	writel(0, &regs->DrCmndCon);	writel(0, &regs->DwCmndPro);	writel(0, &regs->DwCmndCon);	writel(0, &regs->DwCmndRef);	writel(0, &regs->DrDataPro);	writel(0, &regs->DrDataCon);	writel(0, &regs->DrDataRef);	writel(0, &regs->DwDataPro);	writel(0, &regs->DwDataCon);	writel(0, &regs->DwDataRef);#endif 	writel(0xffffffff, &regs->MbEvent);	writel(0, &regs->Event); 	writel(0, &regs->TxPi);	writel(0, &regs->IpRxPi); 	writel(0, &regs->EvtCon);	writel(0, &regs->EvtPrd); 	rrpriv->info->evt_ctrl.pi = 0; 	for (i = 0; i < CMD_RING_ENTRIES; i++)		writel(0, &regs->CmdRing[i]); /* * Why 32 ? is this not cache line size dependent? */	writel(RBURST_64|WBURST_64, &regs->PciState);	wmb(); 	start_pc = rr_read_eeprom_word(rrpriv, &hw->rncd_info.FwStart); #if (DEBUG > 1)	printk("%s: Executing firmware at address 0x%06x\n",	       dev->name, start_pc);#endif 	writel(start_pc + 0x800, &regs->Pc);	wmb();	udelay(5); 	writel(start_pc, &regs->Pc);	wmb(); 	return 0;}  /* * Read a string from the EEPROM. */static unsigned int rr_read_eeprom(struct rr_private *rrpriv,				unsigned long offset,				unsigned char *buf,				unsigned long length){	struct rr_regs __iomem *regs = rrpriv->regs;	u32 misc, io, host, i; 	io = readl(&regs->ExtIo);	writel(0, &regs->ExtIo);	misc = readl(&regs->LocalCtrl);	writel(0, &regs->LocalCtrl);	host = readl(&regs->HostCtrl);	writel(host | HALT_NIC, &regs->HostCtrl);	mb(); 	for (i = 0; i < length; i++){		writel((EEPROM_BASE + ((offset+i) << 3)), &regs->WinBase);		mb();		buf[i] = (readl(&regs->WinData) >> 24) & 0xff;		mb();	} 	writel(host, &regs->HostCtrl);	writel(misc, &regs->LocalCtrl);	writel(io, &regs->ExtIo);	mb();	return i;}  /* * Shortcut to read one word (4 bytes) out of the EEPROM and convert * it to our CPU byte-order. */static u32 rr_read_eeprom_word(struct rr_private *rrpriv,			    void * offset){	u32 word; 	if ((rr_read_eeprom(rrpriv, (unsigned long)offset,			    (char *)&word, 4) == 4))		return be32_to_cpu(word);	return 0;}  /* * Write a string to the EEPROM. * * This is only called when the firmware is not running. */static unsigned int write_eeprom(struct rr_private *rrpriv,				 unsigned long offset,				 unsigned char *buf,				 unsigned long length){	struct rr_regs __iomem *regs = rrpriv->regs;	u32 misc, io, data, i, j, ready, error = 0; 	io = readl(&regs->ExtIo);	writel(0, &regs->ExtIo);	misc = readl(&regs->LocalCtrl);	writel(ENABLE_EEPROM_WRITE, &regs->LocalCtrl);	mb(); 	for (i = 0; i < length; i++){		writel((EEPROM_BASE + ((offset+i) << 3)), &regs->WinBase);		mb();		data = buf[i] << 24;		/*		 * Only try to write the data if it is not the same		 * value already.		 */		if ((readl(&regs->WinData) & 0xff000000) != data){			writel(data, &regs->WinData);			ready = 0;			j = 0;			mb();			while(!ready){				udelay(20);				if ((readl(&regs->WinData) & 0xff000000) ==				    data)					ready = 1;				mb();

Lines 1–500 of 1755.