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

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