2 * Acess2 RTL8139 Driver
3 * - By John Hodge (thePowersGang)
6 #define VERSION ((0<<8)|50)
11 #include <tpl_drv_network.h>
12 #include <semaphore.h>
21 // Multicast Registers
22 MAR0 = 0x08, MAR1, MAR2, MAR3,
23 MAR4, MAR5, MAR6, MAR7,
25 // Transmit status of descriptors 0 - 3
26 TSD0 = 0x10, TSD1 = 0x14,
27 TSD2 = 0x18, TSD3 = 0x1C,
28 // Transmit start addresses
29 TSAD0 = 0x20, TSAD1 = 0x24,
30 TSAD2 = 0x28, TSAD3 = 0x2C,
32 RBSTART = 0x30, //!< Recieve Buffer Start (DWord)
33 // Early Recieve Byte Count
34 ERBCR = 0x34, // 16-bits
35 // Early RX Status Register
38 // ??, ??, ??, RST, RE, TE, ??, ??
41 CAPR = 0x38, // Current address of packet read
42 CBA = 0x3A, // Current Buffer Address - Total byte count in RX buffer
44 IMR = 0x3C, // Interrupt mask register
45 ISR = 0x3E, // Interrupt status register
47 TCR = 0x40, // Transmit Configuration Register
48 RCR = 0x44, // Recieve Configuration Register
49 TCTR = 0x48, // 32-bit timer (count)
50 MPC = 0x4C, // Missed packet count (due to RX overflow)
56 TIMERINT = 0x54, // Fires a timeout when TCTR equals this value
60 #define FLAG_ISR_TOK 0x04
61 #define FLAG_ISR_ROK 0x01
69 int NumWaitingPackets;
72 tPAddr PhysReceiveBuffer;
73 int ReceiveBufferLength;
74 int SeenOfs; //!< End of the most recently seen packet (by IRQ)
76 tSemaphore ReadSemaphore;
78 char *TransmitBuffers[4];
79 tPAddr PhysTransmitBuffers[4];
80 BOOL TransmitInUse; // Flags for each transmit descriptor
88 int RTL8139_Install(char **Options);
89 char *RTL8139_ReadDir(tVFS_Node *Node, int Pos);
90 tVFS_Node *RTL8139_FindDir(tVFS_Node *Node, const char *Filename);
91 int RTL8139_RootIOCtl(tVFS_Node *Node, int ID, void *Arg);
92 Uint64 RTL8139_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
93 Uint64 RTL8139_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
94 int RTL8139_IOCtl(tVFS_Node *Node, int ID, void *Arg);
95 void RTL8139_IRQHandler(int Num);
98 MODULE_DEFINE(0, VERSION, RTL8139, RTL8139_Install, NULL, NULL);
99 tDevFS_Driver gRTL8139_DriverInfo = {
103 .ACLs = &gVFS_ACL_EveryoneRX,
104 .Flags = VFS_FFLAG_DIRECTORY,
105 .ReadDir = RTL8139_ReadDir,
106 .FindDir = RTL8139_FindDir,
107 .IOCtl = RTL8139_RootIOCtl
110 int giRTL8139_CardCount;
111 tCard *gaRTL8139_Cards;
115 * \brief Installs the RTL8139 Driver
117 int RTL8139_Install(char **Options)
124 giRTL8139_CardCount = PCI_CountDevices( 0x10EC, 0x8139, 0 );
126 gaRTL8139_Cards = calloc( giRTL8139_CardCount, sizeof(tCard) );
129 while( (id = PCI_GetDevice(0x10EC, 0x8139, 0, id)) != -1 )
131 base = PCI_AssignPort( id, 0, 0x100 );
132 card = &gaRTL8139_Cards[i];
134 card->IRQ = PCI_GetIRQ( id );
136 // Install IRQ Handler
137 IRQ_AddHandler(card->IRQ, RTL8139_IRQHandler);
140 outb( base + CONFIG1, 0x00 );
142 // Reset (0x10 to CMD)
143 outb( base + CMD, 0x10 );
144 while( inb(base + CMD) & 0x10 ) ;
146 // Set up recieve buffer
147 // - Allocate 3 pages below 4GiB for the recieve buffer (Allows 8k+16+1500)
148 card->ReceiveBuffer = (void*)MM_AllocDMA( 3, 32, &card->PhysReceiveBuffer );
149 outd(base + RBSTART, (Uint32)card->PhysReceiveBuffer);
150 // Set IMR to Transmit OK and Receive OK
151 outw(base + IMR, 0x5);
153 // Set up transmit buffers
154 // - 2 non-contiguous pages (each page can fit 2 1500 byte packets)
155 card->TransmitBuffers[0] = (void*)MM_AllocDMA( 1, 32, &card->PhysTransmitBuffers[0] );
156 card->TransmitBuffers[1] = card->TransmitBuffers[0] + 0x800;
157 card->PhysTransmitBuffers[1] = card->PhysTransmitBuffers[0] + 0x800;
159 card->TransmitBuffers[2] = (void*)MM_AllocDMA( 1, 32, &card->PhysTransmitBuffers[1] );
160 card->TransmitBuffers[3] = card->TransmitBuffers[2] + 0x800;
161 card->PhysTransmitBuffers[3] = card->PhysTransmitBuffers[2] + 0x800;
163 outd(base + TSAD0, card->PhysTransmitBuffers[0]);
164 outd(base + TSAD1, card->PhysTransmitBuffers[1]);
165 outd(base + TSAD2, card->PhysTransmitBuffers[2]);
166 outd(base + TSAD3, card->PhysTransmitBuffers[3]);
168 // Set recieve buffer size and recieve mask
169 // - Bit 7 being unset tells the card to overflow the recieve buffer if needed
170 // (i.e. when the packet starts at the end of the bufffer, it overflows up
172 outd(base + RCR, 0x0F);
174 // Recive Enable and Transmit Enable
175 outb(base + CMD, 0x0C);
177 // Get the card's MAC address
178 card->MacAddr[0] = inb(base+MAC0);
179 card->MacAddr[1] = inb(base+MAC1);
180 card->MacAddr[2] = inb(base+MAC2);
181 card->MacAddr[3] = inb(base+MAC3);
182 card->MacAddr[4] = inb(base+MAC4);
183 card->MacAddr[5] = inb(base+MAC5);
186 card->Name[0] = '0'+i;
187 card->Name[1] = '\0';
188 card->Node.ImplPtr = card;
189 card->Node.NumACLs = 0;
190 card->Node.CTime = now();
191 card->Node.Write = RTL8139_Write;
192 card->Node.Read = RTL8139_Read;
193 card->Node.IOCtl = RTL8139_IOCtl;
195 Log_Log("RTL8139", "Card %i 0x%04x %02x:%02x:%02x:%02x:%02x:%02x",
197 card->MacAddr[0], card->MacAddr[1], card->MacAddr[2],
198 card->MacAddr[3], card->MacAddr[4], card->MacAddr[5]
203 return MODULE_ERR_OK;
206 // --- Root Functions ---
207 char *RTL8139_ReadDir(tVFS_Node *Node, int Pos)
209 if( Pos < 0 || Pos >= giRTL8139_CardCount ) return NULL;
211 return strdup( gaRTL8139_Cards[Pos].Name );
214 tVFS_Node *RTL8139_FindDir(tVFS_Node *Node, const char *Filename)
216 //TODO: It might be an idea to supprt >10 cards
217 if(Filename[0] == '\0' || Filename[0] != '\0') return NULL;
218 if(Filename[0] < '0' || Filename[0] > '9') return NULL;
219 return &gaRTL8139_Cards[ Filename[0]-'0' ].Node;
222 const char *csaRTL8139_RootIOCtls[] = {DRV_IOCTLNAMES, NULL};
223 int RTL8139_RootIOCtl(tVFS_Node *Node, int ID, void *Data)
227 BASE_IOCTLS(DRV_TYPE_NETWORK, "RTL8139", VERSION, csaRTL8139_RootIOCtls);
232 // --- File Functions ---
233 Uint64 RTL8139_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
235 tCard *card = Node->ImplPtr;
236 int read_ofs, pkt_length;
239 Semaphore_Wait( &card->ReadSemaphore, 1 );
241 Mutex_Acquire( &card->ReadMutex );
243 read_ofs = ind( card->IOBase + CAPR ) - card->PhysReceiveBuffer;
246 if( *(Uint16*)&card->ReceiveBuffer[read_ofs] & 0x1E ) {
247 Mutex_Release( &card->ReadMutex );
248 goto retry; // I feel evil
251 pkt_length = *(Uint16*)&card->ReceiveBuffer[read_ofs+2];
254 if( Length > pkt_length ) Length = pkt_length;
255 memcpy(Buffer, &card->ReceiveBuffer[read_ofs+4], Length);
257 // Update read offset
258 read_ofs += pkt_length + 4;
259 read_ofs = (read_ofs + 3) & ~3; // Align
260 if(read_ofs > card->ReceiveBufferLength) read_ofs = 0;
261 outd(card->IOBase + CAPR, read_ofs + card->PhysReceiveBuffer);
263 Mutex_Release( &card->ReadMutex );
268 Uint64 RTL8139_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
272 tCard *card = Node->ImplPtr;
274 if( Length > 1500 ) return 0; // MTU exceeded
276 // TODO: Implement a semaphore for avaliable tranmit buffers
278 // Find an avaliable descriptor
280 for( td = 0; td < 4; td ++ ) {
281 if( !(card->TransmitInUse & (1 << td)) )
284 } while(td == 4 && (Threads_Yield(),1));
286 // Transmit using descriptor `td`
287 card->TransmitInUse |= (1 << td);
289 memcpy(card->TransmitBuffers[td], Buffer, Length);
292 status |= Length & 0x1FFF; // 0-12: Length
293 status |= 0 << 13; // 13: OWN bit
294 status |= (0 & 0x3F) << 16; // 16-21: Early TX threshold (zero atm, TODO: check)
295 outd(card->IOBase + TSD0 + td, status);
300 const char *csaRTL8139_NodeIOCtls[] = {DRV_IOCTLNAMES, NULL};
301 int RTL8139_IOCtl(tVFS_Node *Node, int ID, void *Data)
305 BASE_IOCTLS(DRV_TYPE_NETWORK, "RTL8139", VERSION, csaRTL8139_NodeIOCtls);
310 void RTL8139_IRQHandler(int Num)
315 for( i = 0; i < giRTL8139_CardCount; i ++ )
317 card = &gaRTL8139_Cards[i];
318 if( Num != card->IRQ ) break;
320 status = inb(card->IOBase + ISR);
322 // Transmit OK, a transmit descriptor is now free
323 if( status & FLAG_ISR_TOK )
325 outb(card->IOBase + ISR, FLAG_ISR_TOK);
326 for( j = 0; j < 4; j ++ )
328 if( ind(card->IOBase + TSD0 + j) & 0x8000 ) { // TSD TOK
329 card->TransmitInUse &= ~(1 << j);
330 // TODO: Update semaphore once implemented
335 // Recieve OK, inform read
336 if( status & FLAG_ISR_ROK )
338 int read_ofs, end_ofs;
339 int packet_count = 0;
341 // Scan recieve buffer for packets
342 end_ofs = ind(card->IOBase + CBA) - card->PhysReceiveBuffer;
343 read_ofs = card->SeenOfs;
344 if( read_ofs > end_ofs )
346 while( read_ofs < card->ReceiveBufferLength )
349 read_ofs += *(Uint16*)&card->ReceiveBuffer[read_ofs+1] + 2;
353 while( read_ofs < end_ofs )
356 read_ofs += *(Uint16*)&card->ReceiveBuffer[read_ofs+1] + 2;
358 card->SeenOfs = read_ofs;
360 Semaphore_Signal( &card->ReadSemaphore, packet_count );
362 VFS_MarkAvaliable( &card->Node, 1 );
364 outb(card->IOBase + ISR, FLAG_ISR_ROK);