1/*
2 *	Davicom DM9601 USB 1.1 Ethernet Driver.
3 *	Copyright (c) 2008, 2011 Siarzhuk Zharski <imker@gmx.li>
4 *	Copyright (c) 2009 Adrien Destugues <pulkomandy@gmail.com>
5 *	Distributed under the terms of the MIT license.
6 *
7 *	Heavily based on code of the
8 *	Driver for USB Ethernet Control Model devices
9 *	Copyright (C) 2008 Michael Lotz <mmlr@mlotz.ch>
10 *	Distributed under the terms of the MIT license.
11 */
12#ifndef _USB_DAVICOM_DEVICE_H_
13#define _USB_DAVICOM_DEVICE_H_
14
15
16#include <ether_driver.h>
17#include <util/Vector.h>
18
19#include "Driver.h"
20
21
22struct DM9601NotifyData {
23	// Network Status Register
24	uint RXRDY	:1;
25	uint RXOV	:1;
26	uint TX1END	:1;
27	uint TX2END	:1;
28	uint TXFULL	:1;
29	uint WAKEST	:1;
30	uint LINKST	:1;
31	uint SPEED	:1;
32
33	struct {
34		uint		:2;
35		uint EC		:1;
36		uint COL	:1;
37		uint LC		:1;
38		uint NC		:1;
39		uint LCR	:1;
40		uint		:1;
41	} __attribute__((__packed__)) TSR1, TSR2;
42
43	// RX Status Register
44	uint FOE	:1;
45	uint CE		:1;
46	uint AE		:1;
47	uint PLE	:1;
48	uint RWTO	:1;
49	uint LCS	:1;
50	uint MF		:1;
51	uint RT		:1;
52
53	// RX Overflows Count
54	uint RXFU	:1;
55	uint ROC	:7;
56
57	uint RXC	:8;
58	uint TXC	:8;
59	uint GPR	:8;
60
61	DM9601NotifyData() { memset(this, 0, sizeof(DM9601NotifyData)); }
62} __attribute__((__packed__));
63
64
65struct DeviceInfo {
66	uint16	fIds[2];
67
68	const char* fName;
69	inline uint16		VendorId()	{ return fIds[0]; }
70	inline uint16		ProductId()	{ return fIds[1]; }
71	inline uint32		Key()		{ return fIds[0] << 16 | fIds[1]; }
72};
73
74class DavicomDevice {
75
76		struct _Statistics {
77			// NSR
78			int txFull;
79			int rxOverflow;
80			int rxOvCount;
81			// RSR
82			int	runtFrames;
83			int lateRXCollisions;
84			int rwTOs;
85			int physLayerErros;
86			int alignmentErros;
87			int crcErrors;
88			int overErrors;
89			// TSR 1/2
90			int lateTXCollisions;
91			int lostOfCarrier;
92			int noCarrier;
93			int txCollisions;
94			int excCollisions;
95
96			int notifyCount;
97			int readCount;
98			int writeCount;
99			_Statistics() { memset(this, 0, sizeof(_Statistics)); }
100		};
101
102public:
103							DavicomDevice(usb_device device, DeviceInfo& Info);
104							~DavicomDevice();
105
106		status_t			InitCheck() { return fStatus; };
107
108		status_t			Open(uint32 flags);
109		bool				IsOpen() { return fOpen; };
110
111		status_t			Close();
112		status_t			Free();
113
114		status_t			Read(uint8 *buffer, size_t *numBytes);
115		status_t			Write(const uint8 *buffer, size_t *numBytes);
116		status_t			Control(uint32 op, void *buffer, size_t length);
117
118		void				Removed();
119		bool				IsRemoved() { return fRemoved; };
120
121		status_t			CompareAndReattach(usb_device device);
122		status_t			SetupDevice(bool deviceReplugged);
123
124private:
125static	void				_ReadCallback(void *cookie, int32 status,
126								void *data, size_t actualLength);
127static	void				_WriteCallback(void *cookie, int32 status,
128								void *data, size_t actualLength);
129static	void				_NotifyCallback(void *cookie, int32 status,
130								void *data, size_t actualLength);
131
132		status_t			_SetupEndpoints();
133
134		status_t			_StartDevice();
135		status_t			_StopDevice();
136		status_t			_OnNotify(uint32 actualLength);
137		status_t			_GetLinkState(ether_link_state *state);
138		status_t			_SetPromiscuousMode(bool bOn);
139		uint32				_EthernetCRC32(const uint8* buffer, size_t length);
140		status_t			_ModifyMulticastTable(bool join,
141								ether_address_t *group);
142		status_t			_ReadMACAddress(ether_address_t *address);
143
144		status_t			_ReadRegister(uint8 reg, size_t size, uint8* buffer);
145		status_t			_WriteRegister(uint8 reg, size_t size, uint8* buffer);
146		status_t			_Write1Register(uint8 reg, uint8 buffer);
147		status_t			_ReadMII(uint8 reg, uint16* data);
148		status_t			_WriteMII(uint8 reg, uint16 data);
149		status_t			_InitMII();
150		status_t			_EnableInterrupts(bool enable);
151
152
153		// device info
154		usb_device			fDevice;
155		DeviceInfo			fDeviceInfo;
156		ether_address_t		fMACAddress;
157
158		// state tracking
159		status_t			fStatus;
160		bool				fOpen;
161		bool				fRemoved;
162		bool				fHasConnection;
163		bool				fTXBufferFull;
164		bool				fNonBlocking;
165		int32				fInsideNotify;
166
167		// pipes for notifications, data io and tx packet size
168		usb_pipe			fNotifyEndpoint;
169		usb_pipe			fReadEndpoint;
170		usb_pipe			fWriteEndpoint;
171		uint16				fMaxTXPacketSize;
172
173		// data stores for async usb transfers
174		uint32				fActualLengthRead;
175		uint32				fActualLengthWrite;
176		int32				fStatusRead;
177		int32				fStatusWrite;
178		sem_id				fNotifyReadSem;
179		sem_id				fNotifyWriteSem;
180		sem_id				fLinkStateChangeSem;
181
182		DM9601NotifyData*	fNotifyData;
183		_Statistics			fStats;
184		Vector<uint32>		fMulticastHashes;
185};
186
187#endif // _USB_DAVICOM_DEVICE_H_
188
189