1/*
2 * Copyright 2006, Hideyuki Abe. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6//! Ethernet Driver for VMware PCnet/PCI virtual network controller
7
8#include "vlance.h"
9
10#include <ether_driver.h>
11
12#include <Drivers.h>
13#include <KernelExport.h>
14#include <OS.h>
15#include <PCI.h>
16
17#include <stdarg.h>
18#include <stdlib.h>
19#include <stdio.h>
20#include <string.h>
21
22
23/* debug flag definitions */
24#define ERR       0x0001
25#define INFO      0x0002
26#define RX        0x0004		/* dump received frames */
27#define TX        0x0008		/* dump transmitted frames */
28#define INTERRUPT 0x0010		/* interrupt calls */
29#define FUNCTION  0x0020		/* function calls */
30#define PCI_IO    0x0040		/* pci reads and writes */
31#define SEQ		  0x0080		/* trasnmit & receive TCP/IP sequence sequence numbers */
32#define WARN	  0x0100		/* Warnings - off on final release */
33
34/* debug flag */
35//#define DEBUG_FLG	( ERR | INFO | WARN )
36//#define DEBUG_FLG	( ERR | INFO | INTERRUPT | FUNCTION | WARN )
37#define DEBUG_FLG	( ERR | WARN )
38
39#define	DEBUG(x)	(DEBUG_FLG & (x))
40#define TRACE(x)	dprintf x
41
42/* PCI vendor and device ID's */
43#define VENDOR_ID        0x1022		/* AMD */
44#define DEVICE_ID        0x2000		/* PCnet/PCI */
45
46
47#define DEVICE_NAME "vlance"
48#define DEVICE_NAME_LEN		64
49
50#define MAX_CARDS			4		/* maximum number of driver instances */
51
52#define BUFFER_SIZE			2048L	/* B_PAGE_SIZE divided into even amounts that will hold a 1518 frame */
53#define MAX_FRAME_SIZE		1514	/* 1514 + 4 bytes checksum */
54
55/* ring buffer sizes  */
56#define	TX_BUFF_IDX			(4)
57#define	RX_BUFF_IDX			(5)
58#define TX_BUFFERS			(1 << TX_BUFF_IDX)
59#define RX_BUFFERS			(1 << RX_BUFF_IDX)		/* Must be a power of 2 */
60
61/* max number of multicast address */
62#define	MAX_MULTI			(4)
63
64
65/*
66 * 6-octet MAC address
67 */
68typedef struct {
69	uint8 ch[6];
70	uint8 rsv[2];
71} mac_addr_t;
72
73
74/* driver intance definition */
75typedef struct {
76	mac_addr_t		mac_addr;				/* MAC address */
77	int32			devID; 					/* device identifier */
78	pci_info		*devInfo;				/* device information */
79	uint16			irq;					/* our IRQ line */
80	sem_id			ilock, olock;			/* I/O semaphores */
81	int32			readLock, writeLock;	/* reentrant read/write lock */
82	int32			blockFlg;				/* for blocking (0) or nonblocking (!=0) read */
83	init_block_t	init_blk;				/* Initialization Block */
84	uint32			phys_init_blk;			/* Initialization Block physical address */
85	area_id			tx_desc_area; 			/* transmit descriptor area */
86	area_id			tx_buf_area; 			/* transmit buffer area */
87	area_id			rx_desc_area; 			/* receive descriptor area */
88	area_id			rx_buf_area; 			/* receive buffer area */
89	uchar			*tx_buf[TX_BUFFERS];	/* tx buffers */
90	uchar			*rx_buf[RX_BUFFERS];	/* rx buffers */
91	trns_desc_t		*tx_desc[TX_BUFFERS];	/* tx frame descriptors */
92	recv_desc_t		*rx_desc[RX_BUFFERS];	/* rx frame descriptors */
93	uint32			phys_tx_buf;			/* tx buffer physical address */
94	uint32			phys_rx_buf;			/* rx buffer physical address */
95	uint32			phys_tx_desc;			/* tx descriptor physical address */
96	uint32			phys_rx_desc;			/* rx descriptor physical address */
97	int16			tx_sent, tx_acked;		/* in & out index to tx buffers */
98	int16			rx_received, rx_acked;	/* in & out index to rx buffers */
99	int32			nmulti;					/* number of multicast address */
100	mac_addr_t		multi[MAX_MULTI];		/* multicast address */
101	uint32			reg_base; 				/* base address of PCI regs */
102} dev_info_t;
103
104
105/* function prototypes */
106static status_t vlance_open(const char *name, uint32 flags, void **_cookie);
107static status_t vlance_close(void *_device);
108static status_t vlance_free(void *_device);
109static status_t vlance_control(void *cookie, uint32 msg, void *buf, size_t len);
110static status_t vlance_read(void *_device, off_t pos, void *buf, size_t *len);
111static status_t vlance_write(void *_device, off_t pos, const void *buf, size_t *len);
112static int32 vlance_interrupt(void *_device);
113
114static device_hooks sDeviceHooks = {
115	vlance_open,		/* open entry point */
116	vlance_close,		/* close entry point */
117	vlance_free,		/* free entry point */
118	vlance_control,		/* control entry point */
119	vlance_read,		/* read entry point */
120	vlance_write,		/* write entry point */
121	NULL,				/* select entry point */
122	NULL,				/* deselect entry point */
123	NULL,				/* readv */
124	NULL				/* writev */
125};
126
127int32 api_version = B_CUR_DRIVER_API_VERSION;
128
129static pci_module_info *sPCI;
130static uint32 sNumOfCards;
131static char *sDeviceNames[MAX_CARDS + 1];	/* NULL-terminated */
132static pci_info *sCardInfo[MAX_CARDS];
133static int32 sOpenLock[MAX_CARDS];
134
135
136#define write8(addr, val)	(*sPCI->write_io_8)((addr), (val))
137#define write16(addr, val)	(*sPCI->write_io_16)((addr), (val))
138#define write32(addr, val)	(*sPCI->write_io_32)((addr), (val))
139#define read8(addr)			((*sPCI->read_io_8)(addr))
140#define read16(addr)		((*sPCI->read_io_16)(addr))
141#define read32(addr)		((*sPCI->read_io_32)(addr))
142
143#define RNDUP(x, y) (((x) + (y) - 1) & ~((y) - 1))
144
145
146//	#pragma mark - register access
147
148
149static inline uint32
150csr_read(dev_info_t *device, uint32 reg_num)
151{
152	write32(device->reg_base + PCNET_RAP_OFFSET, reg_num);
153	return read32(device->reg_base + PCNET_RDP_OFFSET);
154}
155
156
157static inline void
158csr_write(dev_info_t *device, uint32 reg_num, uint32 data)
159{
160	write32(device->reg_base + PCNET_RAP_OFFSET, reg_num);
161	write32(device->reg_base + PCNET_RDP_OFFSET, data);
162}
163
164
165static inline uint32
166bcr_read(dev_info_t *device, uint32 reg_num)
167{
168	write32(device->reg_base + PCNET_RAP_OFFSET, reg_num);
169	return read32(device->reg_base + PCNET_BDP_OFFSET);
170}
171
172
173static inline void
174bcr_write(dev_info_t *device, uint32 reg_num, uint32 data)
175{
176	write32(device->reg_base + PCNET_RAP_OFFSET, reg_num);
177	write32(device->reg_base + PCNET_BDP_OFFSET, data);
178}
179
180
181//	#pragma mark - misc
182
183
184static int32
185get_card_info(pci_info *info[])
186{
187	status_t status;
188	int32 i, entries;
189	pci_info *item = (pci_info *)malloc(sizeof(pci_info));
190	if (item == NULL)
191		return 0;
192
193	for (i = 0, entries = 0; entries < MAX_CARDS; i++) {
194		status = sPCI->get_nth_pci_info(i, item);
195		if (status != B_OK)
196			break;
197
198		if (item->vendor_id == VENDOR_ID && item->device_id == DEVICE_ID) {
199			/* check if the device really has an IRQ */
200			if (item->u.h0.interrupt_line == 0 || item->u.h0.interrupt_line == 0xff) {
201				TRACE((DEVICE_NAME " found with invalid IRQ - check IRQ assignement\n"));
202				continue;
203			}
204
205			TRACE((DEVICE_NAME " found at IRQ %x\n", item->u.h0.interrupt_line));
206
207			info[entries++] = item;
208			item = (pci_info *)malloc(sizeof(pci_info));
209		}
210	}
211
212	free(item);
213	return entries;
214}
215
216
217static status_t
218free_card_info(pci_info *info[])
219{
220	int32 i;
221
222	for (i = 0; i < sNumOfCards; i++) {
223		free(info[i]);
224	}
225
226	return B_OK;
227}
228
229
230static status_t
231map_pci_addr(dev_info_t *device)
232{
233	pci_info *dev_info = device->devInfo;
234	int32 pci_cmd;
235
236	pci_cmd = sPCI->read_pci_config(dev_info->bus, dev_info->device,
237		dev_info->function, PCI_command, 2);
238
239	/* turn on I/O port decode, Memory Address Decode, and Bus Mastering */
240	sPCI->write_pci_config(dev_info->bus, dev_info->device,
241		dev_info->function, PCI_command, 2,
242		pci_cmd | PCI_command_io | PCI_command_memory | PCI_command_master);
243
244	device->reg_base = dev_info->u.h0.base_registers[0];
245
246#if DEBUG(PCI_IO)
247	dprintf(DEVICE_NAME ": reg_base=%x\n", device->reg_base);
248#endif
249
250	return B_OK;
251}
252
253
254static status_t
255alloc_buffers(dev_info_t *device)
256{
257	uint32 size;
258	uint16 i;
259	physical_entry entry;
260
261	/* get physical address of Initialization Block */
262	size = RNDUP(sizeof(dev_info_t), B_PAGE_SIZE);
263	get_memory_map(&(device->init_blk), size, &entry, 1);
264	device->phys_init_blk = entry.address;
265
266	TRACE((DEVICE_NAME " init block va=%p pa=%p, size %lx\n",
267		&(device->init_blk), (void *)device->phys_init_blk, size));
268
269	/* create tx descriptor area */
270	size = RNDUP(sizeof(trns_desc_t) * TX_BUFFERS, B_PAGE_SIZE);
271	device->tx_desc_area = create_area(DEVICE_NAME " tx descriptors",
272		(void **)device->tx_desc, B_ANY_KERNEL_ADDRESS, size,
273		B_32_BIT_FULL_LOCK, B_READ_AREA | B_WRITE_AREA);
274	if (device->tx_desc_area < 0)
275		return device->tx_desc_area;
276
277	for (i = 1; i < TX_BUFFERS; i++) {
278		device->tx_desc[i] = (device->tx_desc[i-1]) + 1;
279	}
280	/* get physical address of tx descriptor */
281	get_memory_map(device->tx_desc[0], size, &entry, 1);
282	device->phys_tx_desc = entry.address;
283
284	TRACE((DEVICE_NAME " create tx desc area va=%p pa=%p sz=%lx\n",
285		device->tx_desc[0], (void *)device->phys_tx_desc, size));
286
287	/* create tx buffer area */
288	size = RNDUP(BUFFER_SIZE * TX_BUFFERS, B_PAGE_SIZE);
289	device->tx_buf_area = create_area(DEVICE_NAME " tx buffers",
290		(void **)device->tx_buf, B_ANY_KERNEL_ADDRESS, size,
291		B_32_BIT_FULL_LOCK, B_READ_AREA | B_WRITE_AREA);
292	if (device->tx_buf_area < 0) {
293		delete_area(device->tx_desc_area);	// sensitive to alloc ordering
294		return device->tx_buf_area;
295	}
296
297	for (i = 1; i < TX_BUFFERS; i++) {
298		device->tx_buf[i] = (device->tx_buf[i-1]) + BUFFER_SIZE;
299	}
300
301	/* get physical address of tx buffer */
302	get_memory_map(device->tx_buf[0], size, &entry, 1);
303	device->phys_tx_buf = entry.address;
304
305	TRACE((DEVICE_NAME " create tx buf area va=%p pa=%08lx sz=%lx\n",
306		device->tx_buf[0], device->tx_desc[0]->s.tbadr, size));
307
308	/* create rx descriptor area */
309	size = RNDUP( sizeof(recv_desc_t) * RX_BUFFERS, B_PAGE_SIZE);
310	device->rx_desc_area = create_area(DEVICE_NAME " rx descriptors",
311		(void **)device->rx_desc, B_ANY_KERNEL_ADDRESS, size,
312		B_32_BIT_FULL_LOCK, B_READ_AREA | B_WRITE_AREA);
313	if (device->rx_desc_area < 0) {
314		delete_area(device->tx_desc_area);
315		delete_area(device->tx_buf_area);	// sensitive to alloc ordering
316		return device->rx_desc_area;
317	}
318
319	for (i = 1; i < RX_BUFFERS; i++) {
320		device->rx_desc[i] = (device->rx_desc[i-1]) + 1;
321	}
322	/* get physical address of rx descriptor */
323	get_memory_map(device->rx_desc[0], size, &entry, 1);
324	device->phys_rx_desc = entry.address;
325
326	TRACE((DEVICE_NAME " create rx desc area va=%p pa=%p sz=%lx\n",
327		device->rx_desc[0], (void *)device->phys_rx_desc, size));
328
329	/* create rx buffer area */
330	size = RNDUP(BUFFER_SIZE * RX_BUFFERS, B_PAGE_SIZE);
331	device->rx_buf_area = create_area(DEVICE_NAME " rx buffers",
332		(void **)device->rx_buf, B_ANY_KERNEL_ADDRESS, size,
333		B_32_BIT_FULL_LOCK, B_READ_AREA | B_WRITE_AREA);
334	if (device->rx_buf_area < 0) {
335		delete_area(device->tx_desc_area);
336		delete_area(device->tx_buf_area);
337		delete_area(device->rx_desc_area);	// sensitive to alloc ordering
338		return device->rx_buf_area;
339	}
340	for (i = 1; i < RX_BUFFERS; i++) {
341		device->rx_buf[i] = (device->rx_buf[i-1]) + BUFFER_SIZE;
342	}
343	/* get physical address of rx buffer */
344	get_memory_map(device->rx_buf[0], size, &entry, 1);
345	device->phys_rx_buf = entry.address;
346
347	TRACE((DEVICE_NAME " create rx buf area va=%p pa=%08lx sz=%lx\n",
348		device->rx_buf[0], device->rx_desc[0]->s.rbadr, size));
349
350	return B_OK;
351}
352
353
354static status_t
355init_buffers(dev_info_t *device)
356{
357	int i;
358
359	/* initilize tx descriptors */
360	for (i = 0; i < TX_BUFFERS; i++) {
361		device->tx_desc[i]->s.tbadr = device->phys_tx_buf + BUFFER_SIZE * i;
362		device->tx_desc[i]->s.bcnt = -BUFFER_SIZE;
363		device->tx_desc[i]->s.status = 0;
364		device->tx_desc[i]->s.misc = 0UL;
365		device->tx_desc[i]->s.rsvd = 0UL;
366	}
367
368	/* initialize rx descriptors */
369	for (i = 0; i < RX_BUFFERS; i++) {
370		device->rx_desc[i]->s.rbadr = device->phys_rx_buf + BUFFER_SIZE * i;
371		device->rx_desc[i]->s.bcnt = -BUFFER_SIZE;
372//		device->rx_desc[i]->s.status = 0;
373		device->rx_desc[i]->s.status = 0x8000;	/* OWN */
374		device->rx_desc[i]->s.mcnt = 0UL;
375		device->rx_desc[i]->s.rsvd = 0UL;
376	}
377
378	/* initialize frame indexes */
379	device->tx_sent = device->tx_acked = device->rx_received = device->rx_acked = 0;
380
381	return B_OK;
382}
383
384
385static void
386free_buffers(dev_info_t *device)
387{
388	delete_area(device->tx_desc_area);
389	delete_area(device->tx_buf_area);
390	delete_area(device->rx_desc_area);
391	delete_area(device->rx_buf_area);
392}
393
394
395static void
396get_mac_addr(dev_info_t *device)
397{
398	int i;
399
400	TRACE((DEVICE_NAME ": Mac address: "));
401
402	for (i = 0; i < 6; i++) {
403		device->mac_addr.ch[i] = read8(device->reg_base + PCNET_APROM_OFFSET + i);
404		TRACE((" %02x", device->mac_addr.ch[i]));
405	}
406
407	TRACE(("\n"));
408}
409
410
411/* set hardware so all packets are received. */
412static status_t
413setpromisc(dev_info_t *device)
414{
415	TRACE((DEVICE_NAME ":setpormisc\n"));
416
417	csr_write(device, PCNET_CSR_STATUS, 0x0004UL);
418	csr_write(device, PCNET_CSR_MODE, 0x8000UL);	/* promiscous mode */
419	csr_write(device, PCNET_CSR_STATUS, 0x0042UL);
420
421	return B_OK;
422}
423
424
425#define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */
426
427static status_t
428domulti(dev_info_t *device, uint8 *addr)
429{
430	uint16 mcast_table[4];
431	uint8 *addrs;
432	int i, j, bit, byte;
433	uint32 crc, poly = CRC_POLYNOMIAL_LE;
434
435	if (device->nmulti == MAX_MULTI)
436		return B_ERROR;
437
438	for (i = 0; i < device->nmulti; i++) {
439		if (memcmp(&device->multi[i], addr, sizeof(device->multi[i])) == 0)
440			break;
441	}
442	if (i != device->nmulti)
443		return B_ERROR;
444
445	// only copy if it isn't there already
446	memcpy(&device->multi[i], addr, sizeof(device->multi[i]));
447	device->nmulti++;
448
449	TRACE((DEVICE_NAME ": domulti %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
450		addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]));
451
452	/* clear the multicast filter */
453	mcast_table[0] = 0;	mcast_table[1] = 0;
454	mcast_table[2] = 0;	mcast_table[3] = 0;
455
456	/* set addresses */
457	for (i = 0; i < device->nmulti; i++) {
458		addrs = (uint8 *)(&(device->multi[i]));
459		/* multicast address? */
460		if (!(*addrs & 1))
461			break;
462
463		crc = 0xffffffff;
464		for (byte = 0; byte < 6; byte++) {
465			for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
466				int test;
467
468				test = ((bit ^ crc) & 0x01);
469				crc >>= 1;
470				if (test)
471					crc = crc ^ poly;
472			}
473		}
474		crc = crc >> 26;
475		mcast_table[crc >> 4] |= 1 << (crc & 0xf);
476	}
477
478	csr_write(device, PCNET_CSR_STATUS, 0x0004UL);
479	csr_write(device, PCNET_CSR_MODE, 0x0000UL);	/* portsel ?? */
480	csr_write(device, PCNET_CSR_LADRF0, mcast_table[0]);
481	csr_write(device, PCNET_CSR_LADRF1, mcast_table[1]);
482	csr_write(device, PCNET_CSR_LADRF2, mcast_table[2]);
483	csr_write(device, PCNET_CSR_LADRF3, mcast_table[3]);
484	csr_write(device, PCNET_CSR_STATUS, 0x0042UL);
485
486	return B_OK;
487}
488
489
490static void
491reset_device(dev_info_t *device)
492{
493	TRACE((DEVICE_NAME ": reset_device reset the NIC hardware\n"));
494
495	read32(device->reg_base + PCNET_RST_OFFSET);
496	write32(device->reg_base + PCNET_RST_OFFSET, 0UL);
497	snooze(2);	/* wait >1us */
498};
499
500
501/*
502 * allocate and initialize semaphores.
503 */
504static status_t
505alloc_resources(dev_info_t *device)
506{
507	/* rx semaphores */
508	device->ilock = create_sem(0, DEVICE_NAME " rx");
509	if (device->ilock < 0)
510		return device->ilock;
511
512	set_sem_owner(device->ilock, B_SYSTEM_TEAM);
513
514	/* tx semaphores */
515	device->olock = create_sem(TX_BUFFERS, DEVICE_NAME " tx");
516	if (device->olock < 0) {
517		delete_sem(device->ilock);
518		return device->olock;
519	}
520
521	set_sem_owner(device->olock, B_SYSTEM_TEAM);
522
523	device->readLock = device->writeLock = 0;
524	device->blockFlg = 0;	// set blocking
525
526	return B_OK;
527}
528
529
530static void
531free_resources(dev_info_t *device)
532{
533	delete_sem(device->ilock);
534	delete_sem(device->olock);
535}
536
537
538//	#pragma mark - driver API
539
540
541status_t
542init_hardware(void)
543{
544	TRACE((DEVICE_NAME ": init hardware\n"));
545	return B_OK;
546}
547
548
549status_t
550init_driver()
551{
552	status_t 	status;
553	char		devName[DEVICE_NAME_LEN];
554	int32		i;
555
556	TRACE((DEVICE_NAME ": init_driver\n"));
557
558// TODO: this does not compile with our GCC 2.95.3
559#if 0
560{
561	uint32 mgc_num;
562	/* check VMware */
563	asm volatile (
564		"movl	$0x564d5868, %%eax; "
565		"movl	$0, %%ebx; "
566		"movw	$0x000a, %%cx; "
567		"movw	$0x5658, %%dx; "
568		"inl	%%dx, %%eax"
569		: "=b"(mgc_num)
570		:
571		: "eax", "ecx", "edx");
572
573	TRACE((DEVICE_NAME ": VMware magic number %lx\n", mgc_num));
574
575	if (!(mgc_num == 0x564d5868))
576		return ENODEV;
577}
578#endif
579
580	status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCI);
581	if (status != B_OK)
582		return status;
583
584	/* find LAN cards */
585	sNumOfCards = get_card_info(sCardInfo);
586	if (sNumOfCards == 0) {
587		free_card_info(sCardInfo);
588		put_module(B_PCI_MODULE_NAME);
589		return B_ERROR;
590	}
591
592	/* create device name list*/
593	for (i = 0; i < sNumOfCards; i++) {
594		sprintf(devName, "net/%s/%ld", DEVICE_NAME, i);
595		sDeviceNames[i] = (char *)malloc(DEVICE_NAME_LEN);
596		strcpy(sDeviceNames[i], devName);
597	}
598	sDeviceNames[sNumOfCards] = NULL;
599
600	return B_OK;
601}
602
603
604void
605uninit_driver(void)
606{
607	int32 	i;
608
609	/* free device name list*/
610	for (i = 0; i < sNumOfCards; i++) {
611		free(sDeviceNames[i]);
612	}
613
614	/* free device list*/
615	free_card_info(sCardInfo);
616	put_module(B_PCI_MODULE_NAME);
617}
618
619
620const char **
621publish_devices(void)
622{
623	TRACE((DEVICE_NAME ": publish_devices()\n" ));
624	return (const char **)sDeviceNames;
625}
626
627
628device_hooks *
629find_device(const char *name)
630{
631	int32 	i;
632
633	/* find device name */
634	for (i = 0; i < sNumOfCards; i++) {
635		if (!strcmp(name, sDeviceNames[i]))
636			return &sDeviceHooks;
637	}
638
639	return NULL;
640}
641
642
643//	#pragma mark - device API
644
645
646static status_t
647vlance_open(const char *name, uint32 flags, void **cookie)
648{
649	int32 devID;
650	status_t status;
651	dev_info_t *device;
652
653	/*	find device name */
654	for (devID = 0; devID < sNumOfCards; devID++) {
655		if (!strcmp(name, sDeviceNames[devID]))
656			break;
657	}
658	if (devID >= sNumOfCards)
659		return B_BAD_VALUE;
660
661	/* check if the device is busy and set in-use flag if not */
662	if (atomic_or(&(sOpenLock[devID]), 1))
663		return B_BUSY;
664
665	/* allocate storage for the cookie */
666	*cookie = device = (dev_info_t *)malloc(sizeof(dev_info_t));
667	if (device == NULL) {
668		status = B_NO_MEMORY;
669		goto err0;
670	}
671	memset(device, 0, sizeof(dev_info_t));
672
673	/* setup the cookie */
674	device->devInfo = sCardInfo[devID];
675	device->devID = devID;
676
677	TRACE((DEVICE_NAME ": open %s device=%p\n", name, device));
678
679	/* enable access to the cards address space */
680	status = map_pci_addr(device);
681	if (status != B_OK)
682		goto err1;
683
684	status = alloc_resources(device);
685	if (status != B_OK)
686		goto err1;
687
688	/* init device */
689	reset_device(device);
690
691	/* allocate and initialize frame buffer rings & descriptors */
692	status = alloc_buffers(device);
693	if (status != B_OK)
694		goto err2;
695	status = init_buffers(device);
696	if (status != B_OK)
697		goto err2;
698
699	/* setup interrupts */
700	install_io_interrupt_handler(device->devInfo->u.h0.interrupt_line,
701		vlance_interrupt, *cookie, 0);
702	/* init hardware */
703
704	TRACE((DEVICE_NAME ": hardware specific init\n"));
705
706	write32(device->reg_base + PCNET_RDP_OFFSET, 0UL);	/* DWIO mode */
707	bcr_write(device, PCNET_BCR_SWS, 0x0002UL);	/* 32bit mode */
708
709	get_mac_addr(device);
710
711	device->init_blk.s.mode = ((TX_BUFF_IDX & 0x0f) << 28) | ((RX_BUFF_IDX & 0x0f) << 20) | 0x0000UL;	/* TLEN, RLEN */
712	memcpy(device->init_blk.s.padr, &(device->mac_addr), sizeof(mac_addr_t));
713	device->init_blk.s.padr[6] = 0;
714	device->init_blk.s.padr[7] = 0;
715	device->init_blk.s.ladr[0] = 0UL;
716	device->init_blk.s.ladr[1] = 0UL;
717	device->init_blk.s.rdra = device->phys_rx_desc;
718	device->init_blk.s.tdra = device->phys_tx_desc;
719
720	{
721		int i;
722		for (i = 0; i < sizeof(init_block_t); i++) {
723			TRACE((" %02X", *(((unsigned char *)&(device->init_blk)) + i)));
724		}
725		TRACE(("\n"));
726	}
727
728	csr_write(device, PCNET_CSR_IADDR0, (device->phys_init_blk) & 0xffffUL);	/* set init block address L */
729	csr_write(device, PCNET_CSR_IADDR1, (device->phys_init_blk) >> 16);			/* set init block address H */
730	csr_write(device, PCNET_CSR_STATUS, 0x0001UL);				/* INIT */
731	while (!(csr_read(device, PCNET_CSR_STATUS) & 0x0100UL));	/* check IDON */
732	csr_write(device, PCNET_CSR_STATUS, 0x0004UL);				/* STOP */
733
734#if DEBUG(INFO)
735	dprintf(DEVICE_NAME ": STATUS = %04X\n", csr_read(device, PCNET_CSR_STATUS));
736	dprintf(DEVICE_NAME ": IADDR0 = %04X\n", csr_read(device, PCNET_CSR_IADDR0));
737	dprintf(DEVICE_NAME ": IADDR1 = %04X\n", csr_read(device, PCNET_CSR_IADDR1));
738	dprintf(DEVICE_NAME ": MODE = %04X\n", csr_read(device, PCNET_CSR_MODE));
739	dprintf(DEVICE_NAME ": PADR0 = %04X\n", csr_read(device, PCNET_CSR_PADR0));
740	dprintf(DEVICE_NAME ": PADR1 = %04X\n", csr_read(device, PCNET_CSR_PADR1));
741	dprintf(DEVICE_NAME ": PADR2 = %04X\n", csr_read(device, PCNET_CSR_PADR2));
742	dprintf(DEVICE_NAME ": LADRF0 = %04X\n", csr_read(device, PCNET_CSR_LADRF0));
743	dprintf(DEVICE_NAME ": LADRF1 = %04X\n", csr_read(device, PCNET_CSR_LADRF1));
744	dprintf(DEVICE_NAME ": LADRF2 = %04X\n", csr_read(device, PCNET_CSR_LADRF2));
745	dprintf(DEVICE_NAME ": LADRF3 = %04X\n", csr_read(device, PCNET_CSR_LADRF3));
746	dprintf(DEVICE_NAME ": BADRL = %04X\n", csr_read(device, PCNET_CSR_BADRL));
747	dprintf(DEVICE_NAME ": BADRH = %04X\n", csr_read(device, PCNET_CSR_BADRH));
748	dprintf(DEVICE_NAME ": BADXL = %04X\n", csr_read(device, PCNET_CSR_BADXL));
749	dprintf(DEVICE_NAME ": BADXH = %04X\n", csr_read(device, PCNET_CSR_BADXH));
750	dprintf(DEVICE_NAME ": BCR18 = %04X\n", bcr_read(device, PCNET_BCR_BSBC));
751	dprintf(DEVICE_NAME ": BCR20 = %04X\n", bcr_read(device, PCNET_BCR_SWS));
752#endif
753	csr_write(device, PCNET_CSR_STATUS, 0x7f00);	/* clear int source */
754	csr_write(device, PCNET_CSR_STATUS, 0x0042);	/* IENA, STRT */
755
756	return B_OK;
757
758err2:
759	free_buffers(device);
760err1:
761	free_resources(device);
762	free(device);
763err0:
764	atomic_and(&(sOpenLock[devID]), 0);
765	return status;
766}
767
768
769static status_t
770vlance_close(void *_device)
771{
772	dev_info_t *device = (dev_info_t *) _device;
773
774	TRACE((DEVICE_NAME ": vlance_close\n"));
775
776	csr_write(device, PCNET_CSR_STATUS, 0x0004);	/* STOP */
777	TRACE((DEVICE_NAME ": STATUS = %04lx\n", csr_read(device,PCNET_CSR_STATUS)));
778
779	/* release resources */
780	free_resources(device);
781
782	return B_OK;
783}
784
785
786static status_t
787vlance_free(void *cookie)
788{
789	dev_info_t *device = (dev_info_t *)cookie;
790
791	TRACE((DEVICE_NAME": free %p\n", device));
792
793    /* remove Interrupt Handler */
794	remove_io_interrupt_handler(device->devInfo->u.h0.interrupt_line, vlance_interrupt, cookie);
795
796	free_buffers(device);
797
798	/* device is now available again */
799	atomic_and(&(sOpenLock[device->devID]), 0);
800
801	free(device);
802	return B_OK;
803}
804
805
806static status_t
807vlance_control(void *cookie, uint32 op, void *buf, size_t len)
808{
809	dev_info_t *device = (dev_info_t *)cookie;
810
811	switch (op) {
812		case ETHER_GETADDR: {
813			uint8 i;
814			TRACE((DEVICE_NAME ": control ether_getaddr\n"));
815
816			for (i = 0; i < 6; i++) {
817				((uint8 *)buf)[i] = device->mac_addr.ch[i];
818			}
819			return B_OK;
820		}
821		case ETHER_INIT:
822			TRACE((DEVICE_NAME ": control init\n"));
823			return B_OK;
824
825		case ETHER_GETFRAMESIZE:
826			TRACE((DEVICE_NAME ": control get_framesize\n"));
827			*(uint32 *)buf = MAX_FRAME_SIZE;
828			return B_OK;
829
830		case ETHER_ADDMULTI:
831			TRACE((DEVICE_NAME ": control add multi\n"));
832			return domulti(device, (unsigned char *)buf);
833
834		case ETHER_SETPROMISC:
835			TRACE((DEVICE_NAME ": control set promiscuous\n"));
836			return setpromisc(device);
837
838		case ETHER_NONBLOCK:
839			TRACE((DEVICE_NAME ": control blocking %ld\n", *((int32*)buf)));
840
841			if (*((int32 *)buf))
842				device->blockFlg = 1;	// set non-blocking
843			else
844				device->blockFlg = 0;	// set blocking
845			return B_OK;
846	}
847
848	return B_BAD_VALUE;
849}
850
851
852static status_t
853vlance_read(void *_device, off_t pos, void *buf, size_t *len)
854{
855	dev_info_t *device = (dev_info_t *) _device;
856	int16 frame_size;
857	uint32 flags;
858	status_t status;
859
860//	*len = 0;
861
862#if DEBUG(INFO)
863	dprintf(DEVICE_NAME ": read buf %p, len %d\n", buf, *len);
864#endif
865
866	/* block until data is available (default) */
867	flags = B_CAN_INTERRUPT;
868	if(device->blockFlg) flags |= B_RELATIVE_TIMEOUT;	// non-blocking (0-timeout)
869	status = acquire_sem_etc(device->ilock, 1, flags, 0);
870	if(status != B_NO_ERROR) {
871#if DEBUG(INFO)
872		dprintf(DEVICE_NAME ": cannot acquire rx semaphore\n");
873#endif
874		*len = 0;
875		return status;
876	}
877#if DEBUG(INFO)
878	dprintf(DEVICE_NAME ": try to atomic_or readLock\n");
879#endif
880	/* prevent reentrant read */
881	if(atomic_or(&device->readLock, 1)) {
882#if DEBUG(ERR)
883		dprintf(DEVICE_NAME ": cannot atomic_or readLock\n");
884#endif
885		release_sem_etc(device->ilock, 1, 0);
886		*len = 0;
887		return B_ERROR;
888	}
889
890	/* hardware specific code to copy data from the NIC into buf */
891	if((device->rx_desc[device->rx_acked]->s.status) & 0x8000) {	/* owned by controller */
892#if DEBUG(ERR)
893		dprintf(DEVICE_NAME ": rx desc owned by controller\n");
894#endif
895		*len = 0;
896		status = B_ERROR;
897	} else {
898#if DEBUG(INFO)
899		dprintf(DEVICE_NAME ": rx desc owned by host\n");
900#endif
901		frame_size = 0;
902		status = B_ERROR;
903		if(!((device->rx_desc[device->rx_acked]->s.status) & 0x4000)) {	/* not receive error */
904			frame_size = (device->rx_desc[device->rx_acked]->s.mcnt) & 0xfff;
905			if(frame_size > *len) frame_size = *len;
906			memcpy(buf, device->rx_buf[device->rx_acked], frame_size);
907			status = B_OK;
908		}
909		if(frame_size < *len) *len = frame_size;
910		device->rx_desc[device->rx_acked]->s.mcnt = 0;
911		device->rx_desc[device->rx_acked]->s.status = 0x8000;	/* OWN */
912		device->rx_acked = (device->rx_acked + 1) & (RX_BUFFERS - 1);
913	}
914
915	/* release reentrant lock */
916	atomic_and(&device->readLock, 0);
917
918	return status;
919}
920
921
922static status_t
923vlance_write(void *_device, off_t pos, const void *buf, size_t *len)
924{
925	dev_info_t *device = (dev_info_t *)_device;
926	int16 frame_size;
927	status_t status;
928
929	TRACE((DEVICE_NAME ": write buf %p len %lu\n", buf, *len));
930
931	if (*len > MAX_FRAME_SIZE) {
932#if DEBUG(ERR)
933		dprintf(DEVICE_NAME ": write %lu > 1514 tooo long\n", *len);
934#endif
935		*len = MAX_FRAME_SIZE;
936	}
937	frame_size = *len;
938
939	status = acquire_sem_etc(device->olock, 1, B_CAN_INTERRUPT, 0);
940	if (status != B_NO_ERROR) {
941		*len = 0;
942		return status;
943	}
944
945	/* prevent reentrant write */
946	if (atomic_or(&device->writeLock, 1)) {
947		release_sem_etc(device->olock, 1, 0);
948		*len = 0;
949		return B_ERROR;
950	}
951
952	/* hardware specific code to transmit buff */
953	if ((device->tx_desc[device->tx_sent]->s.status) & 0x8000) {
954		/* owned by controller */
955#if DEBUG(ERR)
956		dprintf(DEVICE_NAME ": tx desc owned by controller\n");
957#endif
958	} else {
959		TRACE((DEVICE_NAME ": tx desc owned by host\n"));
960
961		memcpy(device->tx_buf[device->tx_sent], buf, frame_size);
962		device->tx_desc[device->tx_sent]->s.bcnt = -frame_size;
963//		(device->tx_desc[device->tx_sent]->s.status) |= 0x8300;	/* OWN, STP, ENP */
964		(device->tx_desc[device->tx_sent]->s.status) |= 0x9300;	/* OWN, LTINT, STP, ENP */
965		device->tx_sent = (device->tx_sent + 1) & (TX_BUFFERS - 1);
966		csr_write(device, PCNET_CSR_STATUS, 0x0048UL);	/* IENA, TDMD */
967	}
968
969	/* release reentrant lock */
970	atomic_and(&device->writeLock, 0);
971
972	return B_OK;
973}
974
975
976/*! LAN controller interrupt handler */
977static int32
978vlance_interrupt(void *_device)
979{
980	dev_info_t	*device = (dev_info_t *)_device;
981	int32		handled = B_UNHANDLED_INTERRUPT;
982	int32		interruptStatus;
983	cpu_status	state;
984
985#if DEBUG(INTERRUPT)
986	dprintf(DEVICE_NAME ": ISR_ENTRY\n");
987#endif
988	state = disable_interrupts();	/* disable int state */
989
990	interruptStatus = csr_read(device, PCNET_CSR_STATUS);
991	if (interruptStatus & 0x0080) {
992#if DEBUG(INTERRUPT)
993		dprintf(DEVICE_NAME ": status %04X\n", interruptStatus);
994#endif
995
996		/* clear interrupts */
997		csr_write(device, PCNET_CSR_STATUS, 0x7f00);
998
999		if (interruptStatus & 0x8000) {
1000			/* Error */
1001#if DEBUG(ERR)
1002			dprintf(DEVICE_NAME ": int error status %04lx\n", interruptStatus);
1003#endif
1004			csr_write(device, PCNET_CSR_STATUS, 0x0004);	/* STOP */
1005			init_buffers(device);
1006			csr_write(device, PCNET_CSR_STATUS, 0x0001UL);	/* INIT */
1007			while(!(csr_read(device, PCNET_CSR_STATUS) & 0x0100UL));	/* check IDON */
1008			csr_write(device, PCNET_CSR_STATUS, 0x0042);	/* IENA, STRT */
1009			/* init semaphore ??? */
1010			release_sem_etc(device->olock, TX_BUFFERS, B_DO_NOT_RESCHEDULE);
1011			acquire_sem_etc(device->ilock, RX_BUFFERS, B_RELATIVE_TIMEOUT, 0);
1012			/* not count TINT & RINT ??? */
1013			interruptStatus &= ~0x0600;
1014		}
1015		if (interruptStatus & 0x0200) {	/* TINT */
1016			while (!((device->tx_desc[device->tx_acked]->s.status) & 0x8000)) {
1017				//dprintf(DEVICE_NAME ": rel tx sem\n");
1018				release_sem_etc(device->olock, 1, B_DO_NOT_RESCHEDULE);
1019				device->tx_acked = (device->tx_acked + 1) & (TX_BUFFERS - 1);
1020				if(device->tx_acked == device->tx_sent) break;
1021			}
1022		}
1023		if (interruptStatus & 0x0400) {	/* RINT */
1024			while (!((device->rx_desc[device->rx_received]->s.status) & 0x8000)) {
1025				//dprintf(DEVICE_NAME ": rel rx sem\n");
1026				release_sem_etc(device->ilock, 1, B_DO_NOT_RESCHEDULE);
1027				device->rx_received = (device->rx_received + 1) & (RX_BUFFERS - 1);
1028			}
1029		}
1030
1031		handled = B_INVOKE_SCHEDULER;   /* set because the interrupt was from the NIC, not some other device sharing the interrupt line */
1032
1033#if DEBUG(INTERRUPT)
1034		dprintf(DEVICE_NAME ": ISR - its ours\n");
1035#endif
1036	}
1037
1038	csr_write(device, PCNET_CSR_STATUS, 0x0042);
1039
1040	restore_interrupts(state);	/* restore int state */
1041
1042	return handled;
1043}
1044
1045
1046