Cleanup and Bugfixing
[tpg/acess2.git] / Modules / NE2000 / ne2000.c
1 /* Acess2
2  * NE2000 Driver
3  * 
4  * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
5  */
6 #define DEBUG   1
7 #define VERSION ((0<<8)|50)
8 #include <common.h>
9 #include <modules.h>
10 #include <fs_devfs.h>
11 #include <drv_pci.h>
12 #include <tpl_drv_network.h>
13
14 // === CONSTANTS ===
15 #define MEM_START       0x40
16 #define MEM_END         0xC0
17 #define RX_FIRST        (MEM_START)
18 #define RX_LAST         (MEM_START+RX_BUF_SIZE-1)
19 #define RX_BUF_SIZE     0x40
20 #define TX_FIRST        (MEM_START+RX_BUF_SIZE)
21 #define TX_LAST         (MEM_END)
22 #define TX_BUF_SIZE     0x40
23
24 static const struct {
25         Uint16  Vendor;
26         Uint16  Device;
27 } csaCOMPAT_DEVICES[] = {
28         {0x10EC, 0x8029},       // Realtek 8029
29         {0x10EC, 0x8129}        // Realtek 8129
30 };
31 #define NUM_COMPAT_DEVICES      (sizeof(csaCOMPAT_DEVICES)/sizeof(csaCOMPAT_DEVICES[0]))
32
33 enum eNe2k_Page0Read {
34         CMD = 0,        //!< the master command register
35         CLDA0,          //!< Current Local DMA Address 0
36         CLDA1,          //!< Current Local DMA Address 1
37         BNRY,           //!< Boundary Pointer (for ringbuffer)
38         TSR,            //!< Transmit Status Register
39         NCR,            //!< collisions counter
40         FIFO,           //!< (for what purpose ??)
41         ISR,            //!< Interrupt Status Register
42         CRDA0,          //!< Current Remote DMA Address 0
43         CRDA1,          //!< Current Remote DMA Address 1
44         RSR = 0xC       //!< Receive Status Register
45 };
46
47 enum eNe2k_Page0Write {
48         PSTART = 1,     //!< page start (init only)
49         PSTOP,          //!< page stop  (init only)
50         TPSR = 4,       //!< transmit page start address
51         TBCR0,          //!< transmit byte count (low)
52         TBCR1,          //!< transmit byte count (high)
53         RSAR0 = 8,      //!< remote start address (lo)
54         RSAR1,  //!< remote start address (hi)
55         RBCR0,  //!< remote byte count (lo)
56         RBCR1,  //!< remote byte count (hi)
57         RCR,    //!< receive config register
58         TCR,    //!< transmit config register
59         DCR,    //!< data config register    (init)
60         IMR             //!< interrupt mask register (init)
61 };
62
63 // === TYPES ===
64 typedef struct sNe2k_Card {
65         Uint16  IOBase; //!< IO Port Address from PCI
66         Uint8   IRQ;    //!< IRQ Assigned from PCI
67         
68          int    NextMemPage;    //!< Next Card Memory page to use
69         
70         Uint8   Buffer[RX_BUF_SIZE];
71         
72         char    Name[2];        // "0"
73         tVFS_Node       Node;
74         Uint8   MacAddr[6];
75 } tCard;
76
77 // === PROTOTYPES ===
78  int    Ne2k_Install(char **Arguments);
79 char    *Ne2k_ReadDir(tVFS_Node *Node, int Pos);
80 tVFS_Node       *Ne2k_FindDir(tVFS_Node *Node, char *Name);
81  int    Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data);
82 Uint64  Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
83 Uint8   Ne2k_int_GetWritePage(tCard *Card, Uint16 Length);
84 void    Ne2k_IRQHandler(int IntNum);
85
86 // === GLOBALS ===
87 MODULE_DEFINE(0, VERSION, Ne2k, Ne2k_Install, NULL, NULL);
88 tDevFS_Driver   gNe2k_DriverInfo = {
89         NULL, "ne2k",
90         {
91         .NumACLs = 1,
92         .ACLs = &gVFS_ACL_EveryoneRX,
93         .Flags = VFS_FFLAG_DIRECTORY,
94         .ReadDir = Ne2k_ReadDir,
95         .FindDir = Ne2k_FindDir,
96         .IOCtl = Ne2k_IOCtl
97         }
98 };
99 Uint16  gNe2k_BaseAddress;
100  int    giNe2k_CardCount = 0;
101 tCard   *gpNe2k_Cards = NULL;
102
103 // === CODE ===
104 /**
105  * \fn int Ne2k_Install(char **Options)
106  * \brief Installs the NE2000 Driver
107  */
108 int Ne2k_Install(char **Options)
109 {
110          int    i, j, k;
111          int    count, id, base;
112         
113         // --- Scan PCI Bus ---
114         // Count Cards
115         giNe2k_CardCount = 0;
116         for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
117         {
118                 giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 );
119         }
120         
121         // Enumerate Cards
122         k = 0;
123         gpNe2k_Cards = malloc( giNe2k_CardCount * sizeof(tCard) );
124         memsetd(gpNe2k_Cards, 0, giNe2k_CardCount * sizeof(tCard) / 4);
125         for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
126         {
127                 count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 );
128                 for( j = 0; j < count; j ++,k ++ )
129                 {
130                         id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0, j );
131                         // Create Structure
132                         base = PCI_AssignPort( id, 0, 0x20 );
133                         gpNe2k_Cards[ k ].IOBase = base;
134                         gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id );
135                         gpNe2k_Cards[ k ].NextMemPage = 64;
136                         
137                         // Install IRQ Handler
138                         IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler);
139                         
140                         // Reset Card
141                         outb( base + 0x1F, inb(base + 0x1F) );
142                         while( (inb( base+ISR ) & 0x80) == 0 );
143                         outb( base + ISR, 0x80 );
144                         
145                         // Initialise Card
146                         outb( base + CMD, 0x21 );       // No DMA and Stop
147                         outb( base + DCR, 0x49 );       // Set WORD mode
148                         outb( base + IMR, 0x00 );
149                         outb( base + ISR, 0xFF );
150                         outb( base + RCR, 0x20 );       // Reciever to Monitor
151                         outb( base + TCR, 0x02 );       // Transmitter OFF (TCR.LB = 1, Internal Loopback)
152                         outb( base + RBCR0, 6*4 );      // Remote Byte Count
153                         outb( base + RBCR1, 0 );
154                         outb( base + RSAR0, 0 );        // Clear Source Address
155                         outb( base + RSAR1, 0 );
156                         outb( base + CMD, 0x0A );       // Remote Read, Start
157                         
158                         // Read MAC Address
159                         gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10);  inb(base+0x10);
160                         gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10);  inb(base+0x10);
161                         gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10);  inb(base+0x10);
162                         gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10);  inb(base+0x10);
163                         gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10);  inb(base+0x10);
164                         gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10);  inb(base+0x10);
165                         
166                         outb( base+PSTART, RX_FIRST);   // Set Receive Start
167                         outb( base+BNRY, RX_LAST-1);    // Set Boundary Page
168                         outb( base+PSTOP, RX_LAST);     // Set Stop Page
169                         outb( base+ISR, 0xFF ); // Clear all ints
170                         outb( base+CMD, 0x22 ); // No DMA, Start
171                         outb( base+IMR, 0x3F ); // Set Interupt Mask
172                         outb( base+RCR, 0x0F ); // Set WRAP and allow all packet matches
173                         outb( base+TCR, 0x00 ); // Set Normal Transmitter mode
174                         outb( base+TPSR, 0x40); // Set Transmit Start
175                         // Set MAC Address
176                         /*
177                         Ne2k_WriteReg(base, MAC0, gpNe2k_Cards[ k ].MacAddr[0]);
178                         Ne2k_WriteReg(base, MAC1, gpNe2k_Cards[ k ].MacAddr[1]);
179                         Ne2k_WriteReg(base, MAC2, gpNe2k_Cards[ k ].MacAddr[2]);
180                         Ne2k_WriteReg(base, MAC3, gpNe2k_Cards[ k ].MacAddr[3]);
181                         Ne2k_WriteReg(base, MAC4, gpNe2k_Cards[ k ].MacAddr[4]);
182                         Ne2k_WriteReg(base, MAC5, gpNe2k_Cards[ k ].MacAddr[5]);
183                         */
184                         
185                         Log("[NE2K]: Card #%i: IRQ=%i, IOBase=0x%x",
186                                 k, gpNe2k_Cards[ k ].IRQ, gpNe2k_Cards[ k ].IOBase);
187                         Log("MAC Address %x:%x:%x:%x:%x:%x",
188                                 gpNe2k_Cards[ k ].MacAddr[0], gpNe2k_Cards[ k ].MacAddr[1],
189                                 gpNe2k_Cards[ k ].MacAddr[2], gpNe2k_Cards[ k ].MacAddr[3],
190                                 gpNe2k_Cards[ k ].MacAddr[4], gpNe2k_Cards[ k ].MacAddr[5]
191                                 );
192                         
193                         // Set VFS Node
194                         gpNe2k_Cards[ k ].Name[0] = '0'+k;
195                         gpNe2k_Cards[ k ].Name[1] = '\0';
196                         gpNe2k_Cards[ k ].Node.ImplPtr = &gpNe2k_Cards[ k ];
197                         gpNe2k_Cards[ k ].Node.NumACLs = 0;     // Root Only
198                         gpNe2k_Cards[ k ].Node.CTime = now();
199                         gpNe2k_Cards[ k ].Node.Write = Ne2k_Write;
200                         gpNe2k_Cards[ k ].Node.IOCtl = Ne2k_IOCtl;
201                 }
202         }
203         
204         gNe2k_DriverInfo.RootNode.Size = giNe2k_CardCount;
205         DevFS_AddDevice( &gNe2k_DriverInfo );
206         return 0;
207 }
208
209 /**
210  * \fn char *Ne2k_ReadDir(tVFS_Node *Node, int Pos)
211  */
212 char *Ne2k_ReadDir(tVFS_Node *Node, int Pos)
213 {
214         char    ret[2];
215         if(Pos < 0 || Pos >= giNe2k_CardCount)  return NULL;
216         ret[0] = '0'+Pos;
217         ret[1] = '\0';
218         return strdup(ret);
219 }
220
221 /**
222  * \fn tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name)
223  */
224 tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, char *Name)
225 {
226         if(Name[0] == '\0' || Name[1] != '\0')  return NULL;
227         
228         return &gpNe2k_Cards[ Name[0]-'0' ].Node;
229 }
230
231 static const char *casIOCtls[] = { DRV_IOCTLNAMES, DRV_NETWORK_IOCTLNAMES, NULL };
232 /**
233  * \fn int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data)
234  * \brief IOCtl calls for a network device
235  */
236 int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data)
237 {
238          int    tmp;
239         ENTER("pNode iID pData", Node, ID, Data);
240         switch( ID )
241         {
242         case DRV_IOCTL_TYPE:
243                 LEAVE('i', DRV_TYPE_NETWORK);
244                 return DRV_TYPE_NETWORK;
245         
246         case DRV_IOCTL_IDENT:
247                 if(!CheckMem(Data, 4)) {
248                         LEAVE('i', -1);
249                         return -1;
250                 }
251                 memcpy(Data, "NE2K", 4);
252                 LEAVE('i', 1);
253                 return 1;
254         
255         case DRV_IOCTL_VERSION:
256                 LEAVE('x', VERSION);
257                 return VERSION;
258         
259         case DRV_IOCTL_LOOKUP:
260                 if( !CheckString(Data) ) {
261                         LEAVE('i', -1);
262                         return -1;
263                 }
264                 tmp = LookupString( (char**)casIOCtls, Data );
265                 LEAVE('i', tmp);
266                 return tmp;
267         }
268         
269         // If this is the root, return
270         if( Node == &gNe2k_DriverInfo.RootNode ) {
271                 LEAVE('i', 0);
272                 return 0;
273         }
274         
275         // Device specific settings
276         switch( ID )
277         {
278         case NET_IOCTL_GETMAC:
279                 if( !CheckMem(Data, 6) ) {
280                         LEAVE('i', -1);
281                         return -1;
282                 }
283                 memcpy( Data, ((tCard*)Node->ImplPtr)->MacAddr, 6 );
284                 LEAVE('i', 1);
285                 return 1;
286         }
287         LEAVE('i', 0);
288         return 0;
289 }
290
291 /**
292  * \fn Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
293  * \brief Send a packet from the network card
294  */
295 Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
296 {
297         tCard   *Card = (tCard*)Node->ImplPtr;
298         Uint16  *buf = Buffer;
299          int    rem = Length;
300         
301         ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
302         
303         // Sanity Check Length
304         if(Length > TX_BUF_SIZE) {
305                 LEAVE('i', 0);
306                 return 0;
307         }
308         
309         // Make sure that the card is in page 0
310         outb(Card->IOBase + CMD, 0|0x22);       // Page 0, Start, NoDMA
311         
312         // Clear Remote DMA Flag
313         outb(Card->IOBase + ISR, 0x40); // Bit 6
314         
315         // Send Size - Remote Byte Count Register
316         outb(Card->IOBase + TBCR0, Length & 0xFF);
317         outb(Card->IOBase + TBCR1, Length >> 8);
318         
319         // Send Size - Remote Byte Count Register
320         outb(Card->IOBase + RBCR0, Length & 0xFF);
321         outb(Card->IOBase + RBCR1, Length >> 8);
322         
323         // Set up transfer
324         outb(Card->IOBase + RSAR0, 0x00);       // Page Offset
325         outb(Card->IOBase + RSAR1, Ne2k_int_GetWritePage(Card, Length));        // Page Offset
326         // Start
327         //outb(Card->IOBase + CMD, 0|0x18|0x4|0x2);     // Page 0, Transmit Packet, TXP, Start
328         outb(Card->IOBase + CMD, 0|0x10|0x2);   // Page 0, Remote Write, Start
329         
330         // Send Data
331         for(rem = Length; rem; rem -= 2)
332                 outw(Card->IOBase + 0x10, *buf++);
333         
334         while( inb(Card->IOBase + ISR) == 0)    // Wait for Remote DMA Complete
335                 ;       //Proc_Yield();
336         
337         outb( Card->IOBase + ISR, 0x40 );       // ACK Interrupt
338         
339         // Send Packet
340         outb(Card->IOBase + CMD, 0|0x10|0x4|0x2);
341         
342         // Complete DMA
343         //outb(Card->IOBase + CMD, 0|0x20);
344         
345         LEAVE('i', Length);
346         return Length;
347 }
348
349 /**
350  * \fn Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length)
351  */
352 Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length)
353 {
354         Uint8   ret = Card->NextMemPage;
355         
356         Card->NextMemPage += (Length + 0xFF) >> 8;
357         if(Card->NextMemPage >= TX_LAST) {
358                 Card->NextMemPage -= TX_BUF_SIZE;
359         }
360         
361         return ret;
362 }
363
364 /**
365  * \fn void Ne2k_IRQHandler(int IntNum)
366  */
367 void Ne2k_IRQHandler(int IntNum)
368 {
369          int    i;
370         for( i = 0; i < giNe2k_CardCount; i++ )
371         {
372                 if(gpNe2k_Cards[i].IRQ == IntNum) {
373                         LOG("Clearing interrupts on card %i (0x%x)\n", i, inb( gpNe2k_Cards[i].IOBase + ISR ));
374                         outb( gpNe2k_Cards[i].IOBase + ISR, 0xFF );     // Reset All
375                         return ;
376                 }
377         }
378         Warning("[NE2K ] Recieved Unknown IRQ %i", IntNum);
379 }

UCC git Repository :: git.ucc.asn.au