brintos

brintos / linux-shallow public Read only

0
0
Text · 16.8 KiB · 84b300f Raw
578 lines · c
1/* mac89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. */2/*3	Written 1996 by Russell Nelson, with reference to skeleton.c4	written 1993-1994 by Donald Becker.5 6	This software may be used and distributed according to the terms7	of the GNU General Public License, incorporated herein by reference.8 9	The author may be reached at nelson@crynwr.com, Crynwr10	Software, 11 Grant St., Potsdam, NY 1367611 12  Changelog:13 14  Mike Cruse        : mcruse@cti-ltd.com15                    : Changes for Linux 2.0 compatibility.16                    : Added dev_id parameter in net_interrupt(),17                    : request_irq() and free_irq(). Just NULL for now.18 19  Mike Cruse        : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros20                    : in net_open() and net_close() so kerneld would know21                    : that the module is in use and wouldn't eject the22                    : driver prematurely.23 24  Mike Cruse        : Rewrote init_module() and cleanup_module using 8390.c25                    : as an example. Disabled autoprobing in init_module(),26                    : not a good thing to do to other devices while Linux27                    : is running from all accounts.28 29  Alan Cox          : Removed 1.2 support, added 2.1 extra counters.30 31  David Huggins-Daines <dhd@debian.org>32 33  Split this off into mac89x0.c, and gutted it of all parts which are34  not relevant to the existing CS8900 cards on the Macintosh35  (i.e. basically the Daynaport CS and LC cards).  To be precise:36 37    * Removed all the media-detection stuff, because these cards are38    TP-only.39 40    * Lobotomized the ISA interrupt bogosity, because these cards use41    a hardwired NuBus interrupt and a magic ISAIRQ value in the card.42 43    * Basically eliminated everything not relevant to getting the44    cards minimally functioning on the Macintosh.45 46  I might add that these cards are badly designed even from the Mac47  standpoint, in that Dayna, in their infinite wisdom, used NuBus slot48  I/O space and NuBus interrupts for these cards, but neglected to49  provide anything even remotely resembling a NuBus ROM.  Therefore we50  have to probe for them in a brain-damaged ISA-like fashion.51 52  Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 11/01/200153  check kmalloc and release the allocated memory on failure in54  mac89x0_probe and in init_module55  use local_irq_{save,restore}(flags) in net_get_stat, not just56  local_irq_{dis,en}able()57*/58 59#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt60 61static const char version[] =62"cs89x0.c:v1.02 11/26/96 Russell Nelson <nelson@crynwr.com>\n";63 64#include <linux/module.h>65 66/*67  Sources:68 69	Crynwr packet driver epktisa.70 71	Crystal Semiconductor data sheets.72 73*/74 75#include <linux/kernel.h>76#include <linux/types.h>77#include <linux/fcntl.h>78#include <linux/interrupt.h>79#include <linux/ioport.h>80#include <linux/in.h>81#include <linux/string.h>82#include <linux/nubus.h>83#include <linux/errno.h>84#include <linux/init.h>85#include <linux/netdevice.h>86#include <linux/platform_device.h>87#include <linux/etherdevice.h>88#include <linux/skbuff.h>89#include <linux/delay.h>90#include <linux/bitops.h>91#include <linux/gfp.h>92 93#include <asm/io.h>94#include <asm/hwtest.h>95#include <asm/macints.h>96 97#include "cs89x0.h"98 99static int debug = -1;100module_param(debug, int, 0);101MODULE_PARM_DESC(debug, "debug message level");102 103/* Information that need to be kept for each board. */104struct net_local {105	int msg_enable;106	int chip_type;		/* one of: CS8900, CS8920, CS8920M */107	char chip_revision;	/* revision letter of the chip ('A'...) */108	int send_cmd;		/* the propercommand used to send a packet. */109	int rx_mode;110	int curr_rx_cfg;111        int send_underrun;      /* keep track of how many underruns in a row we get */112};113 114/* Index to functions, as function prototypes. */115static int net_open(struct net_device *dev);116static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);117static irqreturn_t net_interrupt(int irq, void *dev_id);118static void set_multicast_list(struct net_device *dev);119static void net_rx(struct net_device *dev);120static int net_close(struct net_device *dev);121static struct net_device_stats *net_get_stats(struct net_device *dev);122static int set_mac_address(struct net_device *dev, void *addr);123 124/* For reading/writing registers ISA-style */125static inline int126readreg_io(struct net_device *dev, int portno)127{128	nubus_writew(swab16(portno), dev->base_addr + ADD_PORT);129	return swab16(nubus_readw(dev->base_addr + DATA_PORT));130}131 132static inline void133writereg_io(struct net_device *dev, int portno, int value)134{135	nubus_writew(swab16(portno), dev->base_addr + ADD_PORT);136	nubus_writew(swab16(value), dev->base_addr + DATA_PORT);137}138 139/* These are for reading/writing registers in shared memory */140static inline int141readreg(struct net_device *dev, int portno)142{143	return swab16(nubus_readw(dev->mem_start + portno));144}145 146static inline void147writereg(struct net_device *dev, int portno, int value)148{149	nubus_writew(swab16(value), dev->mem_start + portno);150}151 152static const struct net_device_ops mac89x0_netdev_ops = {153	.ndo_open		= net_open,154	.ndo_stop		= net_close,155	.ndo_start_xmit		= net_send_packet,156	.ndo_get_stats		= net_get_stats,157	.ndo_set_rx_mode	= set_multicast_list,158	.ndo_set_mac_address	= set_mac_address,159	.ndo_validate_addr	= eth_validate_addr,160};161 162/* Probe for the CS8900 card in slot E.  We won't bother looking163   anywhere else until we have a really good reason to do so. */164static int mac89x0_device_probe(struct platform_device *pdev)165{166	struct net_device *dev;167	struct net_local *lp;168	int i, slot;169	unsigned rev_type = 0;170	unsigned long ioaddr;171	unsigned short sig;172	int err = -ENODEV;173	struct nubus_rsrc *fres;174 175	dev = alloc_etherdev(sizeof(struct net_local));176	if (!dev)177		return -ENOMEM;178 179	/* We might have to parameterize this later */180	slot = 0xE;181	/* Get out now if there's a real NuBus card in slot E */182	for_each_func_rsrc(fres)183		if (fres->board->slot == slot)184			goto out;185 186	/* The pseudo-ISA bits always live at offset 0x300 (gee,187           wonder why...) */188	ioaddr = (unsigned long)189		nubus_slot_addr(slot) | (((slot&0xf) << 20) + DEFAULTIOBASE);190	{191		int card_present;192 193		card_present = (hwreg_present((void *)ioaddr + 4) &&194				hwreg_present((void *)ioaddr + DATA_PORT));195		if (!card_present)196			goto out;197	}198 199	nubus_writew(0, ioaddr + ADD_PORT);200	sig = nubus_readw(ioaddr + DATA_PORT);201	if (sig != swab16(CHIP_EISA_ID_SIG))202		goto out;203 204	SET_NETDEV_DEV(dev, &pdev->dev);205 206	/* Initialize the net_device structure. */207	lp = netdev_priv(dev);208 209	lp->msg_enable = netif_msg_init(debug, 0);210 211	/* Fill in the 'dev' fields. */212	dev->base_addr = ioaddr;213	dev->mem_start = (unsigned long)214		nubus_slot_addr(slot) | (((slot&0xf) << 20) + MMIOBASE);215	dev->mem_end = dev->mem_start + 0x1000;216 217	/* Turn on shared memory */218	writereg_io(dev, PP_BusCTL, MEMORY_ON);219 220	/* get the chip type */221	rev_type = readreg(dev, PRODUCT_ID_ADD);222	lp->chip_type = rev_type &~ REVISON_BITS;223	lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';224 225	/* Check the chip type and revision in order to set the correct send command226	CS8920 revision C and CS8900 revision F can use the faster send. */227	lp->send_cmd = TX_AFTER_381;228	if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')229		lp->send_cmd = TX_NOW;230	if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')231		lp->send_cmd = TX_NOW;232 233	netif_dbg(lp, drv, dev, "%s", version);234 235	pr_info("cs89%c0%s rev %c found at %#8lx\n",236		lp->chip_type == CS8900 ? '0' : '2',237		lp->chip_type == CS8920M ? "M" : "",238		lp->chip_revision, dev->base_addr);239 240	/* Try to read the MAC address */241	if ((readreg(dev, PP_SelfST) & (EEPROM_PRESENT | EEPROM_OK)) == 0) {242		pr_info("No EEPROM, giving up now.\n");243		goto out1;244        } else {245		u8 addr[ETH_ALEN];246 247                for (i = 0; i < ETH_ALEN; i += 2) {248			/* Big-endian (why??!) */249			unsigned short s = readreg(dev, PP_IA + i);250			addr[i] = s >> 8;251			addr[i+1] = s & 0xff;252                }253		eth_hw_addr_set(dev, addr);254        }255 256	dev->irq = SLOT2IRQ(slot);257 258	/* print the IRQ and ethernet address. */259 260	pr_info("MAC %pM, IRQ %d\n", dev->dev_addr, dev->irq);261 262	dev->netdev_ops		= &mac89x0_netdev_ops;263 264	err = register_netdev(dev);265	if (err)266		goto out1;267 268	platform_set_drvdata(pdev, dev);269	return 0;270out1:271	nubus_writew(0, dev->base_addr + ADD_PORT);272out:273	free_netdev(dev);274	return err;275}276 277/* Open/initialize the board.  This is called (in the current kernel)278   sometime after booting when the 'ifconfig' program is run.279 280   This routine should set everything up anew at each open, even281   registers that "should" only need to be set once at boot, so that282   there is non-reboot way to recover if something goes wrong.283   */284static int285net_open(struct net_device *dev)286{287	struct net_local *lp = netdev_priv(dev);288	int i;289 290	/* Disable the interrupt for now */291	writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) & ~ENABLE_IRQ);292 293	/* Grab the interrupt */294	if (request_irq(dev->irq, net_interrupt, 0, "cs89x0", dev))295		return -EAGAIN;296 297	/* Set up the IRQ - Apparently magic */298	if (lp->chip_type == CS8900)299		writereg(dev, PP_CS8900_ISAINT, 0);300	else301		writereg(dev, PP_CS8920_ISAINT, 0);302 303	/* set the Ethernet address */304	for (i=0; i < ETH_ALEN/2; i++)305		writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));306 307	/* Turn on both receive and transmit operations */308	writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);309 310	/* Receive only error free packets addressed to this card */311	lp->rx_mode = 0;312	writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);313 314	lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;315 316	writereg(dev, PP_RxCFG, lp->curr_rx_cfg);317 318	writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |319	       TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);320 321	writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |322		 TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);323 324	/* now that we've got our act together, enable everything */325	writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ);326	netif_start_queue(dev);327	return 0;328}329 330static netdev_tx_t331net_send_packet(struct sk_buff *skb, struct net_device *dev)332{333	struct net_local *lp = netdev_priv(dev);334	unsigned long flags;335 336	netif_dbg(lp, tx_queued, dev, "sent %d byte packet of type %x\n",337		  skb->len, skb->data[ETH_ALEN + ETH_ALEN] << 8 |338		  skb->data[ETH_ALEN + ETH_ALEN + 1]);339 340	/* keep the upload from being interrupted, since we341	   ask the chip to start transmitting before the342	   whole packet has been completely uploaded. */343	local_irq_save(flags);344	netif_stop_queue(dev);345 346	/* initiate a transmit sequence */347	writereg(dev, PP_TxCMD, lp->send_cmd);348	writereg(dev, PP_TxLength, skb->len);349 350	/* Test to see if the chip has allocated memory for the packet */351	if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {352		/* Gasp!  It hasn't.  But that shouldn't happen since353		   we're waiting for TxOk, so return 1 and requeue this packet. */354		local_irq_restore(flags);355		return NETDEV_TX_BUSY;356	}357 358	/* Write the contents of the packet */359	skb_copy_from_linear_data(skb, (void *)(dev->mem_start + PP_TxFrame),360				  skb->len+1);361 362	local_irq_restore(flags);363	dev_kfree_skb (skb);364 365	return NETDEV_TX_OK;366}367 368/* The typical workload of the driver:369   Handle the network interface interrupts. */370static irqreturn_t net_interrupt(int irq, void *dev_id)371{372	struct net_device *dev = dev_id;373	struct net_local *lp;374	int ioaddr, status;375 376	ioaddr = dev->base_addr;377	lp = netdev_priv(dev);378 379	/* we MUST read all the events out of the ISQ, otherwise we'll never380           get interrupted again.  As a consequence, we can't have any limit381           on the number of times we loop in the interrupt handler.  The382           hardware guarantees that eventually we'll run out of events.  Of383           course, if you're on a slow machine, and packets are arriving384           faster than you can read them off, you're screwed.  Hasta la385           vista, baby!  */386	while ((status = swab16(nubus_readw(dev->base_addr + ISQ_PORT)))) {387		netif_dbg(lp, intr, dev, "status=%04x\n", status);388		switch(status & ISQ_EVENT_MASK) {389		case ISQ_RECEIVER_EVENT:390			/* Got a packet(s). */391			net_rx(dev);392			break;393		case ISQ_TRANSMITTER_EVENT:394			dev->stats.tx_packets++;395			netif_wake_queue(dev);396			if ((status & TX_OK) == 0)397				dev->stats.tx_errors++;398			if (status & TX_LOST_CRS)399				dev->stats.tx_carrier_errors++;400			if (status & TX_SQE_ERROR)401				dev->stats.tx_heartbeat_errors++;402			if (status & TX_LATE_COL)403				dev->stats.tx_window_errors++;404			if (status & TX_16_COL)405				dev->stats.tx_aborted_errors++;406			break;407		case ISQ_BUFFER_EVENT:408			if (status & READY_FOR_TX) {409				/* we tried to transmit a packet earlier,410                                   but inexplicably ran out of buffers.411                                   That shouldn't happen since we only ever412                                   load one packet.  Shrug.  Do the right413                                   thing anyway. */414				netif_wake_queue(dev);415			}416			if (status & TX_UNDERRUN) {417				netif_dbg(lp, tx_err, dev, "transmit underrun\n");418                                lp->send_underrun++;419                                if (lp->send_underrun == 3) lp->send_cmd = TX_AFTER_381;420                                else if (lp->send_underrun == 6) lp->send_cmd = TX_AFTER_ALL;421                        }422			break;423		case ISQ_RX_MISS_EVENT:424			dev->stats.rx_missed_errors += (status >> 6);425			break;426		case ISQ_TX_COL_EVENT:427			dev->stats.collisions += (status >> 6);428			break;429		}430	}431	return IRQ_HANDLED;432}433 434/* We have a good packet(s), get it/them out of the buffers. */435static void436net_rx(struct net_device *dev)437{438	struct net_local *lp = netdev_priv(dev);439	struct sk_buff *skb;440	int status, length;441 442	status = readreg(dev, PP_RxStatus);443	if ((status & RX_OK) == 0) {444		dev->stats.rx_errors++;445		if (status & RX_RUNT)446				dev->stats.rx_length_errors++;447		if (status & RX_EXTRA_DATA)448				dev->stats.rx_length_errors++;449		if ((status & RX_CRC_ERROR) &&450		    !(status & (RX_EXTRA_DATA|RX_RUNT)))451			/* per str 172 */452			dev->stats.rx_crc_errors++;453		if (status & RX_DRIBBLE)454				dev->stats.rx_frame_errors++;455		return;456	}457 458	length = readreg(dev, PP_RxLength);459	/* Malloc up new buffer. */460	skb = alloc_skb(length, GFP_ATOMIC);461	if (skb == NULL) {462		dev->stats.rx_dropped++;463		return;464	}465	skb_put(skb, length);466 467	skb_copy_to_linear_data(skb, (void *)(dev->mem_start + PP_RxFrame),468				length);469 470	netif_dbg(lp, rx_status, dev, "received %d byte packet of type %x\n",471		  length, skb->data[ETH_ALEN + ETH_ALEN] << 8 |472		  skb->data[ETH_ALEN + ETH_ALEN + 1]);473 474        skb->protocol=eth_type_trans(skb,dev);475	netif_rx(skb);476	dev->stats.rx_packets++;477	dev->stats.rx_bytes += length;478}479 480/* The inverse routine to net_open(). */481static int482net_close(struct net_device *dev)483{484 485	writereg(dev, PP_RxCFG, 0);486	writereg(dev, PP_TxCFG, 0);487	writereg(dev, PP_BufCFG, 0);488	writereg(dev, PP_BusCTL, 0);489 490	netif_stop_queue(dev);491 492	free_irq(dev->irq, dev);493 494	/* Update the statistics here. */495 496	return 0;497 498}499 500/* Get the current statistics.	This may be called with the card open or501   closed. */502static struct net_device_stats *503net_get_stats(struct net_device *dev)504{505	unsigned long flags;506 507	local_irq_save(flags);508	/* Update the statistics from the device registers. */509	dev->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);510	dev->stats.collisions += (readreg(dev, PP_TxCol) >> 6);511	local_irq_restore(flags);512 513	return &dev->stats;514}515 516static void set_multicast_list(struct net_device *dev)517{518	struct net_local *lp = netdev_priv(dev);519 520	if(dev->flags&IFF_PROMISC)521	{522		lp->rx_mode = RX_ALL_ACCEPT;523	} else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) {524		/* The multicast-accept list is initialized to accept-all, and we525		   rely on higher-level filtering for now. */526		lp->rx_mode = RX_MULTCAST_ACCEPT;527	}528	else529		lp->rx_mode = 0;530 531	writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);532 533	/* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */534	writereg(dev, PP_RxCFG, lp->curr_rx_cfg |535	     (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));536}537 538 539static int set_mac_address(struct net_device *dev, void *addr)540{541	struct sockaddr *saddr = addr;542	int i;543 544	if (!is_valid_ether_addr(saddr->sa_data))545		return -EADDRNOTAVAIL;546 547	eth_hw_addr_set(dev, saddr->sa_data);548	netdev_info(dev, "Setting MAC address to %pM\n", dev->dev_addr);549 550	/* set the Ethernet address */551	for (i=0; i < ETH_ALEN/2; i++)552		writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));553 554	return 0;555}556 557MODULE_DESCRIPTION("Macintosh CS89x0-based Ethernet driver");558MODULE_LICENSE("GPL");559 560static void mac89x0_device_remove(struct platform_device *pdev)561{562	struct net_device *dev = platform_get_drvdata(pdev);563 564	unregister_netdev(dev);565	nubus_writew(0, dev->base_addr + ADD_PORT);566	free_netdev(dev);567}568 569static struct platform_driver mac89x0_platform_driver = {570	.probe = mac89x0_device_probe,571	.remove_new = mac89x0_device_remove,572	.driver = {573		.name = "mac89x0",574	},575};576 577module_platform_driver(mac89x0_platform_driver);578