Modules/VIARhineII - Fiddling
[tpg/acess2.git] / KernelLand / Modules / Network / VIARhineII / rhine2.c
1 /*
2  * Acess2 VIA Rhine II Driver (VT6102)
3  * - By John Hodge (thePowersGang)
4  */
5 #define DEBUG   0
6 #define VERSION ((0<<8)|10)
7 #include <acess.h>
8 #include <modules.h>
9 #include <fs_devfs.h>
10 #include <drv_pci.h>
11 #include <api_drv_network.h>
12 #include <semaphore.h>
13 #include "rhine2_hw.h"
14
15 // === CONSTANTS ===
16 #define VENDOR_ID       0x1106
17 #define DEVICE_ID       0x3065
18
19 // === TYPES ===
20 typedef struct sCard
21 {
22         Uint16  IOBase;
23         Uint8   IRQ;
24         
25          int    NumWaitingPackets;
26
27         Uint32  DescTablePAddr;
28         void    *DescTable;
29         
30         char    Name[2];
31         tVFS_Node       Node;
32         Uint8   MacAddr[6];
33 }       tCard;
34
35 // === PROTOTYPES ===
36  int    Rhine2_Install(char **Options);
37 char    *Rhine2_ReadDir(tVFS_Node *Node, int Pos);
38 tVFS_Node       *Rhine2_FindDir(tVFS_Node *Node, const char *Filename);
39  int    Rhine2_RootIOCtl(tVFS_Node *Node, int ID, void *Arg);
40 Uint64  Rhine2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
41 Uint64  Rhine2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
42  int    Rhine2_IOCtl(tVFS_Node *Node, int ID, void *Arg);
43 void    Rhine2_IRQHandler(int Num);
44
45 // === GLOBALS ===
46 MODULE_DEFINE(0, VERSION, VIARhineII, Rhine2_Install, NULL, NULL);
47 tVFS_NodeType   gRhine2_DirType = {
48         .ReadDir = Rhine2_ReadDir,
49         .FindDir = Rhine2_FindDir,
50         .IOCtl = Rhine2_RootIOCtl
51         };
52 tDevFS_Driver   gRhine2_DriverInfo = {
53         NULL, "Rhine2",
54         {
55         .NumACLs = 1,
56         .ACLs = &gVFS_ACL_EveryoneRX,
57         .Flags = VFS_FFLAG_DIRECTORY,
58         .Type = &gRhine2_DirType
59         }
60 };
61  int    giRhine2_CardCount;
62 tCard   *gaRhine2_Cards;
63
64 // === CODE ===
65 /**
66  * \brief Initialises the driver
67  */
68 int Rhine2_Install(char **Options)
69 {
70          int    id = -1;
71          int    i = 0;
72 //      Uint16  base;
73         tCard   *card;
74         
75         giRhine2_CardCount = PCI_CountDevices(VENDOR_ID, DEVICE_ID);
76         Log_Debug("Rhine2", "%i cards", giRhine2_CardCount);
77         
78         if( giRhine2_CardCount == 0 )   return MODULE_ERR_NOTNEEDED;
79         
80         gaRhine2_Cards = calloc( giRhine2_CardCount, sizeof(tCard) );
81         
82         while( (id = PCI_GetDevice(VENDOR_ID, DEVICE_ID, i)) != -1 )
83         {
84                 card = &gaRhine2_Cards[i];
85                 
86                 LOG("BAR0 = 0x%08x", PCI_GetBAR(id, 0));
87                 LOG("BAR1 = 0x%08x", PCI_GetBAR(id, 1));
88                 LOG("BAR2 = 0x%08x", PCI_GetBAR(id, 2));
89                 LOG("BAR3 = 0x%08x", PCI_GetBAR(id, 3));
90                 LOG("BAR4 = 0x%08x", PCI_GetBAR(id, 4));
91                 LOG("BAR5 = 0x%08x", PCI_GetBAR(id, 5));
92                 
93 //              card->IOBase = base;
94 //              card->IRQ = PCI_GetIRQ( id );
95                 
96                 // Install IRQ Handler
97 //              IRQ_AddHandler(card->IRQ, Rhine2_IRQHandler);
98                 
99                 
100                 
101 //              Log_Log("PCnet3", "Card %i 0x%04x, IRQ %i %02x:%02x:%02x:%02x:%02x:%02x",
102 //                      i, card->IOBase, card->IRQ,
103 //                      card->MacAddr[0], card->MacAddr[1], card->MacAddr[2],
104 //                      card->MacAddr[3], card->MacAddr[4], card->MacAddr[5]
105 //                      );
106                 
107                 i ++;
108         }
109         
110         gRhine2_DriverInfo.RootNode.Size = giRhine2_CardCount;
111         DevFS_AddDevice( &gRhine2_DriverInfo );
112         
113         return MODULE_ERR_OK;
114 }
115
116 // --- Root Functions ---
117 char *Rhine2_ReadDir(tVFS_Node *Node, int Pos)
118 {
119         if( Pos < 0 || Pos >= giRhine2_CardCount )      return NULL;
120         
121         return strdup( gaRhine2_Cards[Pos].Name );
122 }
123
124 tVFS_Node *Rhine2_FindDir(tVFS_Node *Node, const char *Filename)
125 {
126         //TODO: It might be an idea to supprt >10 cards
127         if(Filename[0] == '\0' || Filename[1] != '\0')  return NULL;
128         if(Filename[0] < '0' || Filename[0] > '9')      return NULL;
129         return &gaRhine2_Cards[ Filename[0]-'0' ].Node;
130 }
131
132 const char *csaRhine2_RootIOCtls[] = {DRV_IOCTLNAMES, NULL};
133 int Rhine2_RootIOCtl(tVFS_Node *Node, int ID, void *Data)
134 {
135         ENTER("pNode iID pData", Node, ID, Data);
136         switch(ID)
137         {
138         BASE_IOCTLS(DRV_TYPE_NETWORK, "Rhine2", VERSION, csaRhine2_RootIOCtls);
139         }
140         LEAVE('i', 0);
141         return 0;
142 }
143
144 // --- File Functions ---
145 Uint64 Rhine2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
146 {
147         #if 0
148         tCard   *card = Node->ImplPtr;
149         Uint16  read_ofs, pkt_length;
150          int    new_read_ofs;
151
152         ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
153
154 retry:
155         if( Semaphore_Wait( &card->ReadSemaphore, 1 ) != 1 )
156         {
157                 LEAVE_RET('i', 0);
158         }
159         
160         Mutex_Acquire( &card->ReadMutex );
161         
162         read_ofs = inw( card->IOBase + CAPR );
163         LOG("raw read_ofs = %i", read_ofs);
164         read_ofs = (read_ofs + 0x10) & 0xFFFF;
165         LOG("read_ofs = %i", read_ofs);
166         
167         pkt_length = *(Uint16*)&card->ReceiveBuffer[read_ofs+2];
168         
169         // Calculate new read offset
170         new_read_ofs = read_ofs + pkt_length + 4;
171         new_read_ofs = (new_read_ofs + 3) & ~3; // Align
172         if(new_read_ofs > card->ReceiveBufferLength) {
173                 LOG("wrapping read_ofs");
174                 new_read_ofs -= card->ReceiveBufferLength;
175         }
176         new_read_ofs -= 0x10;   // I dunno
177         LOG("new_read_ofs = %i", new_read_ofs);
178         
179         // Check for errors
180         if( *(Uint16*)&card->ReceiveBuffer[read_ofs] & 0x1E ) {
181                 // Update CAPR
182                 outw(card->IOBase + CAPR, new_read_ofs);
183                 Mutex_Release( &card->ReadMutex );
184                 goto retry;     // I feel evil
185         }
186         
187         // Get packet
188         if( Length > pkt_length )       Length = pkt_length;
189         memcpy(Buffer, &card->ReceiveBuffer[read_ofs+4], Length);
190         
191         // Update CAPR
192         outw(card->IOBase + CAPR, new_read_ofs);
193         
194         Mutex_Release( &card->ReadMutex );
195         
196         LEAVE('i', Length);
197         #endif
198         
199         return Length;
200 }
201
202 Uint64 Rhine2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
203 {
204         #if 0
205          int    td;
206         Uint32  status;
207         tCard   *card = Node->ImplPtr;
208         
209         if( Length > 1500 )     return 0;       // MTU exceeded
210         
211         ENTER("pNode XLength pBuffer", Node, Length, Buffer);
212         
213         // TODO: Implement a semaphore for avaliable transmit buffers
214
215         // Find an avaliable descriptor
216         Mutex_Acquire(&card->CurTXProtector);
217         td = card->CurTXDescriptor;
218         card->CurTXDescriptor ++;
219         card->CurTXDescriptor %= 4;
220         Mutex_Release(&card->CurTXProtector);
221         // - Lock it
222         Mutex_Acquire( &card->TransmitInUse[td] );
223         
224         LOG("td = %i", td);
225         
226         // Transmit using descriptor `td`
227         LOG("card->PhysTransmitBuffers[td] = %P", card->PhysTransmitBuffers[td]);
228         outd(card->IOBase + TSAD0 + td*4, card->PhysTransmitBuffers[td]);
229         LOG("card->TransmitBuffers[td] = %p", card->TransmitBuffers[td]);
230         // Copy to buffer
231         memcpy(card->TransmitBuffers[td], Buffer, Length);
232         // Start
233         status = 0;
234         status |= Length & 0x1FFF;      // 0-12: Length
235         status |= 0 << 13;      // 13: OWN bit
236         status |= (0 & 0x3F) << 16;     // 16-21: Early TX threshold (zero atm, TODO: check)
237         LOG("status = 0x%08x", status);
238         outd(card->IOBase + TSD0 + td*4, status);
239         
240         LEAVE('i', (int)Length);
241         #endif
242         
243         return Length;
244 }
245
246 const char *csaRhine2_NodeIOCtls[] = {DRV_IOCTLNAMES, NULL};
247 int Rhine2_IOCtl(tVFS_Node *Node, int ID, void *Data)
248 {
249         tCard   *card = Node->ImplPtr;
250         ENTER("pNode iID pData", Node, ID, Data);
251         switch(ID)
252         {
253         BASE_IOCTLS(DRV_TYPE_NETWORK, "Rhine2", VERSION, csaRhine2_NodeIOCtls);
254         case NET_IOCTL_GETMAC:
255                 if( !CheckMem(Data, 6) ) {
256                         LEAVE('i', -1);
257                         return -1;
258                 }
259                 memcpy( Data, card->MacAddr, 6 );
260                 LEAVE('i', 1);
261                 return 1;
262         }
263         LEAVE('i', 0);
264         return 0;
265 }
266
267 void Rhine2_IRQHandler(int Num)
268 {
269         #if 0
270          int    i, j;
271         tCard   *card;
272         Uint16  status;
273
274         LOG("Num = %i", Num);
275         
276         for( i = 0; i < giRhine2_CardCount; i ++ )
277         {
278                 card = &gaRhine2_Cards[i];
279                 if( Num != card->IRQ )  break;
280                 
281                 status = inw(card->IOBase + ISR);
282                 LOG("status = 0x%02x", status);
283                 
284                 // Transmit OK, a transmit descriptor is now free
285                 if( status & FLAG_ISR_TOK )
286                 {
287                         for( j = 0; j < 4; j ++ )
288                         {
289                                 if( ind(card->IOBase + TSD0 + j*4) & 0x8000 ) { // TSD TOK
290                                         Mutex_Release( &card->TransmitInUse[j] );
291                                         // TODO: Update semaphore once implemented
292                                 }
293                         }
294                         outw(card->IOBase + ISR, FLAG_ISR_TOK);
295                 }
296                 
297                 // Recieve OK, inform read
298                 if( status & FLAG_ISR_ROK )
299                 {
300                          int    read_ofs, end_ofs;
301                          int    packet_count = 0;
302                          int    len;
303                         
304                         // Scan recieve buffer for packets
305                         end_ofs = inw(card->IOBase + CBA);
306                         read_ofs = card->SeenOfs;
307                         LOG("read_ofs = %i, end_ofs = %i", read_ofs, end_ofs);
308                         if( read_ofs > end_ofs )
309                         {
310                                 while( read_ofs < card->ReceiveBufferLength )
311                                 {
312                                         packet_count ++;
313                                         len = *(Uint16*)&card->ReceiveBuffer[read_ofs+2];
314                                         LOG("%i 0x%x Pkt Hdr: 0x%04x, len: 0x%04x",
315                                                 packet_count, read_ofs,
316                                                 *(Uint16*)&card->ReceiveBuffer[read_ofs],
317                                                 len
318                                                 );
319                                         if(len > 2000) {
320                                                 Log_Warning("PCnet3", "IRQ: Packet in buffer exceeds sanity (%i>2000)", len);
321                                         }
322                                         read_ofs += len + 4;
323                                         read_ofs = (read_ofs + 3) & ~3; // Align
324                                 }
325                                 read_ofs -= card->ReceiveBufferLength;
326                                 LOG("wrapped read_ofs");
327                         }
328                         while( read_ofs < end_ofs )
329                         {
330                                 packet_count ++;
331                                 LOG("%i 0x%x Pkt Hdr: 0x%04x, len: 0x%04x",
332                                         packet_count, read_ofs,
333                                         *(Uint16*)&card->ReceiveBuffer[read_ofs],
334                                         *(Uint16*)&card->ReceiveBuffer[read_ofs+2]
335                                         );
336                                 read_ofs += *(Uint16*)&card->ReceiveBuffer[read_ofs+2] + 4;
337                                 read_ofs = (read_ofs + 3) & ~3; // Align
338                         }
339                         if( read_ofs != end_ofs ) {
340                                 Log_Warning("PCnet3", "IRQ: read_ofs (%i) != end_ofs(%i)", read_ofs, end_ofs);
341                                 read_ofs = end_ofs;
342                         }
343                         card->SeenOfs = read_ofs;
344                         
345                         LOG("packet_count = %i, read_ofs = 0x%x", packet_count, read_ofs);
346                         
347                         if( packet_count )
348                         {
349                                 if( Semaphore_Signal( &card->ReadSemaphore, packet_count ) != packet_count ) {
350                                         // Oops?
351                                 }
352                                 VFS_MarkAvaliable( &card->Node, 1 );
353                         }
354                         
355                         outw(card->IOBase + ISR, FLAG_ISR_ROK);
356                 }
357         }
358         #endif
359 }

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