1/*
2 * Copyright (c) 2003-2004 Stefano Ceccherini (stefano.ceccherini@gmail.com)
3 * Copyright (c) 1997, 1998
4 *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by Bill Paul.
17 * 4. Neither the name of the author nor the names of any co-contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35#ifndef __WB840_H
36#define __WB840_H
37
38#include <PCI.h>
39#include <KernelExport.h>
40#include "ether_driver.h"
41
42/*
43 * Winbond register definitions.
44 */
45enum registers {
46	WB_BUSCTL 			= 0x00,	/* bus control */
47	WB_TXSTART 			= 0x04,	/* tx start demand */
48	WB_RXSTART 			= 0x08,	/* rx start demand */
49	WB_RXADDR 			= 0x0C,	/* rx descriptor list start addr */
50	WB_TXADDR 			= 0x10,	/* tx descriptor list start addr */
51	WB_ISR 				= 0x14,	/* interrupt status register */
52	WB_NETCFG 			= 0x18,	/* network config register */
53	WB_IMR 				= 0x1C,	/* interrupt mask */
54	WB_FRAMESDISCARDED	= 0x20,	/* # of discarded frames */
55	WB_SIO 				= 0x24,	/* MII and ROM/EEPROM access */
56	WB_BOOTROMADDR 		= 0x28,
57	WB_TIMER 			= 0x2C,	/* general timer */
58	WB_CURRXCTL 		= 0x30,	/* current RX descriptor */
59	WB_CURRXBUF 		= 0x34,	/* current RX buffer */
60	WB_MAR0 			= 0x38,	/* multicast filter 0 */
61	WB_MAR1 			= 0x3C,	/* multicast filter 1 */
62	WB_NODE0 			= 0x40,	/* physical address 0 */
63	WB_NODE1 			= 0x44,	/* physical address 1 */
64	WB_BOOTROMSIZE 		= 0x48,	/* boot ROM size */
65	WB_CURTXCTL	 		= 0x4C,	/* current TX descriptor */
66	WB_CURTXBUF 		= 0x50,	/* current TX buffer */
67};
68
69/*
70 * Bus control bits.
71 */
72enum busControlBits {
73	WB_BUSCTL_RESET = 0x00000001,
74	WB_BUSCTL_ARBITRATION = 0x00000002,
75	WB_BUSCTL_SKIPLEN = 0x0000007C,
76	WB_BUSCTL_BUF_BIGENDIAN = 0x00000080,
77	WB_BUSCTL_BURSTLEN = 0x00003F00,
78	WB_BUSCTL_CACHEALIGN = 0x0000C000,
79	WB_BUSCTL_DES_BIGENDIAN = 0x00100000,
80	WB_BUSCTL_WAIT = 0x00200000,
81	WB_BUSCTL_MUSTBEONE = 0x00400000,
82
83	WB_SKIPLEN_1LONG = 0x00000004,
84	WB_SKIPLEN_2LONG = 0x00000008,
85	WB_SKIPLEN_3LONG = 0x00000010,
86	WB_SKIPLEN_4LONG = 0x00000020,
87	WB_SKIPLEN_5LONG = 0x00000040,
88
89	WB_CACHEALIGN_NONE = 0x00000000,
90	WB_CACHEALIGN_8LONG = 0x00004000,
91	WB_CACHEALIGN_16LONG = 0x00008000,
92	WB_CACHEALIGN_32LONG = 0x0000C000,
93
94	WB_BURSTLEN_USECA = 0x00000000,
95	WB_BURSTLEN_1LONG = 0x00000100,
96	WB_BURSTLEN_2LONG = 0x00000200,
97	WB_BURSTLEN_4LONG = 0x00000400,
98	WB_BURSTLEN_8LONG = 0x00000800,
99	WB_BURSTLEN_16LONG = 0x00001000,
100	WB_BURSTLEN_32LONG = 0x00002000,
101
102};
103
104#define WB_BUSCTL_CONFIG (WB_CACHEALIGN_8LONG|WB_SKIPLEN_4LONG|WB_BURSTLEN_8LONG)
105
106/*
107 * Interrupt status bits.
108 */
109enum InterruptStatusBits {
110	WB_ISR_TX_OK = 0x00000001,
111	WB_ISR_TX_IDLE = 0x00000002,
112	WB_ISR_TX_NOBUF = 0x00000004,
113	WB_ISR_RX_EARLY = 0x00000008,
114	WB_ISR_RX_ERR = 0x00000010,
115	WB_ISR_TX_UNDERRUN = 0x00000020,
116	WB_ISR_RX_OK = 0x00000040,
117	WB_ISR_RX_NOBUF = 0x00000080,
118	WB_ISR_RX_IDLE = 0x00000100,
119	WB_ISR_TX_EARLY = 0x00000400,
120	WB_ISR_TIMER_EXPIRED = 0x00000800,
121	WB_ISR_BUS_ERR = 0x00002000,
122	WB_ISR_ABNORMAL = 0x00008000,
123	WB_ISR_NORMAL = 0x00010000,
124	WB_ISR_RX_STATE	= 0x000E0000,
125	WB_ISR_TX_STATE = 0x00700000,
126	WB_ISR_BUSERRTYPE = 0x03800000,
127};
128
129/*
130 * The RX_STATE and TX_STATE fields are not described anywhere in the
131 * Winbond datasheet, however it appears that the Winbond chip is an
132 * attempt at a DEC 'tulip' clone, hence the ISR register is identical
133 * to that of the tulip chip and we can steal the bit definitions from
134 * the tulip documentation.
135 */
136enum rxState {
137	WB_RXSTATE_STOPPED 	= 0x00000000, 	/* 000 - Stopped */
138	WB_RXSTATE_FETCH 	= 0x00020000,	/* 001 - Fetching descriptor */
139	WB_RXSTATE_ENDCHECK	= 0x00040000,	/* 010 - check for rx end */
140	WB_RXSTATE_WAIT 	= 0x00060000,	/* 011 - waiting for packet */
141	WB_RXSTATE_SUSPEND 	= 0x00080000,	/* 100 - suspend rx */
142	WB_RXSTATE_CLOSE 	= 0x000A0000,	/* 101 - close tx desc */
143	WB_RXSTATE_FLUSH 	= 0x000C0000,	/* 110 - flush from FIFO */
144	WB_RXSTATE_DEQUEUE 	= 0x000E0000,	/* 111 - dequeue from FIFO */
145};
146
147enum txState {
148	 WB_TXSTATE_RESET 	= 0x00000000,	/* 000 - reset */
149	 WB_TXSTATE_FETCH 	= 0x00100000,	/* 001 - fetching descriptor */
150	 WB_TXSTATE_WAITEND = 0x00200000,	/* 010 - wait for tx end */
151	 WB_TXSTATE_READING = 0x00300000,	/* 011 - read and enqueue */
152	 WB_TXSTATE_RSVD 	= 0x00400000,	/* 100 - reserved */
153	 WB_TXSTATE_SETUP 	= 0x00500000,	/* 101 - setup packet */
154	 WB_TXSTATE_SUSPEND = 0x00600000,	/* 110 - suspend tx */
155	 WB_TXSTATE_CLOSE 	= 0x00700000,	/* 111 - close tx desc */
156};
157/*
158 * Network config bits.
159 */
160enum networkConfigBits {
161	WB_NETCFG_RX_ON 		= 0x00000002,
162	WB_NETCFG_RX_ALLPHYS 	= 0x00000008,
163	WB_NETCFG_RX_MULTI 		= 0x00000010,
164	WB_NETCFG_RX_BROAD 		= 0x00000020,
165	WB_NETCFG_RX_RUNT 		= 0x00000040,
166	WB_NETCFG_RX_ERR 		= 0x00000080,
167	WB_NETCFG_FULLDUPLEX 	= 0x00000200,
168	WB_NETCFG_LOOPBACK 		= 0x00000C00,
169	WB_NETCFG_TX_ON 		= 0x00002000,
170	WB_NETCFG_TX_THRESH		= 0x001FC000,
171	WB_NETCFG_RX_EARLYTHRSH	= 0x1FE00000,
172	WB_NETCFG_100MBPS 		= 0x20000000,
173	WB_NETCFG_TX_EARLY_ON 	= 0x40000000,
174	WB_NETCFG_RX_EARLY_ON 	= 0x80000000,
175};
176/*
177 * The tx threshold can be adjusted in increments of 32 bytes.
178 */
179#define WB_TXTHRESH(x)		((x >> 5) << 14)
180#define WB_TXTHRESH_CHUNK	32
181#define WB_TXTHRESH_INIT	0 /*72*/
182
183/*
184 * Interrupt mask bits.
185 */
186enum interruptMaskBits {
187	WB_IMR_TX_OK 			= 0x00000001,
188	WB_IMR_TX_IDLE 			= 0x00000002,
189	WB_IMR_TX_NOBUF 		= 0x00000004,
190	WB_IMR_TX_UNDERRUN 		= 0x00000020,
191	WB_IMR_TX_EARLY 		= 0x00000400,
192	WB_IMR_RX_EARLY 		= 0x00000008,
193	WB_IMR_RX_ERR 			= 0x00000010,
194	WB_IMR_RX_OK 			= 0x00000040,
195	WB_IMR_RX_NOBUF			= 0x00000080,
196	WB_IMR_RX_IDLE			= 0x00000100,
197	WB_IMR_TIMER_EXPIRED	= 0x00000800,
198	WB_IMR_BUS_ERR 			= 0x00002000,
199	WB_IMR_ABNORMAL 		= 0x00008000,
200	WB_IMR_NORMAL 			= 0x00010000,
201};
202
203#define WB_INTRS	\
204	(WB_IMR_RX_OK|WB_IMR_RX_IDLE|WB_IMR_RX_ERR|WB_IMR_RX_NOBUF \
205	|WB_IMR_RX_EARLY|WB_IMR_TX_OK|WB_IMR_TX_EARLY|WB_IMR_TX_NOBUF \
206	|WB_IMR_TX_UNDERRUN|WB_IMR_TX_IDLE|WB_IMR_BUS_ERR \
207	|WB_IMR_ABNORMAL|WB_IMR_NORMAL|WB_IMR_TIMER_EXPIRED)
208
209/*
210 * Serial I/O (EEPROM/ROM) bits.
211 */
212enum EEpromBits {
213	WB_SIO_EE_CS 		= 0x00000001,			/* EEPROM chip select */
214	WB_SIO_EE_CLK 		= 0x00000002,			/* EEPROM clock */
215	WB_SIO_EE_DATAIN 	= 0x00000004,		/* EEPROM data output */
216	WB_SIO_EE_DATAOUT 	= 0x00000008,		/* EEPROM data input */
217	WB_SIO_ROMDATA4 	= 0x00000010,
218	WB_SIO_ROMDATA5 	= 0x00000020,
219	WB_SIO_ROMDATA6 	= 0x00000040,
220	WB_SIO_ROMDATA7		= 0x00000080,
221	WB_SIO_ROMCTL_WRITE	= 0x00000200,
222	WB_SIO_ROMCTL_READ 	= 0x00000400,
223	WB_SIO_EESEL 		= 0x00000800,
224	WB_SIO_MII_CLK 		= 0x00010000,		/* MDIO clock */
225	WB_SIO_MII_DATAIN 	= 0x00020000,		/* MDIO data out */
226	WB_SIO_MII_DIR 		= 0x00040000,		/* MDIO dir */
227	WB_SIO_MII_DATAOUT 	= 0x00080000,	/* MDIO data in */
228};
229
230enum EEpromCmd {
231	WB_EECMD_WRITE = 0x140,
232	WB_EECMD_READ = 0x180,
233	WB_EECMD_ERASE = 0x1c0
234};
235
236/*
237 * Winbond TX/RX descriptor structure.
238 */
239
240typedef struct wb_desc wb_desc;
241struct wb_desc {
242	uint32		wb_status;
243	uint32		wb_ctl;
244	uint32		wb_data;
245	uint32		wb_next;
246};
247
248enum rxStatusBits {
249	WB_RXSTAT_CRCERR  	= 0x00000002,
250	WB_RXSTAT_DRIBBLE 	= 0x00000004,
251 	WB_RXSTAT_MIIERR  	= 0x00000008,
252 	WB_RXSTAT_LATEEVENT = 0x00000040,
253 	WB_RXSTAT_GIANT 	= 0x00000080,
254 	WB_RXSTAT_LASTFRAG 	= 0x00000100,
255 	WB_RXSTAT_FIRSTFRAG = 0x00000200,
256 	WB_RXSTAT_MULTICAST = 0x00000400,
257 	WB_RXSTAT_RUNT 		= 0x00000800,
258 	WB_RXSTAT_RXTYPE 	= 0x00003000,
259 	WB_RXSTAT_RXERR 	= 0x00008000,
260 	WB_RXSTAT_RXLEN		= 0x3FFF0000,
261	WB_RXSTAT_RXCMP		= 0x40000000,
262	WB_RXSTAT_OWN		= 0x80000000
263};
264
265#define WB_RXBYTES(x)		((x & WB_RXSTAT_RXLEN) >> 16)
266#define WB_RXSTAT (WB_RXSTAT_FIRSTFRAG|WB_RXSTAT_LASTFRAG|WB_RXSTAT_OWN)
267
268enum rxControlBits {
269	WB_RXCTL_BUFLEN1	= 0x00000FFF,
270 	WB_RXCTL_BUFLEN2	= 0x00FFF000,
271 	WB_RXCTL_RLINK 		= 0x01000000,
272 	WB_RXCTL_RLAST		= 0x02000000
273};
274
275
276enum txStatusBits {
277	WB_TXSTAT_DEFER		= 0x00000001,
278 	WB_TXSTAT_UNDERRUN	= 0x00000002,
279 	WB_TXSTAT_COLLCNT	= 0x00000078,
280 	WB_TXSTAT_SQE		= 0x00000080,
281 	WB_TXSTAT_ABORT		= 0x00000100,
282 	WB_TXSTAT_LATECOLL	= 0x00000200,
283 	WB_TXSTAT_NOCARRIER	= 0x00000400,
284 	WB_TXSTAT_CARRLOST	= 0x00000800,
285 	WB_TXSTAT_TXERR		= 0x00001000,
286 	WB_TXSTAT_OWN		= 0x80000000
287};
288
289enum txControlBits {
290	WB_TXCTL_BUFLEN1 	= 0x000007FF,
291	WB_TXCTL_BUFLEN2 	= 0x003FF800,
292	WB_TXCTL_PAD		= 0x00800000,
293	WB_TXCTL_TLINK		= 0x01000000,
294	WB_TXCTL_TLAST		= 0x02000000,
295	WB_TXCTL_NOCRC		= 0x08000000,
296	WB_TXCTL_FIRSTFRAG	= 0x20000000,
297	WB_TXCTL_LASTFRAG	= 0x40000000,
298	WB_TXCTL_FINT		= 0x80000000
299};
300
301#define WB_MAXFRAGS			16
302#define WB_RX_LIST_CNT		64
303#define WB_TX_LIST_CNT		64
304#define WB_RX_CNT_MASK		(WB_RX_LIST_CNT - 1)
305#define WB_TX_CNT_MASK		(WB_TX_LIST_CNT - 1)
306#define WB_MIN_FRAMELEN		60
307#define WB_MAX_FRAMELEN		1536
308
309#define WB_UNSENT	0x1234
310#define WB_BUFBYTES 2048
311
312/* Ethernet defines */
313#define CRC_SIZE 4
314#define ETHER_TRANSMIT_TIMEOUT ((bigtime_t)5000000)  /* five seconds */
315#define WB_TIMEOUT		1000
316
317typedef struct wb_mii_frame wb_mii_frame;
318struct wb_mii_frame {
319	uint8		mii_stdelim;
320	uint8		mii_opcode;
321	uint8		mii_phyaddr;
322	uint8		mii_regaddr;
323	uint8		mii_turnaround;
324	uint16		mii_data;
325};
326
327/*
328 * MII constants
329 */
330#define WB_MII_STARTDELIM	0x01
331#define WB_MII_READOP		0x02
332#define WB_MII_WRITEOP		0x01
333#define WB_MII_TURNAROUND	0x02
334
335typedef struct wb_device wb_device;
336struct wb_device {
337	timer		timer;
338	int32		devId;
339	pci_info*	pciInfo;
340	uint16		irq;		/* IRQ line */
341	volatile uint32 reg_base;	/* hardware register base address */
342
343	// rx data
344	volatile wb_desc rxDescriptor[WB_RX_LIST_CNT];
345	volatile void* rxBuffer[WB_RX_LIST_CNT];
346	int32 rxLock;
347	sem_id rxSem;
348	spinlock rxSpinlock;
349	area_id rxArea;
350	int16 rxCurrent;
351	int16 rxInterruptIndex;
352	int16 rxFree;
353
354	//tx data
355	volatile wb_desc txDescriptor[WB_TX_LIST_CNT];
356	volatile char* txBuffer[WB_TX_LIST_CNT];
357	int32 txLock;
358	sem_id txSem;
359	spinlock txSpinlock;
360	area_id txArea;
361	int16 txCurrent;
362	int16 txInterruptIndex;
363	int16 txSent;
364
365	struct mii_phy* firstPHY;
366	struct mii_phy* currentPHY;
367	uint16 phy;
368	bool autoNegotiationComplete;
369	bool link;
370	bool full_duplex;
371	uint16 speed;
372	uint16 fixedMode;
373
374	volatile int32 blockFlag;
375	ether_address_t MAC_Address;
376
377	spinlock intLock;
378	const char* deviceName;
379	uint8 wb_type;
380	uint16 wb_txthresh;
381	int wb_cachesize;
382};
383
384
385/* MII Interface */
386struct mii_phy {
387	struct mii_phy *next;
388	uint16	id0, id1;
389	uint16	address;
390	uint8	types;
391};
392
393
394// taken from Axel's Sis900 driver
395enum MII_address {
396	// standard registers
397	MII_CONTROL		= 0x00,
398	MII_STATUS		= 0x01,
399	MII_PHY_ID0		= 0x02,
400	MII_PHY_ID1		= 0x03,
401	MII_AUTONEG_ADV				= 0x04,
402	MII_AUTONEG_LINK_PARTNER	= 0x05,
403	MII_AUTONEG_EXT				= 0x06
404};
405
406enum MII_control {
407	MII_CONTROL_RESET			= 0x8000,
408	MII_CONTROL_RESET_AUTONEG	= 0x0200,
409	MII_CONTROL_AUTO			= 0x1000,
410	MII_CONTROL_FULL_DUPLEX		= 0x0100,
411	MII_CONTROL_ISOLATE			= 0x0400
412};
413
414enum MII_commands {
415	MII_CMD_READ		= 0x6000,
416	MII_CMD_WRITE		= 0x5002,
417
418	MII_PHY_SHIFT		= 7,
419	MII_REG_SHIFT		= 2,
420};
421
422enum MII_status_bits {
423	MII_STATUS_EXT			= 0x0001,
424	MII_STATUS_JAB			= 0x0002,
425	MII_STATUS_LINK			= 0x0004,
426	MII_STATUS_CAN_AUTO		= 0x0008,
427	MII_STATUS_FAULT		= 0x0010,
428	MII_STATUS_AUTO_DONE	= 0x0020,
429	MII_STATUS_CAN_T		= 0x0800,
430	MII_STATUS_CAN_T_FDX	= 0x1000,
431	MII_STATUS_CAN_TX		= 0x2000,
432	MII_STATUS_CAN_TX_FDX	= 0x4000,
433	MII_STATUS_CAN_T4		= 0x8000
434};
435
436enum MII_auto_negotiation {
437	MII_NWAY_NODE_SEL	= 0x001f,
438	MII_NWAY_CSMA_CD	= 0x0001,
439	MII_NWAY_T			= 0x0020,
440	MII_NWAY_T_FDX		= 0x0040,
441	MII_NWAY_TX			= 0x0080,
442	MII_NWAY_TX_FDX		= 0x0100,
443	MII_NWAY_T4			= 0x0200,
444	MII_NWAY_PAUSE		= 0x0400,
445	MII_NWAY_RF			= 0x2000,
446	MII_NWAY_ACK		= 0x4000,
447	MII_NWAY_NP			= 0x8000
448};
449
450
451enum MII_link_status {
452	MII_LINK_FAIL			= 0x4000,
453	MII_LINK_100_MBIT		= 0x0080,
454	MII_LINK_FULL_DUPLEX	= 0x0040
455};
456
457enum link_modes {
458	LINK_HALF_DUPLEX	= 0x0100,
459	LINK_FULL_DUPLEX	= 0x0200,
460	LINK_DUPLEX_MASK	= 0xff00,
461
462	LINK_SPEED_HOME		= 1,
463	LINK_SPEED_10_MBIT	= 10,
464	LINK_SPEED_100_MBIT	= 100,
465	LINK_SPEED_DEFAULT	= LINK_SPEED_100_MBIT,
466	LINK_SPEED_MASK		= 0x00ff
467};
468
469/*
470 * Vendor and Card IDs
471 *
472 * Winbond
473 */
474#define	WB_VENDORID			0x1050
475#define	WB_DEVICEID_840F	0x0840
476
477/*
478 * Compex
479 */
480#define CP_VENDORID			0x11F6
481#define CP_DEVICEID_RL100	0x2011
482
483/*
484 * Utility Macros
485 */
486#define WB_SETBIT(reg, x) write32(reg, read32(reg) | x)
487#define WB_CLRBIT(reg, x) write32(reg, read32(reg) & ~x)
488
489// Prototypes
490extern int32		wb_interrupt(void* arg);
491
492extern status_t		wb_create_semaphores(wb_device* device);
493extern void		wb_delete_semaphores(wb_device* device);
494
495extern status_t		wb_create_rings(wb_device* device);
496extern void		wb_delete_rings(wb_device* device);
497
498extern void		wb_init(wb_device* device);
499extern void		wb_reset(wb_device* device);
500extern status_t		wb_stop(wb_device* device);
501
502extern status_t		wb_initPHYs(wb_device* device);
503
504extern void		wb_disable_interrupts(wb_device* device);
505extern void		wb_enable_interrupts(wb_device* device);
506
507extern void		wb_set_mode(wb_device* device, int mode);
508extern int32		wb_read_mode(wb_device* device);
509
510extern void		wb_set_rx_filter(wb_device* device);
511
512extern int32		wb_tick(timer* arg);
513extern void		wb_put_rx_descriptor(volatile wb_desc* desc);
514
515extern void		print_address(ether_address_t* addr);
516
517#endif //__WB840_H
518