POK
|
00001 /* 00002 * POK header 00003 * 00004 * The following file is a part of the POK project. Any modification should 00005 * made according to the POK licence. You CANNOT use this file or a part of 00006 * this file is this part of a file for your own project 00007 * 00008 * For more information on the POK licence, please see our LICENCE FILE 00009 * 00010 * Please follow the coding guidelines described in doc/CODING_GUIDELINES 00011 * 00012 * Copyright (c) 2007-2009 POK team 00013 * 00014 * Created by julien on Mon May 18 18:44:51 2009 00015 */ 00016 00024 #ifdef POK_NEEDS_RTL8029 00025 #include "rtl8029.h" 00026 00027 #include <middleware/port.h> 00028 00029 // global since there is no way to get device data otherwise... 00030 static s_ne2000_dev dev; 00031 00032 /* 00033 * We *always* assume page 0 to be selected. 00034 * Two exceptions: initialization and polling. 00035 * Therefore, each time we need to switch to page 1, 00036 * the card is switched to page 0 again when we're done... 00037 */ 00038 #define NE2000_SELECT_PAGE(dev, page) \ 00039 outb((pok_inb((dev)->addr + NE2000_CR) & \ 00040 ~(NE2000_CR_PS0 | NE2000_CR_PS1)) | ((page) << 6), (dev)->addr) 00041 00042 static 00043 ssize_t ne2000_write(const s_ne2000_dev* dev, 00044 const void* buf, 00045 unsigned short count, 00046 unsigned short offset) 00047 { 00048 const char* p = NULL; 00049 ssize_t ret = count; 00050 00051 // Sets RD2 (abort/complete remote DMA) 00052 outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD0 | NE2000_CR_RD1)) | 00053 NE2000_CR_RD2, (dev)->addr); 00054 00055 /* These two registers set the start address of remote DMA. */ 00056 outb(offset, dev->addr + NE2000_RSAR0); 00057 outb(offset >> 8, dev->addr + NE2000_RSAR1); 00058 00059 /* These two registers set the data byte counts of remote DMA. */ 00060 outb(count, dev->addr + NE2000_RBCR0); 00061 outb(count >> 8, dev->addr + NE2000_RBCR1); 00062 00063 // Sets RD1 (remote write) 00064 outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD0 | NE2000_CR_RD2)) | 00065 NE2000_CR_RD1, (dev)->addr); 00066 00067 for (p = buf; count > 0; count--, p++) 00068 { 00069 outb(*p, dev->addr + NE2000_DMA_PORT); 00070 } 00071 00072 return (ret); 00073 } 00074 00075 static 00076 ssize_t ne2000_read(const s_ne2000_dev* dev, 00077 void* buf, 00078 unsigned short count, 00079 unsigned short offset) 00080 { 00081 char* p = NULL; 00082 ssize_t ret = count; 00083 00084 // Sets RD2 (abort/complete remote DMA) 00085 outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD0 | NE2000_CR_RD1)) | 00086 NE2000_CR_RD2, (dev)->addr); 00087 00088 /* These two registers set the start address of remote DMA. */ 00089 outb(offset, dev->addr + NE2000_RSAR0); 00090 outb(offset >> 8, dev->addr + NE2000_RSAR1); 00091 00092 /* These two registers set the data byte counts of remote DMA. */ 00093 outb(count, dev->addr + NE2000_RBCR0); 00094 outb(count >> 8, dev->addr + NE2000_RBCR1); 00095 00096 // Sets RD0 (remote read) 00097 outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD1 | NE2000_CR_RD2)) | 00098 NE2000_CR_RD0, (dev)->addr); 00099 00100 for (p = buf; count > 0; count--, p++) 00101 { 00102 *p = pok_inb(dev->addr + NE2000_DMA_PORT); 00103 } 00104 00105 return (ret); 00106 } 00107 00108 00113 static inline 00114 void rtl8029_enqueue (pok_packet_t *packet) 00115 { 00116 pok_queue_t* queue = dev.recv_buf + packet->udp.dst; 00117 uint32_t off = 0; 00118 uint32_t i = 0; 00119 00120 /* overflow? */ 00121 if (queue->len + packet->udp.len > RECV_BUF_SZ) 00122 { 00123 printf("rtl8029_read: error: ring buffer %d overflow!\n", packet->udp.dst); 00124 return; 00125 } 00126 00127 /* at which offset should we start writing? */ 00128 off = (queue->off + queue->len) % RECV_BUF_SZ; 00129 00130 /* copying data from the packet to the circular buffer in the queue */ 00131 for (i = 0; i < packet->udp.len; i++) 00132 { 00133 queue->data[off] = packet->data[i]; 00134 off = (off + 1) % RECV_BUF_SZ; 00135 } 00136 00137 /* updating data length in this queue */ 00138 queue->len += packet->udp.len; 00139 } 00140 00146 void rtl8029_read (pok_port_id_t port_id, void* data, uint32_t len) 00147 { 00148 pok_port_id_t global; 00149 pok_ret_t ret; 00150 00151 ret = pok_port_virtual_get_global (port_id, &global); 00152 00153 if (ret == POK_ERRNO_OK) 00154 { 00155 char *dest = data; 00156 pok_queue_t* queue = dev.recv_buf + global; 00157 uint32_t size = len < queue->len ? len : queue->len; 00158 uint32_t copied = 0; 00159 00160 printf ("[RTL8029] READ DATA FROM LOCAL PORT %d " 00161 "GLOBAL_PORT=%d), size=%d\n", port_id, global, len); 00162 00163 /* is there something to read ? */ 00164 if (queue->len == 0) 00165 { 00166 printf("rtl8029_read: error: empty read ring buffer %d!\n", port_id); 00167 return; 00168 } 00169 00170 /* copy from the queue to the buffer */ 00171 for (copied = 0; copied < size; copied++) 00172 { 00173 dest[copied % RECV_BUF_SZ] = queue->data[queue->off]; 00174 queue->off = (queue->off + 1) % RECV_BUF_SZ; 00175 } 00176 00177 /* updating data length in this queue */ 00178 queue->len -= size; 00179 } 00180 } 00181 00187 void rtl8029_write (pok_port_id_t port_id, const void* data, uint32_t len) 00188 { 00189 uint32_t nbdest; 00190 uint32_t tmp; 00191 uint32_t dest; 00192 pok_ret_t ret; 00193 char node2[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 00194 pok_packet_t packet; 00195 const char* d; 00196 size_t cpylen = 0; 00197 size_t sndlen = 0; 00198 unsigned char state; // ISR state 00199 00200 ret = pok_port_virtual_nb_destinations (port_id, &nbdest); 00201 if (ret != POK_ERRNO_OK) 00202 { 00203 return; 00204 } 00205 00206 for (tmp = 0 ; tmp < nbdest ; tmp++) 00207 { 00208 ret = pok_port_virtual_destination (port_id, tmp, &dest); 00209 if (ret == POK_ERRNO_OK) 00210 { 00211 printf ("[RTL8029] SEND DATA THROUGH NETWORK FROM LOCAL PORT %d " 00212 "TO GLOBAL PORT %d, size=%d\n", port_id, dest, len); 00213 00214 memcpy(packet.eth.src, dev.mac, ETH_MAC_LEN); 00215 memcpy(packet.eth.dst, node2, ETH_MAC_LEN); 00216 packet.eth.ethertype = 0x4242; 00217 packet.udp.src = port_id; 00218 packet.udp.dst = dest; 00219 00220 for (d = data; len != 0; len -= cpylen, data += cpylen) 00221 { 00222 // too short; let's cut 00223 if (len <= NET_DATA_MINLEN) 00224 { 00225 cpylen = len; 00226 sndlen = ETH_DATA_MINLEN + sizeof(eth_hdr_t); 00227 } 00228 else 00229 { 00230 // too big; let's pad 00231 if (len >= NET_DATA_MAXLEN) 00232 { 00233 cpylen = NET_DATA_MAXLEN; 00234 sndlen = ETH_DATA_MAXLEN + sizeof(eth_hdr_t); 00235 } 00236 // normal 00237 else 00238 { 00239 cpylen = len; 00240 sndlen = sizeof(eth_hdr_t) + sizeof(udp_hdr_t) + cpylen; 00241 } 00242 } 00243 00244 packet.udp.len = cpylen; 00245 memcpy(&(packet.data), data, cpylen); 00246 00247 ne2000_write(&dev, &packet, sndlen, NE2000_TXBUF * 256); 00248 00249 do 00250 { 00251 state = pok_inb(dev.addr + NE2000_ISR); 00252 } 00253 while ((state & NE2000_ISR_RDC) != NE2000_ISR_RDC); 00254 00255 /* This register sets the start page address of 00256 the packet to the transmitted. */ 00257 outb(NE2000_TXBUF, dev.addr + NE2000_TPSR); //? 00258 00259 /* These two registers set the byte counts of 00260 the packet to be transmitted. */ 00261 outb(sndlen, dev.addr + NE2000_TBCR0); 00262 outb(sndlen >> 8, dev.addr + NE2000_TBCR1); 00263 00264 /* This bit must be set to transmit a packet. */ 00265 outb(pok_inb(dev.addr + NE2000_CR) | NE2000_CR_TXP, 00266 dev.addr + NE2000_CR); 00267 00268 outb(NE2000_ISR_RDC, dev.addr + NE2000_ISR); // Clear RDC bit 00269 } 00270 } 00271 } 00272 } 00273 00279 void rtl8029_polling () 00280 { 00281 unsigned char state; // ISR state 00282 00283 NE2000_SELECT_PAGE(&dev, 0); 00284 00285 while (1) 00286 { 00287 // do we have an interrupt flag set? 00288 if ((state = pok_inb(dev.addr + NE2000_ISR)) == 0) 00289 continue; 00290 00291 if (state & NE2000_ISR_PRX) 00292 { 00293 if ((pok_inb(dev.addr + NE2000_RSR) & NE2000_RSR_PRX) == 0) 00294 { 00295 // error 00296 } 00297 00298 printf("[*]\n"); 00299 00300 /* no errors */ 00301 s_ne2000_header ne2000_hdr; // ne2000 packet header 00302 unsigned short offset; // dma offset 00303 unsigned char start, end; // pointers for the ring buffer 00304 pok_packet_t recv_packet; 00305 00306 while (1) 00307 { 00308 00309 /* This register is used to prevent overwrite of the receive buffer ring. 00310 It is typically used as a pointer indicating the last receive buffer 00311 page the host has read.*/ 00312 start = pok_inb(dev.addr + NE2000_BNRY) + 1; 00313 00314 /* This register points to the page address of the first receive 00315 buffer page to be used for a packet reception. */ 00316 NE2000_SELECT_PAGE(&dev, 1); 00317 end = pok_inb(dev.addr + NE2000_CURR); 00318 NE2000_SELECT_PAGE(&dev, 0); 00319 00320 if ((end % NE2000_MEMSZ) == (start % NE2000_MEMSZ) + 1) 00321 { 00322 break; 00323 } 00324 00325 /* et on decapsule! */ 00326 offset = start << 8; 00327 // ne2000 header 00328 offset += ne2000_read(&dev, &ne2000_hdr, sizeof(s_ne2000_header), 00329 offset); 00330 00331 ne2000_read(&dev, &recv_packet, 00332 ne2000_hdr.size - sizeof(s_ne2000_header), offset); 00333 rtl8029_enqueue(&recv_packet); 00334 00335 // update the BNRY register... almost forgot that 00336 outb(ne2000_hdr.next > NE2000_MEMSZ ? 00337 NE2000_RXBUF - 1 : ne2000_hdr.next - 1, dev.addr + NE2000_BNRY); 00338 00339 } 00340 00341 outb(NE2000_ISR_PRX, dev.addr + NE2000_ISR); // Clear PRX flag 00342 } 00343 00344 if (state & NE2000_ISR_PTX) 00345 { 00346 outb(NE2000_ISR_PTX, dev.addr + NE2000_ISR); // Clear PTX flag 00347 } 00348 00349 if (state & NE2000_ISR_RXE) 00350 { 00351 outb(NE2000_ISR_RXE, dev.addr + NE2000_ISR); // Clear RXE flag 00352 } 00353 00354 if (state & NE2000_ISR_TXE) 00355 { 00356 outb(NE2000_ISR_TXE, dev.addr + NE2000_ISR); // Clear TXE flag 00357 } 00358 00359 if (state & NE2000_ISR_OVW) 00360 { 00361 outb(NE2000_ISR_OVW, dev.addr + NE2000_ISR); // Clear OVW flag 00362 } 00363 00364 if (state & NE2000_ISR_CNT) 00365 { 00366 outb(NE2000_ISR_CNT, dev.addr + NE2000_ISR); // Clear CNT flag 00367 } 00368 00369 if (state & NE2000_ISR_RST) 00370 { 00371 outb(NE2000_ISR_RST, dev.addr + NE2000_ISR); // Clear RST bit 00372 } 00373 } 00374 } 00375 00382 void rtl8029_init () 00383 { 00384 dev.pci.vendorid = 0x10ec; 00385 dev.pci.deviceid = 0x8029; 00386 dev.pci.io_range = 0x10; 00387 00388 if (pci_register(&(dev.pci)) != 0) 00389 { 00390 printf("rtl8029: PCI init failed!\n"); 00391 return; 00392 } 00393 00394 dev.addr = dev.pci.bar[0] & (~0x1F); 00395 00396 unsigned char i = 0; 00397 unsigned char buf[6 * 2]; // used for MAC address 00398 00399 NE2000_SELECT_PAGE(&dev, 0); 00400 00401 /* This bit is the STOP command. When it is set, no packets will be 00402 received or transmitted. POWER UP=1. */ 00403 outb(NE2000_CR_STP, dev.addr + NE2000_CR); 00404 00405 // Sets several options... Read the datasheet! 00406 outb(0x00, dev.addr + NE2000_TCR); 00407 outb(NE2000_RCR_AB, dev.addr + NE2000_RCR); 00408 outb(NE2000_DCR_LS | NE2000_DCR_FT1, dev.addr + NE2000_DCR); 00409 00410 /* The Page Start register sets the start page address 00411 of the receive buffer ring. */ 00412 outb(NE2000_RXBUF, dev.addr + NE2000_PSTART); 00413 /* The Page Stop register sets the stop page address 00414 of the receive buffer ring. */ 00415 outb(NE2000_MEMSZ, dev.addr + NE2000_PSTOP); 00416 /* This register is used to prevent overwrite of the receive buffer ring. 00417 It is typically used as a pointer indicating the last receive buffer 00418 page the host has read. */ 00419 outb(NE2000_RXBUF, dev.addr + NE2000_BNRY); 00420 00421 /* These two registers set the data byte counts of remote DMA. */ 00422 outb(0, dev.addr + NE2000_RBCR0); 00423 outb(0, dev.addr + NE2000_RBCR1); 00424 00425 NE2000_SELECT_PAGE(&dev, 1); 00426 00427 /* This register points to the page address of the first receive buffer 00428 page to be used for a packet reception. */ 00429 outb(NE2000_RXBUF + 1, dev.addr + NE2000_CURR); 00430 00431 // Init mac address 00432 /* Here's something I do not understand... Section 6.2.2 of the datasheet 00433 says bytes 00H-05H of the PROM corresponds to the Ethernet ID. But it 00434 looks like each byte of the MAC address is written twice... 00435 Therefore I read 2 * sizeof(mac) and select one of the two bytes 00436 corresponding to the MAC... Weird... Really... */ 00437 ne2000_read(&dev, buf, 6 * 2, 0); 00438 for (i = 0; i < 6; i++) 00439 dev.mac[i] = buf[i * 2]; 00440 00441 /* These registers contain my Ethernet node address and are used to compare 00442 the destination address of incoming packets for acceptation or rejection.*/ 00443 outb(dev.mac[0], dev.addr + NE2000_PAR0); 00444 outb(dev.mac[1], dev.addr + NE2000_PAR1); 00445 outb(dev.mac[2], dev.addr + NE2000_PAR2); 00446 outb(dev.mac[3], dev.addr + NE2000_PAR3); 00447 outb(dev.mac[4], dev.addr + NE2000_PAR4); 00448 outb(dev.mac[5], dev.addr + NE2000_PAR5); 00449 00450 NE2000_SELECT_PAGE(&dev, 0); 00451 00452 // Start command 00453 outb(NE2000_CR_STA, dev.addr + NE2000_CR); 00454 00455 // Reactivating interrupts 00456 /* ISR register must be cleared after power up. */ 00457 outb(0xFF, dev.addr + NE2000_ISR); 00458 /* All bits correspond to the bits in the ISR register. POWER UP=all 0s. 00459 Setting individual bits will enable the corresponding interrupts. */ 00460 /* Since POK use polling, ALL interrupts are disabled */ 00461 outb(0x00, dev.addr + NE2000_IMR); 00462 00463 for (i = 0; i < 20; i++) /* TODO: random constant */ 00464 { 00465 dev.recv_buf[i].len = 0; 00466 dev.recv_buf[i].off = 0; 00467 } 00468 00469 return; 00470 } 00471 00472 #endif