1 // vim: set et sw=4 sts=4 :
5 void sleep(unsigned char);
7 static xdata leds1 _at_ 0x0080;
8 static xdata leds2 _at_ 0x00c0;
10 unsigned char uip_buf[80] =
12 0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbf, // MAC destino
13 //0x00, 0x80, 0xc7, 0x42, 0x8d, 0x27, // MAC destino
14 0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbe, // MAC fuente
18 unsigned int uip_len = 14;
20 // Packet transmit & receive buffer configuration
21 #define ETH_TX_PAGE_START 0x40 // 0x4000 Tx buffer is 6 * 256 = 1536 bytes
22 #define ETH_RX_PAGE_START 0x46 // 0x4600 Rx buffer is 26 * 256 = 6656 bytes
23 #define ETH_RX_PAGE_STOP 0x60 // 0x6000
25 #define ETH_ADDR_PORT_MASK 0x1F // 00011111y
26 #define ETH_DATA_PORT_MASK 0xFF // 11111111y
28 #define ETH_MIN_PACKET_LEN 0x3C // 60 bytes
31 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data);
32 static unsigned char etherdev_reg_read(unsigned char reg);
34 // Manipulate PS1 & PS0 in CR to select RTL8019AS register page.
35 #define ETHERDEV_SELECT_REG_PAGE(page) \
38 etherdev_reg_write(CR, etherdev_reg_read(CR) & ~(PS1 | PS0)); \
39 etherdev_reg_write(CR, etherdev_reg_read(CR) | (page << 6)); \
43 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data)
45 // Select register address.
46 ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK;
49 // Output register data to port.
50 ETH_DATA_PORT = wr_data;
52 // Clock register data into RTL8019AS.
53 // IOR & IOW are both active low.
59 // Set register data port as input again.
60 ETH_DATA_PORT = ETH_DATA_PORT_MASK;
66 static unsigned char etherdev_reg_read(unsigned char reg)
68 unsigned char rd_data;
70 // Select register address.
71 ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK;
74 // Enable register data output from RTL8019AS.
78 // Read register data from port.
79 rd_data = ETH_DATA_PORT;
81 // Disable register data output from RTL8019AS.
93 Returns: 1 on success, 0 on failure.
94 Refer to National Semiconductor DP8390 App Note 874, July 1993.
97 bit etherdev_init(void)
99 // Set IOR & IOW as they're active low.
104 // Set register data port as input.
105 ETH_DATA_PORT = ETH_DATA_PORT_MASK;
107 // Configure RTL8019AS ethernet controller.
109 // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).
110 // That leaves plenty of time for the RTL8019AS to read it's
111 // configuration in from the 9346 EEPROM before we get here.
113 // Select RTL8019AS register page 0.
114 ETHERDEV_SELECT_REG_PAGE(0);
116 // Check if RTL8019AS fully reset.
117 if(!(etherdev_reg_read(ISR) & RST))
122 // Stop RTL8019AS, select page 0 and abort DMA operation.
123 etherdev_reg_write(CR, RD2 | STP);
125 // Initialise data configuration register.
126 // FIFO threshold 8 bytes, no loopback, don't use auto send packet.
127 etherdev_reg_write(DCR, FT1 | LS);
129 // Reset remote byte count registers.
130 etherdev_reg_write(RBCR0, 0x00);
131 etherdev_reg_write(RBCR1, 0x00);
133 // Receive configuration register to monitor mode.
134 etherdev_reg_write(RCR, MON);
136 // Initialise transmit configuration register to loopback internally.
137 etherdev_reg_write(TCR, LB0);
139 // Clear interrupt status register bits by writing 1 to each.
140 etherdev_reg_write(ISR, 0xFF);
142 // Mask all interrupts in mask register.
143 etherdev_reg_write(IMR, 0x00);
145 // Obtengo MAC de la placa
146 etherdev_reg_write(RBCR0, 0x0c); // Vamos a leer 12 bytes (2 x 6)
147 etherdev_reg_write(RBCR1, 0x00);
148 etherdev_reg_write(RSAR0, 0x00); // En la dirección 0x0000
149 etherdev_reg_write(RSAR1, 0x00);
150 etherdev_reg_write(CR, RD0 | STA); // Comienza lectura
151 uip_buf[6] = etherdev_reg_read(RDMA);
152 etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
153 uip_buf[7] = etherdev_reg_read(RDMA);
154 etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
155 uip_buf[8] = etherdev_reg_read(RDMA);
156 etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
157 uip_buf[9] = etherdev_reg_read(RDMA);
158 etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
159 uip_buf[10] = etherdev_reg_read(RDMA);
160 etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
161 uip_buf[11] = etherdev_reg_read(RDMA);
162 etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
164 // Wait until remote DMA operation completes.
165 while(!(etherdev_reg_read(ISR) & RDC)) continue;
167 // Abort/ complete DMA operation.
168 etherdev_reg_write(CR, RD2 | STP);
171 etherdev_reg_write(ISR, RDC);
173 // Set transmit page start.
174 etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
176 // Set receive buffer page start.
177 etherdev_reg_write(PSTART, ETH_RX_PAGE_START);
179 // Initialise last receive buffer read pointer.
180 etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
182 // Set receive buffer page stop.
183 etherdev_reg_write(PSTOP, ETH_RX_PAGE_STOP);
185 // Select RTL8019AS register page 1.
186 etherdev_reg_write(CR, RD2 | PS0 | STP);
188 // Initialise current packet receive buffer page pointer
189 etherdev_reg_write(CURR, ETH_RX_PAGE_START + 1);
191 // Set physical address
192 etherdev_reg_write(PAR0, uip_buf[0]);
193 etherdev_reg_write(PAR1, uip_buf[0]);
194 etherdev_reg_write(PAR2, uip_buf[0]);
195 etherdev_reg_write(PAR3, uip_buf[0]);
196 etherdev_reg_write(PAR4, uip_buf[0]);
197 etherdev_reg_write(PAR5, uip_buf[0]);
199 // Select RTL8019AS register page 0 and abort DMA operation.
200 etherdev_reg_write(CR, RD2 | STP);
202 // Restart RTL8019AS.
203 etherdev_reg_write(CR, RD2 | STA);
205 // Initialise transmit configuration register for normal operation.
206 etherdev_reg_write(TCR, 0x00);
208 // Receive configuration register to accept broadcast packets.
209 etherdev_reg_write(RCR, AB);
219 Send the packet in the uip_buf and uip_appdata buffers using the
220 RTL8019AS ethernet card.
223 void etherdev_send(void)
227 // Setup for DMA transfer from uip_buf & uip_appdata buffers to RTL8019AS.
229 // Select RTL8019AS register page 0 and abort DMA operation.
230 etherdev_reg_write(CR, RD2 | STA);
232 // Wait until pending transmit operation completes.
233 while(etherdev_reg_read(CR) & TXP) continue;
235 // Set remote DMA start address registers to indicate where to load packet.
236 etherdev_reg_write(RSAR0, 0x00);
237 etherdev_reg_write(RSAR1, ETH_TX_PAGE_START);
239 // Set remote DMA byte count registers to indicate length of packet load.
240 etherdev_reg_write(RBCR0, (unsigned char)(uip_len & 0xFF));
241 etherdev_reg_write(RBCR1, (unsigned char)(uip_len >> 8));
243 // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
244 etherdev_reg_write(CR, RD1 | STA);
246 // DMA transfer packet from uip_buf & uip_appdata to RTL8019AS local
247 // transmit buffer memory.
248 for(i = 0; i < uip_len; i++)
250 etherdev_reg_write(RDMA, uip_buf[i]);
253 // Wait until remote DMA operation complete.
254 while(!(etherdev_reg_read(ISR) & RDC)) continue;
256 // Clear remote DMA complete interrupt status register bit.
257 etherdev_reg_write(ISR, RDC);
259 // Abort/ complete DMA operation.
260 etherdev_reg_write(CR, RD2 | STA);
262 // Set transmit page start to indicate packet start.
263 etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
265 // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.
266 if(uip_len < ETH_MIN_PACKET_LEN)
268 uip_len = ETH_MIN_PACKET_LEN;
271 // Set transmit byte count registers to indicate packet length.
272 etherdev_reg_write(TBCR0, (unsigned char)(uip_len & 0xFF));
273 etherdev_reg_write(TBCR1, (unsigned char)(uip_len >> 8));
275 // Issue command for RTL8019AS to transmit packet from it's local buffer.
276 etherdev_reg_write(CR, RD2 | TXP | STA);
282 static void etherdev_reset()
284 bit retransmit = etherdev_reg_read(CR) & TXP;
286 // If the receive buffer ring has overflowed we dump the whole
287 // thing and start over. There is no way of knowing whether the
288 // data it contains is uncorrupted, or will cause us grief.
290 // Stop RTL8019AS and abort DMA operation.
291 etherdev_reg_write(CR, RD2 | STP);
293 // Wait for controller to halt after any current tx completes.
294 while(!(etherdev_reg_read(ISR) & RST)) continue;
296 // Reset remote byte count registers.
297 etherdev_reg_write(RBCR0, 0x00);
298 etherdev_reg_write(RBCR1, 0x00);
300 // Check whether currently transmitting a packet.
303 // If neither a successful transmission nor a tx abort error
304 // has occured, then flag current tx packet for resend.
305 if(etherdev_reg_read(ISR) & (PTX | TXE))
311 // Set transmit configuration register to loopback internally.
312 etherdev_reg_write(TCR, LB0);
314 // Restart the RTL8019AS.
315 etherdev_reg_write(CR, RD2 | STA);
317 // Re-initialise last receive buffer read pointer.
318 etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
320 // Select RTL8019AS register page 1.
321 ETHERDEV_SELECT_REG_PAGE(1);
323 // Re-initialise current packet receive buffer page pointer.
324 etherdev_reg_write(CURR, ETH_RX_PAGE_START + 1);
326 // Select RTL8019AS register page 0.
327 ETHERDEV_SELECT_REG_PAGE(0);
329 // Clear rx buffer overflow & packet received interrupt flags.
330 etherdev_reg_write(ISR, PRX | OVW);
332 // Re-itialise transmit configuration reg for normal operation.
333 etherdev_reg_write(TCR, 0x00);
337 // Retransmit packet in RTL8019AS local tx buffer.
338 etherdev_reg_write(CR, RD2 | TXP | STA);
343 unsigned int etherdev_read(void)
345 unsigned int len = 0;
347 // Check if the rx buffer has overflowed.
348 if (etherdev_reg_read(ISR) & OVW)
350 unsigned char current;
352 // Select RTL8019AS register page 1.
353 ETHERDEV_SELECT_REG_PAGE(1);
355 // Retrieve current receive buffer page
356 current = etherdev_reg_read(CURR);
358 // Select RTL8019AS register page 1.
359 ETHERDEV_SELECT_REG_PAGE(0);
361 if (etherdev_reg_read(BNRY) == current)
365 leds2 = ~etherdev_reg_read(ISR);
368 leds2 = ~etherdev_reg_read(BNRY);
377 // Check if there is a packet in the rx buffer.
378 else if (etherdev_reg_read(ISR) & PRX)
381 unsigned char next_rx_packet;
382 unsigned char current;
384 unsigned char status;
386 // Retrieve packet header. (status, next_ptr, length_l, length_h)
388 // Set remote DMA start address registers to packet header.
389 bnry = etherdev_reg_read(BNRY) + 1;
390 if (bnry >= ETH_RX_PAGE_STOP)
391 bnry = ETH_RX_PAGE_START;
392 etherdev_reg_write(RSAR0, 0x00);
393 etherdev_reg_write(RSAR1, bnry);
395 // Select RTL8019AS register page 1.
396 ETHERDEV_SELECT_REG_PAGE(1);
398 // Retrieve current receive buffer page
399 current = etherdev_reg_read(CURR);
401 // Select RTL8019AS register page 1.
402 ETHERDEV_SELECT_REG_PAGE(0);
404 // Check if last packet has been removed from rx buffer.
407 // Clear packet received interrupt flag.
408 etherdev_reg_write(ISR, PRX | RXE);
412 // Set remote DMA byte count registers to packet header length.
413 etherdev_reg_write(RBCR0, 0x04);
414 etherdev_reg_write(RBCR1, 0x00);
416 // Clear remote DMA complete interrupt status register bit.
417 etherdev_reg_write(ISR, RDC);
419 // Initiate DMA transfer of packet header.
420 etherdev_reg_write(CR, RD0 | STA);
423 status = etherdev_reg_read(RDMA);
425 // Save next packet pointer.
426 next_rx_packet = etherdev_reg_read(RDMA);
428 // Retrieve packet data length and subtract CRC bytes.
429 len = etherdev_reg_read(RDMA);
430 len += etherdev_reg_read(RDMA) << 8;
433 // Wait until remote DMA operation completes.
434 while(!(etherdev_reg_read(ISR) & RDC)) continue;
436 // Abort/ complete DMA operation.
437 etherdev_reg_write(CR, RD2 | STA);
440 etherdev_reg_write(ISR, RDC);
442 // Si es un paquete inválido, lo dropeamos
443 if (len < 60 || len > 1518)
449 // Si hubo un error, también lo dropeamos
450 if ((status & 0x0F) != RXSOK)
456 // Retrieve packet data.
458 // Check if incoming packet will fit into rx buffer.
459 if(len <= sizeof(uip_buf))
462 // Set remote DMA start address registers to packet data.
463 etherdev_reg_write(RSAR0, 0x04);
464 etherdev_reg_write(RSAR1, bnry);
466 // Set remote DMA byte count registers to packet data length.
467 etherdev_reg_write(RBCR0, (unsigned char)(len & 0xFF));
468 etherdev_reg_write(RBCR1, (unsigned char)(len >> 8));
470 // Initiate DMA transfer of packet data.
471 etherdev_reg_write(CR, RD0 | STA);
473 // Read packet data directly into uip_buf.
475 for(i = 0; i < 14; i++)
477 etherdev_reg_read(RDMA); // XXX descarto cabecera eth
479 for(i = 14; i < len; i++)
481 uip_buf[i] = etherdev_reg_read(RDMA); // XXX copio el resto
484 // Wait until remote DMA operation complete.
485 while(!(etherdev_reg_read(ISR) & RDC)) continue;
487 // Abort/ complete DMA operation.
488 etherdev_reg_write(CR, RD2 | STA);
490 // Clear remote DMA complete interrupt status register bit.
491 etherdev_reg_write(ISR, RDC);
496 // Incoming packet too big, so dump it.
501 // Advance boundary pointer to next packet start.
502 etherdev_reg_write(BNRY, next_rx_packet - 1);