1/*
2 * Copyright (c) 1998, 1999, Be Incorporated.  All Rights Reserved.
3 * This file may be used under the terms of the Be Sample Code License.
4 */
5
6/*! Ethernet driver: handles PCI NE2000 cards */
7
8#include "etherpci_private.h"
9#include <ether_driver.h>
10
11#include <OS.h>
12#include <KernelExport.h>
13#include <Drivers.h>
14#include <PCI.h>
15
16#include <stdlib.h>
17#include <stdio.h>
18#include <string.h>
19#include <stdarg.h>
20
21#define kDevName "etherpci"
22#define kDevDir "net/" kDevName "/"
23#define DEVNAME_LENGTH		64
24#define MAX_CARDS 			 4			/* maximum number of driver instances */
25
26int32 api_version = B_CUR_DRIVER_API_VERSION;
27
28/* debug flags */
29#define ERR       0x0001
30#define INFO      0x0002
31#define RX        0x0004		/* dump received frames */
32#define TX        0x0008		/* dump transmitted frames */
33#define INTERRUPT 0x0010		/* interrupt calls */
34#define FUNCTION  0x0020		/* function calls */
35#define PCI_IO    0x0040		/* pci reads and writes */
36#define SEQ		  0x0080		/* trasnmit & receive TCP/IP sequence sequence numbers */
37#define WARN	  0x0100		/* Warnings - off on final release */
38
39/* diagnostic debug flags - compile in here or set while running with debugger "AcmeRoadRunner" command */
40#define DEFAULT_DEBUG_FLAGS ( ERR | INFO | WARN | FUNCTION )
41
42//#define TRACE_ETHERPCI
43#ifdef TRACE_ETHERPCI
44#	define ETHER_DEBUG(mask, enabled, format, args...) \
45		do { if (mask & enabled) \
46			dprintf(format , ##args); } while (0)
47#else
48#	define ETHER_DEBUG(mask, enabled, format, args...) ;
49#endif
50
51
52static pci_module_info		*gPCIModInfo;
53static char 				*gDevNameList[MAX_CARDS+1];
54static pci_info 			*gDevList[MAX_CARDS+1];
55static int32 				gOpenMask = 0;
56
57
58/* Driver Entry Points */
59status_t init_hardware(void);
60status_t init_driver(void);
61void uninit_driver(void);
62const char** publish_devices(void);
63device_hooks *find_device(const char *name);
64
65
66
67/*
68 * Define STAY_ON_PAGE_0 if you want the driver to stay on page 0 all the
69 * time.  This is faster than if it has to switch to page 1 to get the
70 * current register to see if there are any more packets.  Reason: the
71 * interrupt handler does not have to do any locking if it knows it is
72 * always on page 0.  I'm not sure why the speed difference is so dramatic,
73 * so perhaps there is actually a bug in page-changing version.
74 *
75 * STAY_ON_PAGE_0 uses a rather dubious technique to avoid changing the
76 * register page and it may not be 100% reliable.  The technique used is to
77 * make sure all ring headers are zeroed out before packets are received
78 * into them.  Then, if you detect a non-zero ring header, you can be pretty
79 * sure that it is another packet.
80 *
81 * We never read the "might-be-a-packet" immediately.  Instead, we just
82 * release a semaphore so that the next read will occur later on enough
83 * so that the ring header information should be completely filled in.
84 *
85 */
86#define STAY_ON_PAGE_0	0
87
88
89/*
90 * We only care about these interrupts in our driver
91 */
92#define INTS_WE_CARE_ABOUT (ISR_RECEIVE | ISR_RECEIVE_ERROR |\
93							ISR_TRANSMIT | ISR_TRANSMIT_ERROR | ISR_COUNTER)
94
95typedef struct etherpci_private {
96	int32			devID; 		/* device identifier: 0-n */
97	pci_info		*pciInfo;
98	uint16			irq;		/* IRQ line */
99	uint32			reg_base;	/* hardware register base address */
100	area_id			ioarea; 	/* Area used for MMIO of hostRegs */
101	int boundary;			/* boundary register value (mirrored) */
102	ether_address_t myaddr;	/* my ethernet address */
103	unsigned nmulti;		/* number of multicast addresses */
104	ether_address_t multi[MAX_MULTI];	/* multicast addresses */
105	sem_id iolock;			/* ethercard io, except interrupt handler */
106	int nonblocking;		/* non-blocking mode */
107#if !STAY_ON_PAGE_0
108	spinlock intrlock;		/* ethercard io, including interrupt handler */
109#endif /* !STAY_ON_PAGE_0 */
110	volatile int interrupted;   /* interrupted system call */
111	sem_id inrw;			/* in read or write function */
112	sem_id ilock;			/* waiting for input */
113	sem_id olock;	 		/* waiting to output */
114
115	/*
116	 * Various statistics
117	 */
118	volatile int ints;	/* total number of interrupts */
119	volatile int rints;	/* read interrupts */
120	volatile int wints;	/* write interrupts */
121	volatile int reads;	/* reads */
122	volatile int writes;	/* writes */
123	volatile int resets;	/* resets */
124	volatile int rerrs;	/* read errors */
125	volatile int werrs;	/* write errors */
126	volatile int interrs;/* unknown interrupts */
127	volatile int frame_errs;	/* frame alignment errors */
128	volatile int crc_errs;	/* crc errors */
129	volatile int frames_lost;/* frames lost due to buffer problems */
130
131	/*
132	 * Most recent values of the error statistics to detect any changes in them
133	 */
134	int rerrs_last;
135	int werrs_last;
136	int interrs_last;
137	int frame_errs_last;
138	int crc_errs_last;
139	int frames_lost_last;
140
141	/* stats from the hardware */
142	int chip_rx_frame_errors;
143	int chip_rx_crc_errors;
144	int chip_rx_missed_errors;
145	/*
146	 * These values are set once and never looked at again.  They are
147	 * almost as good as constants, but they differ for the various
148	 * cards, so we can't set them now.
149	 */
150	int ETHER_BUF_START;
151	int ETHER_BUF_SIZE;
152	int EC_VMEM_PAGE;
153	int EC_VMEM_NPAGES;
154	int EC_RXBUF_START_PAGE;
155	int EC_RXBUF_END_PAGE;
156	int EC_RINGSTART;
157	int EC_RINGSIZE;
158
159	uint32 debug;
160
161} etherpci_private_t;
162
163
164#if __POWERPC__
165
166#define ether_inb(device, offset)  			(*((volatile uint8*)(device->reg_base + (offset)))); __eieio()
167#define ether_inw(device, offset)  			(*((volatile uint16*)(device->reg_base + (offset)))); __eieio()
168#define ether_outb(device, offset, value)  	(*((volatile uint8 *)(device->reg_base + (offset))) = (value)); __eieio()
169#define ether_outw(device, offset, value) 	(*((volatile uint16*)(device->reg_base + (offset))) = (value)); __eieio()
170
171#else /* !PPC */
172
173#define ether_outb(device, offset, value)	(*gPCIModInfo->write_io_8)((device->reg_base + (offset)), (value))
174#define ether_outw(device, offset, value)	(*gPCIModInfo->write_io_16)((device->reg_base + (offset)), (value))
175#define ether_inb(device, offset)			((*gPCIModInfo->read_io_8)(device->reg_base + (offset)))
176#define ether_inw(device, offset)			((*gPCIModInfo->read_io_16)(device->reg_base + (offset)))
177
178#endif
179
180#if 0
181#if __INTEL__
182
183uint8  ether_inb(etherpci_private_t *device, uint32 offset) {
184  	uint8 result;
185	result = ((*gPCIModInfo->read_io_8)(device->reg_base + (offset)));
186	ETHER_DEBUG(PCI_IO, device->debug, " inb(%x) %x \n", offset, result);
187	return result;
188};
189uint16  ether_inw(etherpci_private_t *device, uint32 offset) {
190  	uint16 result;
191	result = ((*gPCIModInfo->read_io_16)(device->reg_base + (offset)));
192	ETHER_DEBUG(PCI_IO, device->debug, " inw(%x) %x \n", offset, result);
193	return result;
194};
195void  ether_outb(etherpci_private_t *device, uint32 offset, uint8 value) {
196	(*gPCIModInfo->write_io_8)((device->reg_base + (offset)), (value));
197	ETHER_DEBUG(PCI_IO, device->debug, " outb(%x) %x \n", offset, value);
198};
199void  ether_outw(etherpci_private_t *device, uint32 offset, uint16 value) {
200	(*gPCIModInfo->write_io_16)((device->reg_base + (offset)), (value));
201	ETHER_DEBUG(PCI_IO, device->debug, " outb(%x) %x \n", offset, value);
202};
203
204
205#else /* PPC */
206
207uint8  ether_inb(etherpci_private_t *device, uint32 offset) {
208  	uint8 result;
209	result = (*((volatile uint8*) (device->reg_base + (offset)))); __eieio();
210	ETHER_DEBUG(PCI_IO, device->debug, " inb(%x) %x \n", offset, result);
211	return result;
212};
213
214uint16  ether_inw(etherpci_private_t *device, uint32 offset) {
215  	uint16 result;
216	result = (*((volatile uint16*) (device->reg_base + (offset)))); __eieio();
217	ETHER_DEBUG(PCI_IO, device->debug, " inw(%x) %x \n", offset, result);
218	return result;
219};
220
221void  ether_outb(etherpci_private_t *device, uint32 offset, uint8 value) {
222	(*((volatile uint8 *)(device->reg_base + (offset))) = (value)); __eieio();
223	ETHER_DEBUG(PCI_IO, device->debug, " outb(%x) %x \n", offset, value);
224};
225void  ether_outw(etherpci_private_t *device, uint32 offset, uint16 value) {
226	(*((volatile uint16 *)(device->reg_base + (offset))) = (value)); __eieio();
227	ETHER_DEBUG(PCI_IO, device->debug, " outb(%x) %x \n", offset, value);
228};
229
230#endif
231#endif
232
233
234
235
236
237/* for serial debug command*/
238#define DEBUGGER_COMMAND true
239#if DEBUGGER_COMMAND
240etherpci_private_t * gdev;
241static int etherpci(int argc, char **argv);
242	/* serial debug command */
243#endif
244
245/*
246 * io_lock gets you exclusive access to the card, except that
247 * the interrupt handler can still run.
248 * There is probably no need to io_lock() a 3com card, so look into
249 * removing it for that case.
250 */
251#define io_lock(data)	acquire_sem(data->iolock)
252#define io_unlock(data)	release_sem_etc(data->iolock, 1, B_DO_NOT_RESCHEDULE)
253
254/*
255 * output_wait wakes up when the card is ready to transmit another packet
256 */
257#define output_wait(data, t) acquire_sem_etc(data->olock, 1, B_TIMEOUT, t)
258#define output_unwait(data, c)	release_sem_etc(data->olock, c, B_DO_NOT_RESCHEDULE)
259
260/*
261 * input_wait wakes up when the card has at least one packet on it
262 */
263#define input_wait(data)		acquire_sem_etc(data->ilock ,1, B_CAN_INTERRUPT, 0)
264#define input_unwait(data, c)	release_sem_etc(data->ilock, c, B_DO_NOT_RESCHEDULE)
265
266
267/* prototypes */
268static status_t open_hook(const char *name, uint32 flags, void **cookie);
269static status_t close_hook(void *);
270static status_t free_hook(void *);
271static status_t control_hook(void * cookie,uint32 msg,void *buf,size_t len);
272static status_t read_hook(void *data, off_t pos, void *buf, size_t *len);
273static status_t write_hook(void *data, off_t pos, const void *buf, size_t *len);
274//static int32    etherpci_interrupt(void *data);                	   /* interrupt handler */
275//static int32    get_pci_list(pci_info *info[], int32 maxEntries);  /* Get pci_info for each device */
276//static status_t free_pci_list(pci_info *info[]);                   /* Free storage used by pci_info list */
277//static void 	dump_packet(const char * msg, unsigned char * buf, uint16 size); /* diagnostic packet trace */
278//static status_t enable_addressing(etherpci_private_t  *data);             /* enable pci io address space for device */
279//static int domulti(etherpci_private_t *data,char *addr);
280
281static device_hooks gDeviceHooks =  {
282	open_hook, 			/* -> open entry point */
283	close_hook,         /* -> close entry point */
284	free_hook,          /* -> free entry point */
285	control_hook,       /* -> control entry point */
286	read_hook,          /* -> read entry point */
287	write_hook,         /* -> write entry point */
288	NULL,               /* -> select entry point */
289	NULL,                /* -> deselect entry point */
290	NULL,               /* -> readv */
291	NULL                /* -> writev */
292};
293
294
295static int32
296get_pci_list(pci_info *info[], int32 maxEntries)
297{
298	int32 i, entries;
299	pci_info *item;
300
301	item = (pci_info *)malloc(sizeof(pci_info));
302	if (item == NULL)
303		return 0;
304
305	for (i = 0, entries = 0; entries < maxEntries; i++) {
306		if (gPCIModInfo->get_nth_pci_info(i, item) != B_OK)
307			break;
308
309		if ((item->vendor_id == 0x10ec && item->device_id == 0x8029)		// RealTek 8029
310			|| (item->vendor_id == 0x1106 && item->device_id == 0x0926)		// VIA
311			|| (item->vendor_id == 0x4a14 && item->device_id == 0x5000)		// NetVin 5000
312			|| (item->vendor_id == 0x1050 && item->device_id == 0x0940)		// ProLAN
313			|| (item->vendor_id == 0x11f6 && item->device_id == 0x1401)		// Compex
314			|| (item->vendor_id == 0x8e2e && item->device_id == 0x3000)) {	// KTI
315			/* check if the device really has an IRQ */
316			if (item->u.h0.interrupt_line == 0 || item->u.h0.interrupt_line == 0xFF) {
317				dprintf(kDevName " found with invalid IRQ - check IRQ assignement");
318				continue;
319			}
320
321			dprintf(kDevName " found at IRQ %x ", item->u.h0.interrupt_line);
322			info[entries++] = item;
323			item = (pci_info *)malloc(sizeof(pci_info));
324			if (item == NULL)
325				break;
326		}
327	}
328	info[entries] = NULL;
329	free(item);
330	return entries;
331}
332
333
334static status_t
335free_pci_list(pci_info *info[])
336{
337	pci_info *item;
338	int32 i;
339
340	for (i = 0; (item = info[i]) != NULL; i++) {
341		free(item);
342	}
343	return B_OK;
344}
345
346
347#if 0
348/*! How many waiting for io? */
349static long
350io_count(etherpci_private_t *data)
351{
352	long count;
353
354	get_sem_count(data->iolock, &count);
355	return (count);
356}
357
358
359/*! How many waiting for output? */
360static long
361output_count(etherpci_private_t *data)
362{
363	long count;
364
365	get_sem_count(data->olock, &count);
366	return (count);
367}
368#endif
369
370/*
371 * How many waiting for input?
372 */
373static int32
374input_count(etherpci_private_t *data)
375{
376	int32 count;
377
378	get_sem_count(data->ilock, &count);
379	return (count);
380}
381
382#if STAY_ON_PAGE_0
383
384#define INTR_LOCK(data, expression) (expression)
385
386#else /* STAY_ON_PAGE_0 */
387
388/*
389 * Spinlock for negotiating access to card with interrupt handler
390 */
391#define intr_lock(data)			acquire_spinlock(&data->intrlock)
392#define intr_unlock(data)		release_spinlock(&data->intrlock)
393
394/*
395 * The interrupt handler must lock all calls to the card
396 * This macro is useful for that purpose.
397 */
398#define INTR_LOCK(data, expression) (intr_lock(data), (expression), intr_unlock(data))
399
400#endif /* STAY_ON_PAGE_0 */
401
402
403/*
404 * Calculate various constants
405 * These must be done at runtime, since 3com and ne2000 cards have different
406 * values.
407 */
408static void
409calc_constants(etherpci_private_t *data)
410{
411	data->EC_VMEM_PAGE = (data->ETHER_BUF_START >> EC_PAGE_SHIFT);
412	data->EC_VMEM_NPAGES = (data->ETHER_BUF_SIZE >> EC_PAGE_SHIFT);
413
414	data->EC_RXBUF_START_PAGE = (data->EC_VMEM_PAGE + 6);
415	data->EC_RXBUF_END_PAGE = (data->EC_VMEM_PAGE + data->EC_VMEM_NPAGES);
416
417	data->EC_RINGSTART = (data->EC_RXBUF_START_PAGE << EC_PAGE_SHIFT);
418	data->EC_RINGSIZE = ((data->EC_VMEM_NPAGES - 6) << EC_PAGE_SHIFT);
419}
420
421
422/*! Print an ethernet address */
423static void
424print_address(ether_address_t *addr)
425{
426	int i;
427	char buf[3 * 6 + 1];
428
429	for (i = 0; i < 5; i++) {
430		sprintf(&buf[3*i], "%02x:", addr->ebyte[i]);
431	}
432	sprintf(&buf[3*5], "%02x", addr->ebyte[5]);
433	dprintf("%s\n", buf);
434}
435
436
437/*! Get the isr register */
438static unsigned char
439getisr(etherpci_private_t *data)
440{
441	return ether_inb(data, EN0_ISR);
442}
443
444
445/*! Set the isr register */
446static void
447setisr(etherpci_private_t *data, unsigned char isr)
448{
449	ether_outb(data, EN0_ISR, isr);
450}
451
452
453/*! Wait for the DMA to complete */
454static int
455wait_for_dma_complete(etherpci_private_t *data, unsigned short addr,
456	unsigned short size)
457{
458	unsigned short hi, low;
459	unsigned short where;
460	int bogus;
461
462#define MAXBOGUS 20
463
464	/*
465	 * This is the expected way to wait for DMA completion, which
466	 * is in fact incorrect. I think ISR_DMADONE gets set too early.
467	 */
468	bogus = 0;
469	while (!(getisr(data) & ISR_DMADONE) && ++bogus < MAXBOGUS) {
470		/* keep waiting */
471	}
472	if (bogus >= MAXBOGUS)
473		dprintf("Bogus alert: waiting for ISR\n");
474
475	/*
476	 * This is the workaround
477	 */
478	bogus = 0;
479	do {
480		hi = ether_inb(data, EN0_RADDRHI);
481		low = ether_inb(data, EN0_RADDRLO);
482		where = (hi << 8) | low;
483	} while (where < addr + size && ++bogus < MAXBOGUS);
484
485	if (bogus >= MAXBOGUS * 2) {
486		/*
487		 * On some cards, the counters will never clear.
488		 * So only print this message when debugging.
489		 */
490		dprintf("Bogus alert: waiting for counters to zero\n");
491		return -1;
492	}
493
494	setisr(data, ISR_DMADONE);
495	ether_outb(data, EN_CCMD, ENC_NODMA);
496	return 0;
497}
498
499
500/*! Check the status of the last packet transmitted */
501static void
502check_transmit_status(etherpci_private_t *data)
503{
504	unsigned char status;
505
506	status = ether_inb(data, EN0_TPSR);
507	if (status & (TSR_ABORTED | TSR_UNDERRUN)) {
508		dprintf("transmit error: %02x\n", status);
509	}
510#if 0
511	if (data->wints + data->werrs != data->writes) {
512		dprintf("Write interrupts %d, errors %d, transmits %d\n",
513				data->wints, data->werrs, data->writes);
514	}
515#endif
516}
517
518
519static long
520inrw(etherpci_private_t *data)
521{
522	return data->inrw;
523}
524
525
526static status_t
527create_sems(etherpci_private_t *data)
528{
529	data->iolock = create_sem(1, "ethercard io");
530	if (data->iolock < B_OK)
531		return data->iolock;
532
533	data->olock = create_sem(1, "ethercard output");
534	if (data->olock < B_OK) {
535		delete_sem(data->iolock);
536		return data->olock;
537	}
538
539	data->ilock = create_sem(0, "ethercard input");
540	if (data->ilock < B_OK) {
541		delete_sem(data->iolock);
542		delete_sem(data->olock);
543		return data->ilock;
544	}
545
546	return B_OK;
547}
548
549
550/*! Get data from the ne2000 card */
551static void
552etherpci_min(etherpci_private_t *data, unsigned char *dst,
553	unsigned src, unsigned len)
554{
555	int i;
556
557	if (len & 1)
558		len++;
559
560	ether_outb(data, EN0_RCNTLO, len & 0xff);
561	ether_outb(data, EN0_RCNTHI, len >> 8);
562	ether_outb(data, EN0_RADDRLO, src & 0xff);
563	ether_outb(data, EN0_RADDRHI, src >> 8);
564	ether_outb(data, EN_CCMD, ENC_DMAREAD);
565
566	for (i = 0; i < len; i += 2) {
567		unsigned short word;
568
569		word = ether_inw(data, NE_DATA);
570#if __INTEL__
571		dst[i + 1] = word >> 8;
572		dst[i + 0] = word & 0xff;
573#else
574		dst[i] = word >> 8;
575		dst[i + 1] = word & 0xff;
576#endif
577	}
578	wait_for_dma_complete(data, src, len);
579}
580
581
582/*! Put data on the ne2000 card */
583static void
584etherpci_mout(etherpci_private_t *data, unsigned dst,
585	const unsigned char *src, unsigned len)
586{
587	int i;
588	int tries = 1;
589
590	// This loop is for a bug that showed up with the old ISA 3com cards
591	// that were in the original BeBox.  Sometimes the dma status would just
592	// stop on some part of the buffer, never finishing.
593	// If we notice this error, we redo the dma transfer.
594again:
595#define MAXTRIES 2
596	if (tries > MAXTRIES) {
597		dprintf("ether_mout : tried %d times, stopping\n", tries);
598		return;
599	}
600
601	if (len & 1)
602		len++;
603
604	ether_outb(data, EN0_RCNTHI, len >> 8);
605	ether_outb(data, EN0_RADDRLO, dst & 0xff);
606	ether_outb(data, EN0_RADDRHI, dst >> 8);
607
608	/*
609	 * The 8390 hardware has documented bugs in it related to DMA write.
610	 * So, we follow the documentation on how to work around them.
611	 */
612
613	/*
614	 * Step 1: You must put a non-zero value in this register. We use 2.
615	 */
616	if ((len & 0xff) == 0) {
617		ether_outb(data, EN0_RCNTLO, 2);
618	} else {
619		ether_outb(data, EN0_RCNTLO, len & 0xff);
620	}
621
622#if you_want_to_follow_step2_even_though_it_hangs
623	ether_outb(data, EN_CCMD, ENC_DMAREAD);				/* Step 2 */
624#endif
625
626	ether_outb(data, EN_CCMD, ENC_DMAWRITE);
627
628	for (i = 0; i < len; i += 2) {
629		unsigned short word;
630
631#if __INTEL__
632		word = (src[i + 1] << 8) | src[i + 0];
633#else
634		word = (src[i] << 8) | src[i + 1];
635#endif
636		ether_outw(data, NE_DATA, word);
637	}
638
639	if ((len & 0xff) == 0) {
640		/*
641		 * Write out the two extra bytes
642		 */
643		ether_outw(data, NE_DATA, 0);
644		len += 2;
645	}
646	if (wait_for_dma_complete(data, dst, len) != 0) {
647		tries++;
648		goto again;
649	}
650	//if (tries != 1) { dprintf("wait_for_dma worked after %d tries\n", tries); }
651}
652
653
654#if STAY_ON_PAGE_0
655/*! Zero out the headers in the ring buffer */
656static void
657ringzero(etherpci_private_t *data, unsigned boundary,
658	unsigned next_boundary)
659{
660	ring_header ring;
661	int i;
662	int pages;
663	unsigned offset;
664
665	ring.count = 0;
666	ring.next_packet = 0;
667	ring.status = 0;
668
669	if (data->boundary < next_boundary) {
670		pages = next_boundary - data->boundary;
671	} else {
672		pages = (data->EC_RINGSIZE >> EC_PAGE_SHIFT) - (data->boundary - next_boundary);
673	}
674
675	for (i = 0; i < pages; i++) {
676		offset = data->boundary << EC_PAGE_SHIFT;
677		etherpci_mout(data, offset, (unsigned char *)&ring, sizeof(ring));
678		data->boundary++;
679		if (data->boundary >= data->EC_RXBUF_END_PAGE) {
680			data->boundary = data->EC_RXBUF_START_PAGE;
681		}
682	}
683}
684#endif /* STAY_ON_PAGE_0 */
685
686
687/*! Determine if we have an ne2000 PCI card */
688static int
689probe(etherpci_private_t *data)
690{
691	int i;
692	int reg;
693	unsigned char test[EC_PAGE_SIZE];
694	short waddr[ETHER_ADDR_LEN];
695	uint8 reg_val;
696
697	data->ETHER_BUF_START = ETHER_BUF_START_NE2000;
698	data->ETHER_BUF_SIZE = ETHER_BUF_SIZE_NE2000;
699	calc_constants(data);
700
701	reg = ether_inb(data, NE_RESET);
702	snooze(2000);
703	ether_outb(data, NE_RESET, reg);
704	snooze(2000);
705	ether_outb(data, EN_CCMD, ENC_NODMA | ENC_STOP | ENC_PAGE0);
706
707	i = 10000;
708	while ( i-- > 0) {
709		reg_val = ether_inb(data, EN0_ISR);
710		if (reg_val & ISR_RESET) break;
711	}
712	if (i < 0)
713		dprintf("reset failed -- ignoring\n");
714
715	ether_outb(data, EN0_ISR, 0xff);
716	ether_outb(data, EN0_DCFG, DCFG_BM16);
717	ether_outb(data, EN_CCMD, ENC_NODMA | ENC_STOP | ENC_PAGE0);
718
719	snooze(2000);
720
721	reg = ether_inb(data, EN_CCMD);
722	if (reg != (ENC_NODMA|ENC_STOP|ENC_PAGE0)) {
723		dprintf("command register failed: %02x != %02x\n", reg, ENC_NODMA|ENC_STOP);
724		return 0;
725	}
726
727	ether_outb(data, EN0_TXCR, 0);
728	ether_outb(data, EN0_RXCR, ENRXCR_MON);
729	ether_outb(data, EN0_STARTPG, data->EC_RXBUF_START_PAGE);
730	ether_outb(data, EN0_STOPPG, data->EC_RXBUF_END_PAGE);
731	ether_outb(data, EN0_BOUNDARY, data->EC_RXBUF_END_PAGE);
732	ether_outb(data, EN0_IMR, 0);
733	ether_outb(data, EN0_ISR, 0);
734	ether_outb(data, EN_CCMD, ENC_NODMA | ENC_PAGE1 | ENC_STOP);
735	ether_outb(data, EN1_CURPAG, data->EC_RXBUF_START_PAGE);
736	ether_outb(data, EN_CCMD, ENC_NODMA | ENC_PAGE0 | ENC_STOP);
737
738	/* stop chip */
739	ether_outb(data, EN_CCMD, ENC_NODMA | ENC_PAGE0);
740	ether_outb(data, EN_CCMD, ENC_NODMA | ENC_STOP);
741
742	memset(&waddr[0], 0, sizeof(waddr));
743	etherpci_min(data, (unsigned char *)&waddr[0], 0, sizeof(waddr));
744
745	for (i = 0; i < ETHER_ADDR_LEN; i++) {
746		data->myaddr.ebyte[i] = ((unsigned char *)&waddr[0])[2*i];
747	}
748
749	/* test memory */
750	for (i = 0; i < sizeof(test); i++) {
751		test[i] = i;
752	}
753
754	etherpci_mout(data, data->ETHER_BUF_START, (unsigned char *)&test[0], sizeof(test));
755	memset(&test, 0, sizeof(test));
756	etherpci_min(data, (unsigned char *)&test[0], data->ETHER_BUF_START, sizeof(test));
757
758	for (i = 0; i < sizeof(test); i++) {
759		if (test[i] != i) {
760			dprintf("memory test failed: %02x %02x\n", i, test[i]);
761			return 0;
762		}
763	}
764
765	dprintf("ne2000 pci ethernet card found - ");
766	print_address(&data->myaddr);
767	return 1;
768}
769
770
771/*! Initialize the ethernet card */
772static void
773init(etherpci_private_t *data)
774{
775	int i;
776
777#if STAY_ON_PAGE_0
778	/*
779	 * Set all the ring headers to zero
780	 */
781	ringzero(data, data->EC_RXBUF_START_PAGE, data->EC_RXBUF_END_PAGE);
782#endif /* STAY_ON_PAGE_0 */
783
784	/* initialize data configuration register */
785	ether_outb(data, EN0_DCFG, DCFG_BM16);
786
787	/* clear remote byte count registers */
788	ether_outb(data, EN0_RCNTLO, 0x0);
789	ether_outb(data, EN0_RCNTHI, 0x0);
790
791	/* initialize receive configuration register */
792	ether_outb(data, EN0_RXCR, ENRXCR_BCST);
793
794	/* get into loopback mode */
795	ether_outb(data, EN0_TXCR, TXCR_LOOPBACK);
796
797	/* set boundary, page start and page stop */
798	ether_outb(data, EN0_BOUNDARY, data->EC_RXBUF_END_PAGE);
799	data->boundary = data->EC_RXBUF_START_PAGE;
800	ether_outb(data, EN0_STARTPG, data->EC_RXBUF_START_PAGE);
801	ether_outb(data, EN0_STOPPG, data->EC_RXBUF_END_PAGE);
802
803	/* set transmit page start register */
804	ether_outb(data, EN0_TPSR, data->EC_VMEM_PAGE);
805
806	/* clear interrupt status register */
807	ether_outb(data, EN0_ISR, 0xff);
808
809	/* initialize interrupt mask register */
810	ether_outb(data, EN0_IMR, INTS_WE_CARE_ABOUT);
811
812	/* set page 1 */
813	ether_outb(data, EN_CCMD, ENC_NODMA | ENC_PAGE1);
814
815	/* set physical address */
816	for (i = 0; i < 6; i++) {
817		ether_outb(data, EN1_PHYS + i, data->myaddr.ebyte[i]);
818	}
819
820	/* set multicast address */
821	for (i = 0; i < 8; i++) {
822		ether_outb(data, EN1_MULT+i, 0xff);
823	}
824	data->nmulti = 0;
825
826	/* set current pointer */
827	ether_outb(data, EN1_CURPAG, data->EC_RXBUF_START_PAGE);
828
829	/* start chip */
830	ether_outb(data, EN_CCMD, ENC_START | ENC_PAGE0 | ENC_NODMA);
831
832	/* initialize transmit configuration register */
833	ether_outb(data, EN0_TXCR, 0x00);
834}
835
836
837/*! Copy data from the card's ring buffer */
838static void
839ringcopy(etherpci_private_t *data, unsigned char *ether_buf,
840	int offset, int len)
841{
842	int roffset;
843	int rem;
844
845	roffset = offset - data->EC_RINGSTART;
846	rem = data->EC_RINGSIZE - roffset;
847	if (len > rem) {
848		etherpci_min(data, &ether_buf[0], offset, rem);
849		etherpci_min(data, &ether_buf[rem], data->EC_RINGSTART, len - rem);
850	} else {
851		etherpci_min(data, &ether_buf[0], offset, len);
852	}
853}
854
855
856/*!
857	Set the boundary register, both on the card and internally
858	NOTE: you cannot make the boundary = current register on the card,
859	so we actually set it one behind.
860*/
861static void
862setboundary(etherpci_private_t *data, unsigned char nextboundary)
863{
864	if (nextboundary != data->EC_RXBUF_START_PAGE) {
865		ether_outb(data, EN0_BOUNDARY, nextboundary - 1);
866	} else {
867		/* since it's a ring buffer */
868		ether_outb(data, EN0_BOUNDARY, data->EC_RXBUF_END_PAGE - 1);
869	}
870	data->boundary = nextboundary;
871}
872
873
874/*! Start resetting the chip, because of ring overflow */
875static int
876reset(etherpci_private_t *data)
877{
878	unsigned char cmd;
879	int resend = false;
880
881	cmd = ether_inb(data, EN_CCMD);
882	ether_outb(data, EN_CCMD, ENC_STOP | ENC_NODMA);
883	snooze(10 * 1000);
884	ether_outb(data, EN0_RCNTLO, 0x0);
885	ether_outb(data, EN0_RCNTHI, 0x0);
886	if (cmd & ENC_TRANS) {
887		if(!(getisr(data) & (ISR_TRANSMIT | ISR_TRANSMIT_ERROR)))
888			resend = true;  // xmit command issued but ISR shows its not completed
889	}
890	/* get into loopback mode */
891	ether_outb(data, EN0_TXCR, TXCR_LOOPBACK);
892	ether_outb(data, EN_CCMD, ENC_START | ENC_PAGE0 | ENC_NODMA);
893	return (resend);
894}
895
896
897/*! finish the reset */
898static void
899finish_reset(etherpci_private_t *data, int resend)
900{
901	setisr(data, ISR_OVERWRITE);
902	ether_outb(data, EN0_TXCR, 0x00);
903
904	if (resend) {
905//		dprintf("Xmit CMD resent\n");
906		ether_outb(data, EN_CCMD, ENC_START | ENC_PAGE0 | ENC_NODMA | ENC_TRANS);
907	}
908}
909
910
911/*! Handle ethernet interrupts */
912static int32
913etherpci_interrupt(void *_data)
914{
915	etherpci_private_t *data = (etherpci_private_t *) _data;
916	unsigned char isr;
917	int wakeup_reader = 0;
918	int wakeup_writer = 0;
919	int32 handled = B_UNHANDLED_INTERRUPT;
920	data->ints++;
921
922	ETHER_DEBUG(INTERRUPT, data->debug, "ENTR isr=%x & %x?\n",getisr(data), INTS_WE_CARE_ABOUT);
923	for (INTR_LOCK(data, isr = getisr(data));
924			isr & INTS_WE_CARE_ABOUT;
925			INTR_LOCK(data, isr = getisr(data))) {
926		if (isr & ISR_RECEIVE) {
927			data->rints++;
928			wakeup_reader++;
929			INTR_LOCK(data, setisr(data, ISR_RECEIVE));
930			handled = B_HANDLED_INTERRUPT;
931			continue;
932		}
933		if (isr & ISR_TRANSMIT_ERROR) {
934			data->werrs++;
935			INTR_LOCK(data, setisr(data, ISR_TRANSMIT_ERROR));
936			wakeup_writer++;
937			handled = B_HANDLED_INTERRUPT;
938			continue;
939		}
940		if (isr & ISR_TRANSMIT) {
941			data->wints++;
942			INTR_LOCK(data, setisr(data, ISR_TRANSMIT));
943			wakeup_writer++;
944			handled = B_HANDLED_INTERRUPT;
945			continue;
946		}
947		if (isr & ISR_RECEIVE_ERROR) {
948			uint32 err_count;
949			err_count = ether_inb(data, EN0_CNTR0);  data->frame_errs += err_count;
950			err_count = ether_inb(data, EN0_CNTR1);  data->crc_errs += err_count;
951			err_count = ether_inb(data, EN0_CNTR2);  data->frames_lost += err_count;
952
953			isr &= ~ISR_RECEIVE_ERROR;
954			INTR_LOCK(data, setisr(data, ISR_RECEIVE_ERROR));
955			handled = B_HANDLED_INTERRUPT;
956		}
957		if (isr & ISR_DMADONE) {
958			isr &= ~ISR_DMADONE;	/* handled elsewhere */
959			handled = B_HANDLED_INTERRUPT;
960		}
961		if (isr & ISR_OVERWRITE) {
962			isr &= ~ISR_OVERWRITE; /* handled elsewhere */
963			handled = B_HANDLED_INTERRUPT;
964		}
965
966		if (isr & ISR_COUNTER) {
967			isr &= ~ISR_COUNTER; /* handled here */
968//			dprintf("Clearing Stats Cntr\n");
969			INTR_LOCK(data, setisr(data, ISR_COUNTER));
970			handled = B_HANDLED_INTERRUPT;
971		}
972
973		if (isr) {
974			/*
975			 * If any other interrupts, just clear them (hmmm....)
976			 * ??? This doesn't seem right - HB
977			 */
978//			ddprintf("ISR=%x rdr=%x wtr=%x io=%x inrw=%x nonblk=%x\n",
979//				isr,input_count(data), output_count(data),io_count(data),
980//				data->inrw,data->nonblocking);
981			INTR_LOCK(data, setisr(data, isr));
982			data->interrs++;
983		}
984	}
985	if (wakeup_reader) {
986		input_unwait(data, 1);
987	}
988	if (wakeup_writer) {
989		output_unwait(data, 1);
990	}
991
992	return handled;
993}
994
995
996/*! Check to see if there are any new errors */
997static void
998check_errors(etherpci_private_t *data)
999{
1000#define DOIT(stat, message) \
1001	if (stat > stat##_last) { \
1002		stat##_last = stat; \
1003		dprintf(message, stat##_last); \
1004	}
1005
1006	DOIT(data->rerrs, "Receive errors now %d\n");
1007	DOIT(data->werrs, "Transmit errors now %d\n");
1008	DOIT(data->interrs, "Interrupt errors now %d\n");
1009	DOIT(data->frames_lost, "Frames lost now %d\n");
1010#undef DOIT
1011#if 0
1012	/*
1013	 * these are normal errors because collisions are normal
1014	 * so don't make a big deal about them.
1015	 */
1016	DOIT(data->frame_errs, "Frame alignment errors now %d\n");
1017	DOIT(data->crc_errs, "CRC errors now %d\n");
1018#endif
1019}
1020
1021
1022/*! Find out if there are any more packets on the card */
1023static int
1024more_packets(etherpci_private_t *data, int didreset)
1025{
1026#if STAY_ON_PAGE_0
1027	unsigned offset;
1028	ring_header ring;
1029
1030	offset = data->boundary << EC_PAGE_SHIFT;
1031	etherpci_min(data, (unsigned char *)&ring, offset, sizeof(ring));
1032	return ring.status && ring.next_packet && ring.count;
1033
1034#else /* STAY_ON_PAGE_0 */
1035
1036	cpu_status ps;
1037	unsigned char cur;
1038
1039	/*
1040	 * First, get the current registe
1041	 */
1042	ps = disable_interrupts();
1043	intr_lock(data);
1044	ether_outb(data, EN_CCMD, ENC_PAGE1);
1045	cur = ether_inb(data, EN1_CURPAG);
1046	ether_outb(data, EN_CCMD, ENC_PAGE0);
1047	intr_unlock(data);
1048	restore_interrupts(ps);
1049
1050	/*
1051	 * Then return the result
1052	 * Must use didreset since cur == boundary in
1053	 * an overflow situation.
1054	 */
1055	return didreset || cur != data->boundary;
1056#endif	/* STAY_ON_PAGE_0 */
1057}
1058
1059
1060/*! Copy a packet from the ethernet card */
1061static int
1062copy_packet(etherpci_private_t *data, unsigned char *ether_buf,
1063	int buflen)
1064{
1065	ring_header ring;
1066	unsigned offset;
1067	int len;
1068	int rlen;
1069	int ether_len = 0;
1070	int didreset = 0;
1071	int resend = 0;
1072
1073	io_lock(data);
1074	check_errors(data);
1075
1076	/*
1077	 * Check for overwrite error first
1078	 */
1079	if (getisr(data) & ISR_OVERWRITE) {
1080//		dprintf("starting ether reset!\n");
1081		data->resets++;
1082		resend = reset(data);
1083		didreset++;
1084	}
1085
1086	if (more_packets(data, didreset)) do {
1087		/*
1088		 * Read packet ring header
1089		 */
1090		offset = data->boundary << EC_PAGE_SHIFT;
1091		etherpci_min(data, (unsigned char *)&ring, offset, sizeof(ring));
1092
1093		len = swapshort(ring.count);
1094
1095		if (!(ring.status & RSR_INTACT)) {
1096			dprintf("packet not intact! (%02x,%u,%02x) (%d)\n",
1097				ring.status, ring.next_packet, ring.count, data->boundary);
1098
1099			/* discard bad packet */
1100			ether_len = 0; setboundary(data, ring.next_packet);
1101			break;
1102		}
1103
1104		if (ring.next_packet < data->EC_RXBUF_START_PAGE
1105			|| ring.next_packet >= data->EC_RXBUF_END_PAGE) {
1106			dprintf("etherpci_read: bad next packet! (%02x,%u,%02x) (%d)\n",
1107				ring.status, ring.next_packet, ring.count, data->boundary);
1108
1109			data->rerrs++;
1110			/* discard bad packet */
1111			ether_len = 0; setboundary(data, ring.next_packet);
1112			break;
1113		}
1114
1115		len = swapshort(ring.count);
1116		rlen = len - 4;
1117		if (rlen < ETHER_MIN_SIZE || rlen > ETHER_MAX_SIZE) {
1118			dprintf("etherpci_read: bad length! (%02x,%u,%02x) (%d)\n",
1119				ring.status, ring.next_packet, ring.count, data->boundary);
1120
1121			data->rerrs++;
1122			/* discard bad packet */
1123			ether_len = 0; setboundary(data, ring.next_packet);
1124			break;
1125		}
1126
1127		if (rlen > buflen)
1128			rlen = buflen;
1129
1130		ringcopy(data, ether_buf, offset + 4, rlen);
1131
1132#if STAY_ON_PAGE_0
1133		ringzero(data, data->boundary, ring.next_packet);
1134#endif /* STAY_ON_PAGE_0 */
1135
1136		ether_len = rlen;
1137		setboundary(data, ring.next_packet);
1138		data->reads++;
1139	} while (0);
1140
1141	if (didreset) {
1142		dprintf("finishing reset!\n");
1143		finish_reset(data, resend);
1144	}
1145
1146	if (input_count(data) <= 0 && more_packets(data, didreset)) {
1147		/*
1148		 * Looks like there is another packet
1149		 * So, make sure they get woken up
1150		 */
1151		input_unwait(data, 1);
1152	}
1153
1154	io_unlock(data);
1155	return ether_len;
1156}
1157
1158
1159/*! Checks if the received packet is really for us */
1160static int
1161my_packet(etherpci_private_t *data, char *addr)
1162{
1163	int i;
1164	const char broadcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1165
1166	if (memcmp(addr, &data->myaddr, sizeof(data->myaddr)) == 0
1167		|| memcmp(addr, broadcast, sizeof(broadcast)) == 0)
1168		return 1;
1169
1170	for (i = 0; i < data->nmulti; i++) {
1171		if (memcmp(addr, &data->multi[i], sizeof(data->multi[i])) == 0)
1172			return 1;
1173	}
1174
1175	return 0;
1176}
1177
1178
1179static status_t
1180enable_addressing(etherpci_private_t *data)
1181{
1182	unsigned char cmd;
1183
1184#if __INTEL__
1185	data->reg_base = data->pciInfo->u.h0.base_registers[0];
1186#else
1187	uint32 base, size, offset;
1188	base = data->pciInfo->u.h0.base_registers[0];
1189	size = data->pciInfo->u.h0.base_register_sizes[0];
1190
1191	/* Round down to nearest page boundary */
1192	base = base & ~(B_PAGE_SIZE-1);
1193
1194	/* Adjust the size */
1195	offset = data->pciInfo->u.h0.base_registers[0] - base;
1196	size += offset;
1197	size = (size +(B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1);
1198
1199	dprintf(kDevName ": PCI base=%x size=%x offset=%x\n", base, size, offset);
1200
1201	if ((data->ioarea = map_physical_memory(kDevName "_regs", base, size,
1202			B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA,
1203			(void **)&data->reg_base)) < 0) {
1204		return B_ERROR;
1205	}
1206
1207	data->reg_base = data->reg_base + offset;
1208
1209#endif
1210	dprintf(kDevName ": reg_base=%" B_PRIx32 "\n", data->reg_base);
1211
1212	/* enable pci address access */
1213	cmd = (gPCIModInfo->read_pci_config)(data->pciInfo->bus, data->pciInfo->device, data->pciInfo->function, PCI_command, 2);
1214	(gPCIModInfo->write_pci_config)(data->pciInfo->bus, data->pciInfo->device, data->pciInfo->function, PCI_command, 2, cmd | PCI_command_io);
1215
1216	return B_OK;
1217}
1218
1219
1220static int
1221domulti(etherpci_private_t *data, char *addr)
1222{
1223	int i;
1224	int nmulti = data->nmulti;
1225
1226	if (nmulti == MAX_MULTI)
1227		return B_ERROR;
1228
1229	for (i = 0; i < nmulti; i++) {
1230		if (memcmp(&data->multi[i], addr, sizeof(data->multi[i])) == 0) {
1231			break;
1232		}
1233	}
1234
1235	if (i == nmulti) {
1236		/*
1237		 * Only copy if it isn't there already
1238		 */
1239		memcpy(&data->multi[i], addr, sizeof(data->multi[i]));
1240		data->nmulti++;
1241	}
1242	if (data->nmulti == 1) {
1243		dprintf("Enabling multicast\n");
1244		ether_outb(data, EN0_RXCR, ENRXCR_BCST | ENRXCR_MCST);
1245	}
1246
1247	return B_NO_ERROR;
1248}
1249
1250
1251/*!
1252	Serial Debugger command
1253	Connect a terminal emulator to the serial port at 19.2 8-1-None
1254	Press the keys ( alt-sysreq on Intel) or (Clover-leaf Power on Mac ) to enter the debugger
1255	At the kdebug> prompt enter "etherpci arg...",
1256	for example "etherpci R" to enable a received packet trace.
1257*/
1258#if DEBUGGER_COMMAND
1259static int
1260etherpci(int argc, char **argv) {
1261	uint16 i,j;
1262	const char * usage = "usage: etherpci { Function_calls | PCI_IO | Stats | Rx_trace | Tx_trace }\n";
1263
1264
1265	if (argc < 2) {
1266		kprintf("%s",usage);	return 0;
1267	}
1268
1269	for (i= argc, j= 1; i > 1; i--, j++) {
1270		switch (*argv[j]) {
1271		case 'F':
1272		case 'f':
1273			gdev->debug ^= FUNCTION;
1274			if (gdev->debug & FUNCTION)
1275				kprintf("Function() call trace Enabled\n");
1276			else
1277				kprintf("Function() call trace Disabled\n");
1278			break;
1279		case 'N':
1280		case 'n':
1281			gdev->debug ^= SEQ;
1282			if (gdev->debug & SEQ)
1283				kprintf("Sequence numbers packet trace Enabled\n");
1284			else
1285				kprintf("Sequence numbers packet trace Disabled\n");
1286			break;
1287		case 'R':
1288		case 'r':
1289			gdev->debug ^= RX;
1290			if (gdev->debug & RX)
1291				kprintf("Receive packet trace Enabled\n");
1292			else
1293				kprintf("Receive packet trace Disabled\n");
1294			break;
1295		case 'T':
1296		case 't':
1297			gdev->debug ^= TX;
1298			if (gdev->debug & TX)
1299				kprintf("Transmit packet trace Enabled\n");
1300			else
1301				kprintf("Transmit packet trace Disabled\n");
1302			break;
1303		case 'S':
1304		case 's':
1305			kprintf(kDevName " statistics\n");
1306			kprintf("rx_ints %d,  tx_ints %d\n", gdev->rints, gdev->wints);
1307			kprintf("resets %d \n", gdev->resets);
1308			kprintf("crc_errs %d, frame_errs %d, frames_lost %d\n", gdev->crc_errs, gdev->frame_errs, gdev->frames_lost);
1309			break;
1310		case 'P':
1311		case 'p':
1312			gdev->debug ^= PCI_IO;
1313			if (gdev->debug & PCI_IO)
1314				kprintf("PCI IO trace Enabled\n");
1315			else
1316				kprintf("PCI IO trace Disabled\n");
1317			break;
1318		default:
1319			kprintf("%s",usage);
1320			return 0;
1321		}
1322	}
1323
1324	return 0;
1325}
1326#endif /* DEBUGGER_COMMAND */
1327
1328
1329static void
1330dump_packet(const char * msg, unsigned char * buf, uint16 size)
1331{
1332	uint16 j;
1333
1334	dprintf("%s dumping %p size %u \n", msg, buf, size);
1335	for (j = 0; j < size; j++) {
1336		if ((j & 0xF) == 0)
1337			dprintf("\n");
1338		dprintf("%2.2x ", buf[j]);
1339	}
1340}
1341
1342
1343//	#pragma mark - Driver Entry Points
1344
1345
1346status_t
1347init_hardware(void)
1348{
1349	return B_NO_ERROR;
1350}
1351
1352
1353status_t
1354init_driver(void)
1355{
1356	status_t status;
1357	int32 entries;
1358	char devName[64];
1359	int32 i;
1360
1361	dprintf(kDevName ": init_driver ");
1362
1363	if ((status = get_module( B_PCI_MODULE_NAME, (module_info **)&gPCIModInfo )) != B_OK) {
1364		dprintf(kDevName " Get module failed! %s\n", strerror(status ));
1365		return status;
1366	}
1367
1368	/* Find Lan cards*/
1369	if ((entries = get_pci_list(gDevList, MAX_CARDS )) == 0) {
1370		dprintf("init_driver: " kDevName " not found\n");
1371		free_pci_list(gDevList);
1372		put_module(B_PCI_MODULE_NAME );
1373		return B_ERROR;
1374	}
1375	dprintf("\n");
1376
1377	/* Create device name list*/
1378	for (i=0; i<entries; i++ )
1379	{
1380		sprintf(devName, "%s%" B_PRId32, kDevDir, i );
1381		gDevNameList[i] = (char *)malloc(strlen(devName)+1);
1382		strcpy(gDevNameList[i], devName);
1383	}
1384	gDevNameList[i] = NULL;
1385
1386	return B_OK;
1387}
1388
1389
1390void
1391uninit_driver(void)
1392{
1393	void *item;
1394	int32 i;
1395
1396	/*Free device name list*/
1397	for (i = 0; (item = gDevNameList[i]) != NULL; i++) {
1398		free(item);
1399	}
1400
1401	/*Free device list*/
1402	free_pci_list(gDevList);
1403	put_module(B_PCI_MODULE_NAME);
1404}
1405
1406
1407device_hooks *
1408find_device(const char *name)
1409{
1410	int32 i;
1411	char *item;
1412
1413	/* Find device name */
1414	for (i = 0; (item = gDevNameList[i]) != NULL; i++) {
1415		if (!strcmp(name, item))
1416			return &gDeviceHooks;
1417	}
1418
1419	return NULL;
1420}
1421
1422
1423const char**
1424publish_devices(void)
1425{
1426	dprintf(kDevName ": publish_devices()\n");
1427	return (const char **)gDevNameList;
1428}
1429
1430
1431//	#pragma mark Device Hooks
1432
1433
1434/*! Implements the read() system call to the ethernet driver */
1435static status_t
1436read_hook(void *_data, off_t pos, void *buf, size_t *len)
1437{
1438	etherpci_private_t *data = (etherpci_private_t *) _data;
1439	ulong buflen;
1440	int packet_len;
1441
1442	buflen = *len;
1443	atomic_add(&data->inrw, 1);
1444	if (data->interrupted) {
1445		atomic_add(&data->inrw, -1);
1446		return B_INTERRUPTED;
1447	}
1448
1449	do {
1450		if (!data->nonblocking) {
1451			input_wait(data);
1452		}
1453		if (data->interrupted) {
1454			atomic_add(&data->inrw, -1);
1455			return B_INTERRUPTED;
1456		}
1457		packet_len = copy_packet(data, (unsigned char *)buf, buflen);
1458		if ((packet_len) && (data->debug & RX)) {
1459			dump_packet("RX:" ,buf, packet_len);
1460		}
1461	} while (!data->nonblocking && packet_len == 0 && !my_packet(data, buf));
1462
1463	atomic_add(&data->inrw, -1);
1464	*len = packet_len;
1465	return 0;
1466}
1467
1468
1469static status_t
1470open_hook(const char *name, uint32 flags, void **cookie)
1471{
1472	int32 devID;
1473	int32 mask;
1474	status_t status;
1475	char *devName;
1476	etherpci_private_t *data;
1477
1478	/*	Find device name*/
1479	for (devID = 0; (devName = gDevNameList[devID]); devID++) {
1480		if (strcmp(name, devName) == 0)
1481			break;
1482	}
1483	if (!devName)
1484		return EINVAL;
1485
1486	/* Check if the device is busy and set in-use flag if not */
1487	mask = 1 << devID;
1488	if (atomic_or(&gOpenMask, mask) &mask)
1489		return B_BUSY;
1490
1491	/*	Allocate storage for the cookie*/
1492	if (!(*cookie = data = (etherpci_private_t *)malloc(sizeof(etherpci_private_t)))) {
1493		status = B_NO_MEMORY;
1494		goto err0;
1495	}
1496	memset(data, 0, sizeof(etherpci_private_t));
1497
1498	/* Setup the cookie */
1499	data->pciInfo = gDevList[devID];
1500	data->devID = devID;
1501	data->interrupted = 0;
1502	data->inrw = 0;
1503	data->nonblocking = 0;
1504
1505	data->debug = DEFAULT_DEBUG_FLAGS;
1506	ETHER_DEBUG(FUNCTION, data->debug, kDevName ": open %s dev=%p\n", name, data);
1507
1508#if DEBUGGER_COMMAND
1509	gdev = data;
1510	add_debugger_command (kDevName, etherpci, "Ethernet driver Info");
1511#endif
1512
1513	/* enable access to the cards address space */
1514	if ((status = enable_addressing(data)) != B_OK)
1515		goto err1;
1516
1517	if (!probe(data)) {
1518		dprintf(kDevName ": probe failed\n");
1519		goto err1;
1520	}
1521
1522	if (create_sems(data) != B_OK)
1523		goto err2;
1524
1525	/* Setup interrupts */
1526	install_io_interrupt_handler( data->pciInfo->u.h0.interrupt_line, etherpci_interrupt, *cookie, 0 );
1527
1528	dprintf("Interrupts installed at %x\n", data->pciInfo->u.h0.interrupt_line);
1529	/* Init Device */
1530	init(data);
1531
1532	return B_NO_ERROR;
1533
1534err2:
1535#if !__INTEL__
1536	delete_area(data->ioarea);
1537#endif
1538err1:
1539#if DEBUGGER_COMMAND
1540	remove_debugger_command (kDevName, etherpci);
1541#endif
1542	free(data);
1543
1544err0:
1545	atomic_and(&gOpenMask, ~mask);
1546	dprintf(kDevName ": open failed!\n");
1547	return B_ERROR;
1548}
1549
1550
1551static status_t
1552close_hook(void *_data)
1553{
1554	etherpci_private_t *data = (etherpci_private_t *)_data;
1555	ETHER_DEBUG(FUNCTION, data->debug, kDevName ": close dev=%p\n", data);
1556
1557	/*
1558	 * Force pending reads and writes to terminate
1559	 */
1560	io_lock(data);
1561	data->interrupted = 1;
1562	input_unwait(data, 1);
1563	output_unwait(data, 1);
1564	io_unlock(data);
1565	while (inrw(data)) {
1566		snooze(1000000);
1567		dprintf("ether: still waiting for read/write to finish\n");
1568	}
1569
1570	/*
1571	 * Stop the chip
1572	 */
1573	ether_outb(data, EN_CCMD, ENC_STOP);
1574	snooze(2000);
1575
1576	/*
1577	 * And clean up
1578	 */
1579	remove_io_interrupt_handler(data->pciInfo->u.h0.interrupt_line, etherpci_interrupt, data);
1580	delete_sem(data->iolock);
1581	delete_sem(data->ilock);
1582	delete_sem(data->olock);
1583
1584	/*
1585	 * Reset all the statistics
1586	 */
1587	data->ints = 0;
1588	data->rints = 0;
1589	data->rerrs = 0;
1590	data->wints = 0;
1591	data->werrs = 0;
1592	data->reads = 0;
1593	data->writes = 0;
1594	data->interrs = 0;
1595	data->resets = 0;
1596	data->frame_errs = 0;
1597	data->crc_errs = 0;
1598	data->frames_lost = 0;
1599
1600	data->rerrs_last = 0;
1601	data->werrs_last = 0;
1602	data->interrs_last = 0;
1603	data->frame_errs_last = 0;
1604	data->crc_errs_last = 0;
1605	data->frames_lost_last = 0;
1606
1607	data->chip_rx_frame_errors = 0;
1608	data->chip_rx_crc_errors = 0;
1609	data->chip_rx_missed_errors = 0;
1610
1611#if DEBUGGER_COMMAND
1612	remove_debugger_command (kDevName, etherpci);
1613#endif
1614
1615	return B_OK;
1616}
1617
1618
1619static status_t
1620free_hook(void *_data)
1621{
1622	etherpci_private_t *data = (etherpci_private_t *)_data;
1623	int32 mask;
1624
1625	ETHER_DEBUG(FUNCTION, data->debug, kDevName ": free dev=%p\n", data);
1626
1627#if !__INTEL__
1628	delete_area(data->ioarea);
1629#endif
1630
1631	// make sure the device can be reopened again
1632	mask = 1L << data->devID;
1633	atomic_and(&gOpenMask, ~mask);
1634
1635	free(data);
1636	return B_OK;
1637}
1638
1639
1640static status_t
1641write_hook(void *_data, off_t pos, const void *buf, size_t *len)
1642{
1643	etherpci_private_t *data = (etherpci_private_t *) _data;
1644	ulong buflen;
1645	int status;
1646
1647	buflen = *len;
1648	atomic_add(&data->inrw, 1);
1649	if (data->interrupted) {
1650		atomic_add(&data->inrw, -1);
1651		return B_INTERRUPTED;
1652	}
1653	/*
1654	 * Wait for somebody else (if any) to finish transmitting
1655	 */
1656	status = output_wait(data, ETHER_TRANSMIT_TIMEOUT);
1657	if (status < B_NO_ERROR || data->interrupted) {
1658		atomic_add(&data->inrw, -1);
1659		return status;
1660	}
1661
1662	io_lock(data);
1663	check_errors(data);
1664
1665	if (data->writes > 0)
1666		check_transmit_status(data);
1667
1668	etherpci_mout(data, data->ETHER_BUF_START, (const unsigned char *)buf, buflen);
1669	if (buflen < ETHER_MIN_SIZE) {
1670		/*
1671		 * Round up to ETHER_MIN_SIZE
1672		 */
1673		buflen = ETHER_MIN_SIZE;
1674	}
1675	ether_outb(data, EN0_TCNTLO, (char)(buflen & 0xff));
1676	ether_outb(data, EN0_TCNTHI, (char)(buflen >> 8));
1677	ether_outb(data, EN_CCMD, ENC_NODMA | ENC_TRANS);
1678	data->writes++;
1679	io_unlock(data);
1680	atomic_add(&data->inrw, -1);
1681	*len = buflen;
1682
1683	if (data->debug & TX)
1684		dump_packet("TX:",(unsigned char *) buf, buflen);
1685
1686	return 0;
1687}
1688
1689
1690/*! Standard driver control function */
1691static status_t
1692control_hook(void *_data, uint32 msg, void *buf, size_t len)
1693{
1694	etherpci_private_t *data = (etherpci_private_t *) _data;
1695
1696	switch (msg) {
1697		case ETHER_INIT:
1698			ETHER_DEBUG(FUNCTION, data->debug, kDevName ": control: ETHER_INIT \n");
1699			return B_OK;
1700
1701		case ETHER_GETADDR:
1702			if (data == NULL)
1703				return B_ERROR;
1704
1705			ETHER_DEBUG(FUNCTION, data->debug, kDevName ": control: GET_ADDR \n");
1706			memcpy(buf, &data->myaddr, sizeof(data->myaddr));
1707			return B_OK;
1708
1709		case ETHER_NONBLOCK:
1710			if (data == NULL)
1711				return B_ERROR;
1712
1713			memcpy(&data->nonblocking, buf, sizeof(data->nonblocking));
1714			ETHER_DEBUG(FUNCTION, data->debug, kDevName ": control: NON_BLOCK %x\n", data->nonblocking);
1715			return B_OK;
1716
1717		case ETHER_ADDMULTI:
1718			ETHER_DEBUG(FUNCTION, data->debug, kDevName ": control: DO_MULTI\n");
1719			return domulti(data, (char *)buf);
1720	}
1721
1722	return B_ERROR;
1723}
1724
1725