POK
rtl8029.c
Go to the documentation of this file.
1 /*
2  * POK header
3  *
4  * The following file is a part of the POK project. Any modification should
5  * made according to the POK licence. You CANNOT use this file or a part of
6  * this file is this part of a file for your own project
7  *
8  * For more information on the POK licence, please see our LICENCE FILE
9  *
10  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
11  *
12  * Copyright (c) 2007-2009 POK team
13  *
14  * Created by julien on Mon May 18 18:44:51 2009
15  */
16 
24 #ifdef POK_NEEDS_RTL8029
25 #include "rtl8029.h"
26 
27 #include <middleware/port.h>
28 
29 // global since there is no way to get device data otherwise...
30 static s_ne2000_dev dev;
31 
32 /*
33  * We *always* assume page 0 to be selected.
34  * Two exceptions: initialization and polling.
35  * Therefore, each time we need to switch to page 1,
36  * the card is switched to page 0 again when we're done...
37  */
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)
41 
42 static
43 ssize_t ne2000_write(const s_ne2000_dev* dev,
44  const void* buf,
45  unsigned short count,
46  unsigned short offset)
47 {
48  const char* p = NULL;
49  ssize_t ret = count;
50 
51  // Sets RD2 (abort/complete remote DMA)
52  outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD0 | NE2000_CR_RD1)) |
53  NE2000_CR_RD2, (dev)->addr);
54 
55  /* These two registers set the start address of remote DMA. */
56  outb(offset, dev->addr + NE2000_RSAR0);
57  outb(offset >> 8, dev->addr + NE2000_RSAR1);
58 
59  /* These two registers set the data byte counts of remote DMA. */
60  outb(count, dev->addr + NE2000_RBCR0);
61  outb(count >> 8, dev->addr + NE2000_RBCR1);
62 
63  // Sets RD1 (remote write)
64  outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD0 | NE2000_CR_RD2)) |
65  NE2000_CR_RD1, (dev)->addr);
66 
67  for (p = buf; count > 0; count--, p++)
68  {
69  outb(*p, dev->addr + NE2000_DMA_PORT);
70  }
71 
72  return (ret);
73 }
74 
75 static
76 ssize_t ne2000_read(const s_ne2000_dev* dev,
77  void* buf,
78  unsigned short count,
79  unsigned short offset)
80 {
81  char* p = NULL;
82  ssize_t ret = count;
83 
84  // Sets RD2 (abort/complete remote DMA)
85  outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD0 | NE2000_CR_RD1)) |
86  NE2000_CR_RD2, (dev)->addr);
87 
88  /* These two registers set the start address of remote DMA. */
89  outb(offset, dev->addr + NE2000_RSAR0);
90  outb(offset >> 8, dev->addr + NE2000_RSAR1);
91 
92  /* These two registers set the data byte counts of remote DMA. */
93  outb(count, dev->addr + NE2000_RBCR0);
94  outb(count >> 8, dev->addr + NE2000_RBCR1);
95 
96  // Sets RD0 (remote read)
97  outb((pok_inb((dev)->addr + NE2000_CR) & ~(NE2000_CR_RD1 | NE2000_CR_RD2)) |
98  NE2000_CR_RD0, (dev)->addr);
99 
100  for (p = buf; count > 0; count--, p++)
101  {
102  *p = pok_inb(dev->addr + NE2000_DMA_PORT);
103  }
104 
105  return (ret);
106 }
107 
108 
113 static inline
114 void rtl8029_enqueue (pok_packet_t *packet)
115 {
116  pok_queue_t* queue = dev.recv_buf + packet->udp.dst;
117  uint32_t off = 0;
118  uint32_t i = 0;
119 
120  /* overflow? */
121  if (queue->len + packet->udp.len > RECV_BUF_SZ)
122  {
123  printf("rtl8029_read: error: ring buffer %d overflow!\n", packet->udp.dst);
124  return;
125  }
126 
127  /* at which offset should we start writing? */
128  off = (queue->off + queue->len) % RECV_BUF_SZ;
129 
130  /* copying data from the packet to the circular buffer in the queue */
131  for (i = 0; i < packet->udp.len; i++)
132  {
133  queue->data[off] = packet->data[i];
134  off = (off + 1) % RECV_BUF_SZ;
135  }
136 
137  /* updating data length in this queue */
138  queue->len += packet->udp.len;
139 }
140 
146 void rtl8029_read (pok_port_id_t port_id, void* data, uint32_t len)
147 {
148  pok_port_id_t global;
149  pok_ret_t ret;
150 
151  ret = pok_port_virtual_get_global (port_id, &global);
152 
153  if (ret == POK_ERRNO_OK)
154  {
155  char *dest = data;
156  pok_queue_t* queue = dev.recv_buf + global;
157  uint32_t size = len < queue->len ? len : queue->len;
158  uint32_t copied = 0;
159 
160  printf ("[RTL8029] READ DATA FROM LOCAL PORT %d "
161  "GLOBAL_PORT=%d), size=%d\n", port_id, global, len);
162 
163  /* is there something to read ? */
164  if (queue->len == 0)
165  {
166  printf("rtl8029_read: error: empty read ring buffer %d!\n", port_id);
167  return;
168  }
169 
170  /* copy from the queue to the buffer */
171  for (copied = 0; copied < size; copied++)
172  {
173  dest[copied % RECV_BUF_SZ] = queue->data[queue->off];
174  queue->off = (queue->off + 1) % RECV_BUF_SZ;
175  }
176 
177  /* updating data length in this queue */
178  queue->len -= size;
179  }
180 }
181 
187 void rtl8029_write (pok_port_id_t port_id, const void* data, uint32_t len)
188 {
189  uint32_t nbdest;
190  uint32_t tmp;
191  uint32_t dest;
192  pok_ret_t ret;
193  char node2[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
194  pok_packet_t packet;
195  const char* d;
196  size_t cpylen = 0;
197  size_t sndlen = 0;
198  unsigned char state; // ISR state
199 
200  ret = pok_port_virtual_nb_destinations (port_id, &nbdest);
201  if (ret != POK_ERRNO_OK)
202  {
203  return;
204  }
205 
206  for (tmp = 0 ; tmp < nbdest ; tmp++)
207  {
208  ret = pok_port_virtual_destination (port_id, tmp, &dest);
209  if (ret == POK_ERRNO_OK)
210  {
211  printf ("[RTL8029] SEND DATA THROUGH NETWORK FROM LOCAL PORT %d "
212  "TO GLOBAL PORT %d, size=%d\n", port_id, dest, len);
213 
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;
219 
220  for (d = data; len != 0; len -= cpylen, data += cpylen)
221  {
222  // too short; let's cut
223  if (len <= NET_DATA_MINLEN)
224  {
225  cpylen = len;
226  sndlen = ETH_DATA_MINLEN + sizeof(eth_hdr_t);
227  }
228  else
229  {
230  // too big; let's pad
231  if (len >= NET_DATA_MAXLEN)
232  {
233  cpylen = NET_DATA_MAXLEN;
234  sndlen = ETH_DATA_MAXLEN + sizeof(eth_hdr_t);
235  }
236  // normal
237  else
238  {
239  cpylen = len;
240  sndlen = sizeof(eth_hdr_t) + sizeof(udp_hdr_t) + cpylen;
241  }
242  }
243 
244  packet.udp.len = cpylen;
245  memcpy(&(packet.data), data, cpylen);
246 
247  ne2000_write(&dev, &packet, sndlen, NE2000_TXBUF * 256);
248 
249  do
250  {
251  state = pok_inb(dev.addr + NE2000_ISR);
252  }
253  while ((state & NE2000_ISR_RDC) != NE2000_ISR_RDC);
254 
255  /* This register sets the start page address of
256  the packet to the transmitted. */
257  outb(NE2000_TXBUF, dev.addr + NE2000_TPSR); //?
258 
259  /* These two registers set the byte counts of
260  the packet to be transmitted. */
261  outb(sndlen, dev.addr + NE2000_TBCR0);
262  outb(sndlen >> 8, dev.addr + NE2000_TBCR1);
263 
264  /* This bit must be set to transmit a packet. */
265  outb(pok_inb(dev.addr + NE2000_CR) | NE2000_CR_TXP,
266  dev.addr + NE2000_CR);
267 
268  outb(NE2000_ISR_RDC, dev.addr + NE2000_ISR); // Clear RDC bit
269  }
270  }
271  }
272 }
273 
280 {
281  unsigned char state; // ISR state
282 
283  NE2000_SELECT_PAGE(&dev, 0);
284 
285  while (1)
286  {
287  // do we have an interrupt flag set?
288  if ((state = pok_inb(dev.addr + NE2000_ISR)) == 0)
289  continue;
290 
291  if (state & NE2000_ISR_PRX)
292  {
293  if ((pok_inb(dev.addr + NE2000_RSR) & NE2000_RSR_PRX) == 0)
294  {
295  // error
296  }
297 
298  printf("[*]\n");
299 
300  /* no errors */
301  s_ne2000_header ne2000_hdr; // ne2000 packet header
302  unsigned short offset; // dma offset
303  unsigned char start, end; // pointers for the ring buffer
304  pok_packet_t recv_packet;
305 
306  while (1)
307  {
308 
309  /* This register is used to prevent overwrite of the receive buffer ring.
310  It is typically used as a pointer indicating the last receive buffer
311  page the host has read.*/
312  start = pok_inb(dev.addr + NE2000_BNRY) + 1;
313 
314  /* This register points to the page address of the first receive
315  buffer page to be used for a packet reception. */
316  NE2000_SELECT_PAGE(&dev, 1);
317  end = pok_inb(dev.addr + NE2000_CURR);
318  NE2000_SELECT_PAGE(&dev, 0);
319 
320  if ((end % NE2000_MEMSZ) == (start % NE2000_MEMSZ) + 1)
321  {
322  break;
323  }
324 
325  /* et on decapsule! */
326  offset = start << 8;
327  // ne2000 header
328  offset += ne2000_read(&dev, &ne2000_hdr, sizeof(s_ne2000_header),
329  offset);
330 
331  ne2000_read(&dev, &recv_packet,
332  ne2000_hdr.size - sizeof(s_ne2000_header), offset);
333  rtl8029_enqueue(&recv_packet);
334 
335  // update the BNRY register... almost forgot that
336  outb(ne2000_hdr.next > NE2000_MEMSZ ?
337  NE2000_RXBUF - 1 : ne2000_hdr.next - 1, dev.addr + NE2000_BNRY);
338 
339  }
340 
341  outb(NE2000_ISR_PRX, dev.addr + NE2000_ISR); // Clear PRX flag
342  }
343 
344  if (state & NE2000_ISR_PTX)
345  {
346  outb(NE2000_ISR_PTX, dev.addr + NE2000_ISR); // Clear PTX flag
347  }
348 
349  if (state & NE2000_ISR_RXE)
350  {
351  outb(NE2000_ISR_RXE, dev.addr + NE2000_ISR); // Clear RXE flag
352  }
353 
354  if (state & NE2000_ISR_TXE)
355  {
356  outb(NE2000_ISR_TXE, dev.addr + NE2000_ISR); // Clear TXE flag
357  }
358 
359  if (state & NE2000_ISR_OVW)
360  {
361  outb(NE2000_ISR_OVW, dev.addr + NE2000_ISR); // Clear OVW flag
362  }
363 
364  if (state & NE2000_ISR_CNT)
365  {
366  outb(NE2000_ISR_CNT, dev.addr + NE2000_ISR); // Clear CNT flag
367  }
368 
369  if (state & NE2000_ISR_RST)
370  {
371  outb(NE2000_ISR_RST, dev.addr + NE2000_ISR); // Clear RST bit
372  }
373  }
374 }
375 
383 {
384  dev.pci.vendorid = 0x10ec;
385  dev.pci.deviceid = 0x8029;
386  dev.pci.io_range = 0x10;
387 
388  if (pci_register(&(dev.pci)) != 0)
389  {
390  printf("rtl8029: PCI init failed!\n");
391  return;
392  }
393 
394  dev.addr = dev.pci.bar[0] & (~0x1F);
395 
396  unsigned char i = 0;
397  unsigned char buf[6 * 2]; // used for MAC address
398 
399  NE2000_SELECT_PAGE(&dev, 0);
400 
401  /* This bit is the STOP command. When it is set, no packets will be
402  received or transmitted. POWER UP=1. */
403  outb(NE2000_CR_STP, dev.addr + NE2000_CR);
404 
405  // Sets several options... Read the datasheet!
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);
409 
410  /* The Page Start register sets the start page address
411  of the receive buffer ring. */
412  outb(NE2000_RXBUF, dev.addr + NE2000_PSTART);
413  /* The Page Stop register sets the stop page address
414  of the receive buffer ring. */
415  outb(NE2000_MEMSZ, dev.addr + NE2000_PSTOP);
416  /* This register is used to prevent overwrite of the receive buffer ring.
417  It is typically used as a pointer indicating the last receive buffer
418  page the host has read. */
419  outb(NE2000_RXBUF, dev.addr + NE2000_BNRY);
420 
421  /* These two registers set the data byte counts of remote DMA. */
422  outb(0, dev.addr + NE2000_RBCR0);
423  outb(0, dev.addr + NE2000_RBCR1);
424 
425  NE2000_SELECT_PAGE(&dev, 1);
426 
427  /* This register points to the page address of the first receive buffer
428  page to be used for a packet reception. */
429  outb(NE2000_RXBUF + 1, dev.addr + NE2000_CURR);
430 
431  // Init mac address
432  /* Here's something I do not understand... Section 6.2.2 of the datasheet
433  says bytes 00H-05H of the PROM corresponds to the Ethernet ID. But it
434  looks like each byte of the MAC address is written twice...
435  Therefore I read 2 * sizeof(mac) and select one of the two bytes
436  corresponding to the MAC... Weird... Really... */
437  ne2000_read(&dev, buf, 6 * 2, 0);
438  for (i = 0; i < 6; i++)
439  dev.mac[i] = buf[i * 2];
440 
441  /* These registers contain my Ethernet node address and are used to compare
442  the destination address of incoming packets for acceptation or rejection.*/
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);
449 
450  NE2000_SELECT_PAGE(&dev, 0);
451 
452  // Start command
453  outb(NE2000_CR_STA, dev.addr + NE2000_CR);
454 
455  // Reactivating interrupts
456  /* ISR register must be cleared after power up. */
457  outb(0xFF, dev.addr + NE2000_ISR);
458  /* All bits correspond to the bits in the ISR register. POWER UP=all 0s.
459  Setting individual bits will enable the corresponding interrupts. */
460  /* Since POK use polling, ALL interrupts are disabled */
461  outb(0x00, dev.addr + NE2000_IMR);
462 
463  for (i = 0; i < 20; i++) /* TODO: random constant */
464  {
465  dev.recv_buf[i].len = 0;
466  dev.recv_buf[i].off = 0;
467  }
468 
469  return;
470 }
471 
472 #endif