24 #ifdef POK_NEEDS_RTL8029
27 #include <middleware/port.h>
38 #define NE2000_SELECT_PAGE(dev, page) \
39 outb((pok_inb((dev)->addr + NE2000_CR) & \
40 ~(NE2000_CR_PS0 | NE2000_CR_PS1)) | ((page) << 6), (dev)->addr)
46 unsigned short offset)
52 outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD0 | NE2000_CR_RD1)) |
53 NE2000_CR_RD2, (dev)->addr);
56 outb(offset, dev->addr + NE2000_RSAR0);
57 outb(offset >> 8, dev->addr + NE2000_RSAR1);
60 outb(count, dev->addr + NE2000_RBCR0);
61 outb(count >> 8, dev->addr + NE2000_RBCR1);
64 outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD0 | NE2000_CR_RD2)) |
65 NE2000_CR_RD1, (dev)->addr);
67 for (p = buf; count > 0; count--, p++)
69 outb(*p, dev->addr + NE2000_DMA_PORT);
79 unsigned short offset)
85 outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD0 | NE2000_CR_RD1)) |
86 NE2000_CR_RD2, (dev)->addr);
89 outb(offset, dev->addr + NE2000_RSAR0);
90 outb(offset >> 8, dev->addr + NE2000_RSAR1);
93 outb(count, dev->addr + NE2000_RBCR0);
94 outb(count >> 8, dev->addr + NE2000_RBCR1);
97 outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD1 | NE2000_CR_RD2)) |
98 NE2000_CR_RD0, (dev)->addr);
100 for (p = buf; count > 0; count--, p++)
102 *p = pok_inb(dev->addr + NE2000_DMA_PORT);
114 void rtl8029_enqueue (pok_packet_t *packet)
116 pok_queue_t* queue = dev.recv_buf + packet->udp.dst;
121 if (queue->len + packet->udp.len > RECV_BUF_SZ)
123 printf(
"rtl8029_read: error: ring buffer %d overflow!\n", packet->udp.dst);
128 off = (queue->off + queue->len) % RECV_BUF_SZ;
131 for (i = 0; i < packet->udp.len; i++)
133 queue->data[off] = packet->data[i];
134 off = (off + 1) % RECV_BUF_SZ;
138 queue->len += packet->udp.len;
148 pok_port_id_t global;
151 ret = pok_port_virtual_get_global (port_id, &global);
153 if (ret == POK_ERRNO_OK)
157 uint32_t size = len < queue->len ? len : queue->len;
160 printf (
"[RTL8029] READ DATA FROM LOCAL PORT %d "
161 "GLOBAL_PORT=%d), size=%d\n", port_id, global, len);
166 printf(
"rtl8029_read: error: empty read ring buffer %d!\n", port_id);
171 for (copied = 0; copied < size; copied++)
173 dest[copied % RECV_BUF_SZ] = queue->data[queue->off];
174 queue->off = (queue->off + 1) % RECV_BUF_SZ;
193 char node2[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
200 ret = pok_port_virtual_nb_destinations (port_id, &nbdest);
201 if (ret != POK_ERRNO_OK)
206 for (tmp = 0 ; tmp < nbdest ; tmp++)
208 ret = pok_port_virtual_destination (port_id, tmp, &dest);
209 if (ret == POK_ERRNO_OK)
211 printf (
"[RTL8029] SEND DATA THROUGH NETWORK FROM LOCAL PORT %d "
212 "TO GLOBAL PORT %d, size=%d\n", port_id, dest, len);
214 memcpy(packet.eth.src, dev.mac, ETH_MAC_LEN);
215 memcpy(packet.eth.dst, node2, ETH_MAC_LEN);
216 packet.eth.ethertype = 0x4242;
217 packet.udp.src = port_id;
218 packet.udp.dst = dest;
220 for (d = data; len != 0; len -= cpylen, data += cpylen)
223 if (len <= NET_DATA_MINLEN)
226 sndlen = ETH_DATA_MINLEN +
sizeof(eth_hdr_t);
231 if (len >= NET_DATA_MAXLEN)
233 cpylen = NET_DATA_MAXLEN;
234 sndlen = ETH_DATA_MAXLEN +
sizeof(eth_hdr_t);
240 sndlen =
sizeof(eth_hdr_t) +
sizeof(udp_hdr_t) + cpylen;
244 packet.udp.len = cpylen;
245 memcpy(&(packet.data), data, cpylen);
247 ne2000_write(&dev, &packet, sndlen, NE2000_TXBUF * 256);
251 state = pok_inb(dev.addr + NE2000_ISR);
253 while ((state & NE2000_ISR_RDC) != NE2000_ISR_RDC);
257 outb(NE2000_TXBUF, dev.addr + NE2000_TPSR);
261 outb(sndlen, dev.addr + NE2000_TBCR0);
262 outb(sndlen >> 8, dev.addr + NE2000_TBCR1);
265 outb(pok_inb(dev.addr + NE2000_CR) | NE2000_CR_TXP,
266 dev.addr + NE2000_CR);
268 outb(NE2000_ISR_RDC, dev.addr + NE2000_ISR);
283 NE2000_SELECT_PAGE(&dev, 0);
288 if ((state = pok_inb(dev.addr + NE2000_ISR)) == 0)
291 if (state & NE2000_ISR_PRX)
293 if ((pok_inb(dev.addr + NE2000_RSR) & NE2000_RSR_PRX) == 0)
301 s_ne2000_header ne2000_hdr;
302 unsigned short offset;
303 unsigned char start, end;
304 pok_packet_t recv_packet;
312 start = pok_inb(dev.addr + NE2000_BNRY) + 1;
316 NE2000_SELECT_PAGE(&dev, 1);
317 end = pok_inb(dev.addr + NE2000_CURR);
318 NE2000_SELECT_PAGE(&dev, 0);
320 if ((end % NE2000_MEMSZ) == (start % NE2000_MEMSZ) + 1)
328 offset += ne2000_read(&dev, &ne2000_hdr,
sizeof(s_ne2000_header),
331 ne2000_read(&dev, &recv_packet,
332 ne2000_hdr.size -
sizeof(s_ne2000_header), offset);
333 rtl8029_enqueue(&recv_packet);
336 outb(ne2000_hdr.next > NE2000_MEMSZ ?
337 NE2000_RXBUF - 1 : ne2000_hdr.next - 1, dev.addr + NE2000_BNRY);
341 outb(NE2000_ISR_PRX, dev.addr + NE2000_ISR);
344 if (state & NE2000_ISR_PTX)
346 outb(NE2000_ISR_PTX, dev.addr + NE2000_ISR);
349 if (state & NE2000_ISR_RXE)
351 outb(NE2000_ISR_RXE, dev.addr + NE2000_ISR);
354 if (state & NE2000_ISR_TXE)
356 outb(NE2000_ISR_TXE, dev.addr + NE2000_ISR);
359 if (state & NE2000_ISR_OVW)
361 outb(NE2000_ISR_OVW, dev.addr + NE2000_ISR);
364 if (state & NE2000_ISR_CNT)
366 outb(NE2000_ISR_CNT, dev.addr + NE2000_ISR);
369 if (state & NE2000_ISR_RST)
371 outb(NE2000_ISR_RST, dev.addr + NE2000_ISR);
384 dev.pci.vendorid = 0x10ec;
385 dev.pci.deviceid = 0x8029;
386 dev.pci.io_range = 0x10;
388 if (pci_register(&(dev.pci)) != 0)
390 printf(
"rtl8029: PCI init failed!\n");
394 dev.addr = dev.pci.bar[0] & (~0x1F);
397 unsigned char buf[6 * 2];
399 NE2000_SELECT_PAGE(&dev, 0);
403 outb(NE2000_CR_STP, dev.addr + NE2000_CR);
406 outb(0x00, dev.addr + NE2000_TCR);
407 outb(NE2000_RCR_AB, dev.addr + NE2000_RCR);
408 outb(NE2000_DCR_LS | NE2000_DCR_FT1, dev.addr + NE2000_DCR);
412 outb(NE2000_RXBUF, dev.addr + NE2000_PSTART);
415 outb(NE2000_MEMSZ, dev.addr + NE2000_PSTOP);
419 outb(NE2000_RXBUF, dev.addr + NE2000_BNRY);
422 outb(0, dev.addr + NE2000_RBCR0);
423 outb(0, dev.addr + NE2000_RBCR1);
425 NE2000_SELECT_PAGE(&dev, 1);
429 outb(NE2000_RXBUF + 1, dev.addr + NE2000_CURR);
437 ne2000_read(&dev, buf, 6 * 2, 0);
438 for (i = 0; i < 6; i++)
439 dev.mac[i] = buf[i * 2];
443 outb(dev.mac[0], dev.addr + NE2000_PAR0);
444 outb(dev.mac[1], dev.addr + NE2000_PAR1);
445 outb(dev.mac[2], dev.addr + NE2000_PAR2);
446 outb(dev.mac[3], dev.addr + NE2000_PAR3);
447 outb(dev.mac[4], dev.addr + NE2000_PAR4);
448 outb(dev.mac[5], dev.addr + NE2000_PAR5);
450 NE2000_SELECT_PAGE(&dev, 0);
453 outb(NE2000_CR_STA, dev.addr + NE2000_CR);
457 outb(0xFF, dev.addr + NE2000_ISR);
461 outb(0x00, dev.addr + NE2000_IMR);
463 for (i = 0; i < 20; i++)
465 dev.recv_buf[i].len = 0;
466 dev.recv_buf[i].off = 0;