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 #define ETH_CPU_CLOCK ETH_CPU_XTAL / 12 // 8051 clock rate (X1 mode)
22 // Delay routine timing parameters
23 #define ETH_DELAY_CONST 9.114584e-5 // Delay routine constant
24 #define ETH_DELAY_MULTPLR (unsigned char)(ETH_DELAY_CONST * ETH_CPU_CLOCK)
26 // X1 CPU mode timing parameters
27 #define ETH_T0_CLOCK ETH_CPU_XTAL / 12 // Timer 0 mode 1 clock rate
28 #define ETH_T0_INT_RATE 24 // Timer 0 intrupt rate (Hz)
29 #define ETH_T0_RELOAD 65536 - (ETH_T0_CLOCK / ETH_T0_INT_RATE)
31 // Packet transmit & receive buffer configuration
32 #define ETH_TX_PAGE_START 0x40 // 0x4000 Tx buffer is 6 * 256 = 1536 bytes
33 #define ETH_RX_PAGE_START 0x46 // 0x4600 Rx buffer is 26 * 256 = 6656 bytes
34 #define ETH_RX_PAGE_STOP 0x60 // 0x6000
36 #define ETH_ADDR_PORT_MASK 0x1F // 00011111y
37 #define ETH_DATA_PORT_MASK 0xFF // 11111111y
39 #define ETH_MIN_PACKET_LEN 0x3C
42 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data);
43 static unsigned char etherdev_reg_read(unsigned char reg);
44 static void etherdev_delay_ms(unsigned int count);
45 static unsigned int etherdev_poll(void);
47 // Manipulate PS1 & PS0 in CR to select RTL8019AS register page.
48 #define ETHERDEV_SELECT_REG_PAGE(page) \
51 etherdev_reg_write(CR, etherdev_reg_read(CR) & ~(PS1 | PS0)); \
52 etherdev_reg_write(CR, etherdev_reg_read(CR) | (page << 6)); \
55 static unsigned char tick_count = 0;
58 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data)
60 // Select register address.
61 ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK;
64 // Output register data to port.
65 ETH_DATA_PORT = wr_data;
67 // Clock register data into RTL8019AS.
68 // IOR & IOW are both active low.
74 // Set register data port as input again.
75 ETH_DATA_PORT = ETH_DATA_PORT_MASK;
81 static unsigned char etherdev_reg_read(unsigned char reg)
83 unsigned char rd_data;
85 // Select register address.
86 ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK;
89 // Enable register data output from RTL8019AS.
93 // Read register data from port.
94 rd_data = ETH_DATA_PORT;
96 // Disable register data output from RTL8019AS.
106 etherdev_timer0_isr()
108 This function is invoked each 1/24th of a second and updates a
109 1/24th of a second tick counter.
112 static void etherdev_timer0_isr(void) interrupt 1 using 1
114 // Reload timer/ counter 0 for 24Hz periodic interrupt.
115 TH0 = ETH_T0_RELOAD >> 8;
118 // Increment 24ths of a second counter.
129 Returns: 1 on success, 0 on failure.
130 Refer to National Semiconductor DP8390 App Note 874, July 1993.
133 bit etherdev_init(void)
135 // Set IOR & IOW as they're active low.
140 // Set register data port as input.
141 ETH_DATA_PORT = ETH_DATA_PORT_MASK;
143 // Configure RTL8019AS ethernet controller.
145 // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).
146 // That leaves plenty of time for the RTL8019AS to read it's
147 // configuration in from the 9346 EEPROM before we get here.
149 // Select RTL8019AS register page 0.
150 ETHERDEV_SELECT_REG_PAGE(0);
152 // Check if RTL8019AS fully reset.
153 if(!(etherdev_reg_read(ISR) & RST))
158 // Select RTL8019AS register page 0.
159 ETHERDEV_SELECT_REG_PAGE(0);
161 // Stop RTL8019AS, select page 0 and abort DMA operation.
162 etherdev_reg_write(CR, RD2 | STP);
164 // Initialise data configuration register.
165 // FIFO threshold 8 bytes, no loopback, don't use auto send packet.
166 etherdev_reg_write(DCR, FT1 | LS);
168 // Reset remote byte count registers.
169 etherdev_reg_write(RBCR0, 0x00);
170 etherdev_reg_write(RBCR1, 0x00);
172 // Receive configuration register to monitor mode.
173 etherdev_reg_write(RCR, MON);
175 // Initialise transmit configuration register to loopback internally.
176 etherdev_reg_write(TCR, LB0);
178 // Clear interrupt status register bits by writing 1 to each.
179 etherdev_reg_write(ISR, 0xFF);
181 // Mask all interrupts in mask register.
182 etherdev_reg_write(IMR, 0x00);
184 // TODO Obtengo MAC de la placa
185 //etherdev_reg_write(CR, 0x21);
187 // Set transmit page start.
188 etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
190 // Set receive buffer page start.
191 etherdev_reg_write(PSTART, ETH_RX_PAGE_START);
193 // Initialise last receive buffer read pointer.
194 etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
196 // Set receive buffer page stop.
197 etherdev_reg_write(PSTOP, ETH_RX_PAGE_STOP);
199 // Select RTL8019AS register page 1.
200 etherdev_reg_write(CR, RD2 | PS0 | STP);
202 // Initialise current packet receive buffer page pointer
203 etherdev_reg_write(CURR, ETH_RX_PAGE_START+1);
205 // Set physical address
206 etherdev_reg_write(PAR0, 0x00);
207 etherdev_reg_write(PAR1, 0x0c);
208 etherdev_reg_write(PAR2, 0x6e);
209 etherdev_reg_write(PAR3, 0x37);
210 etherdev_reg_write(PAR4, 0x19);
211 etherdev_reg_write(PAR5, 0xbe);
213 // Select RTL8019AS register page 0 and abort DMA operation.
214 etherdev_reg_write(CR, RD2 | STP);
216 // Restart RTL8019AS.
217 etherdev_reg_write(CR, RD2 | STA);
219 // Initialise transmit configuration register for normal operation.
220 etherdev_reg_write(TCR, 0x00);
222 // Receive configuration register to accept broadcast packets.
223 etherdev_reg_write(RCR, AB);
226 // Initialize Timer 0 to generate a periodic 24Hz interrupt.
228 // Stop timer/ counter 0.
231 // Set timer/ counter 0 as mode 1 16 bit timer.
235 // Preload for 24Hz periodic interrupt.
236 TH0 = ETH_T0_RELOAD >> 8;
239 // Restart timer/ counter 0 running.
242 // Enable timer/ counter 0 overflow interrupt.
245 // Enable global interrupt.
256 Send the packet in the uip_buf and uip_appdata buffers using the
257 RTL8019AS ethernet card.
260 void etherdev_send(void)
264 // Setup for DMA transfer from uip_buf & uip_appdata buffers to RTL8019AS.
266 // Select RTL8019AS register page 0 and abort DMA operation.
267 etherdev_reg_write(CR, RD2 | STA);
269 // Wait until pending transmit operation completes.
270 while(etherdev_reg_read(CR) & TXP) continue;
272 // Set remote DMA start address registers to indicate where to load packet.
273 etherdev_reg_write(RSAR0, 0x00);
274 etherdev_reg_write(RSAR1, ETH_TX_PAGE_START);
276 // Set remote DMA byte count registers to indicate length of packet load.
277 etherdev_reg_write(RBCR0, (unsigned char)(uip_len & 0xFF));
278 etherdev_reg_write(RBCR1, (unsigned char)(uip_len >> 8));
280 // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
281 etherdev_reg_write(CR, RD1 | STA);
283 // DMA transfer packet from uip_buf & uip_appdata to RTL8019AS local
284 // transmit buffer memory.
285 for(i = 0; i < uip_len; i++)
287 etherdev_reg_write(RDMA, uip_buf[i]);
290 // Wait until remote DMA operation complete.
291 while(!(etherdev_reg_read(ISR) & RDC)) continue;
293 // Clear remote DMA complete interrupt status register bit.
294 etherdev_reg_write(ISR, RDC);
296 // Abort/ complete DMA operation.
297 etherdev_reg_write(CR, RD2 | STA);
299 // Set transmit page start to indicate packet start.
300 etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
302 // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.
303 if(uip_len < ETH_MIN_PACKET_LEN)
305 uip_len = ETH_MIN_PACKET_LEN;
308 // Set transmit byte count registers to indicate packet length.
309 etherdev_reg_write(TBCR0, (unsigned char)(uip_len & 0xFF));
310 etherdev_reg_write(TBCR1, (unsigned char)(uip_len >> 8));
312 // Issue command for RTL8019AS to transmit packet from it's local buffer.
313 etherdev_reg_write(CR, RD2 | TXP | STA);
323 This function will read an entire IP packet into the uip_buf.
324 If it must wait for more than 0.5 seconds, it will return with
325 the return value 0. Otherwise, when a full packet has been read
326 into the uip_buf buffer, the length of the packet is returned.
329 unsigned int etherdev_read(void)
331 unsigned int bytes_read;
333 /* tick_count threshold should be 12 for 0.5 sec bail-out
334 One second (24) worked better for me, but socket recycling
335 is then slower. I set UIP_TIME_WAIT_TIMEOUT 60 in uipopt.h
336 to counter this. Retransmission timing etc. is affected also. */
337 while ((!(bytes_read = etherdev_poll())) && (tick_count < 12)) continue;
349 Poll the RTL8019AS ethernet device for an available packet.
352 static unsigned int etherdev_poll(void)
354 unsigned int len = 0;
357 leds2 = ~etherdev_reg_read(ISR);
360 if(etherdev_reg_read(ISR) & OVW)
363 leds2 = ~etherdev_reg_read(BNRY);
366 leds2 = ~etherdev_reg_read(CURR);
370 // Check if there is a packet in the rx buffer.
371 if(etherdev_reg_read(ISR) & PRX)
373 // Check if the rx buffer has overflowed.
374 if(etherdev_reg_read(ISR) & OVW)
378 // If the receive buffer ring has overflowed we dump the whole
379 // thing and start over. There is no way of knowing whether the
380 // data it contains is uncorrupted, or will cause us grief.
382 // Stop RTL8019AS and abort DMA operation.
383 etherdev_reg_write(CR, RD2 | STP);
385 // Reset remote byte count registers.
386 etherdev_reg_write(RBCR0, 0x00);
387 etherdev_reg_write(RBCR1, 0x00);
389 // Wait for controller to halt after any current tx completes.
390 while(!(etherdev_reg_read(ISR) & RST)) continue;
392 // Check whether currently transmitting a packet.
393 if(etherdev_reg_read(CR) & TXP)
395 // If neither a successful transmission nor a tx abort error
396 // has occured, then flag current tx packet for resend.
397 if(!((etherdev_reg_read(ISR) & PTX)
398 || (etherdev_reg_read(ISR) & TXE)))
404 // Set transmit configuration register to loopback internally.
405 etherdev_reg_write(TCR, LB0);
407 // Restart the RTL8019AS.
408 etherdev_reg_write(CR, RD2 | STA);
410 // Re-initialise last receive buffer read pointer.
411 etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
413 // Select RTL8019AS register page 1.
414 ETHERDEV_SELECT_REG_PAGE(1);
416 // Re-initialise current packet receive buffer page pointer.
417 etherdev_reg_write(CURR, ETH_RX_PAGE_START+1);
419 // Select RTL8019AS register page 0.
420 ETHERDEV_SELECT_REG_PAGE(0);
422 // Clear rx buffer overflow & packet received interrupt flags.
423 etherdev_reg_write(ISR, PRX | OVW);
425 // Re-itialise transmit configuration reg for normal operation.
426 etherdev_reg_write(TCR, 0x00);
430 // Retransmit packet in RTL8019AS local tx buffer.
431 etherdev_reg_write(CR, RD2 | TXP | STA);
434 else // Rx buffer has not overflowed, so read a packet into uip_buf.
437 unsigned char next_rx_packet;
438 unsigned char current;
440 unsigned char status;
442 // Retrieve packet header. (status, next_ptr, length_l, length_h)
444 // Set remote DMA start address registers to packet header.
445 bnry = etherdev_reg_read(BNRY) + 1;
446 if (bnry >= ETH_RX_PAGE_STOP)
447 bnry = ETH_RX_PAGE_START;
448 etherdev_reg_write(RSAR0, 0x00);
449 etherdev_reg_write(RSAR1, bnry);
451 // Select RTL8019AS register page 1.
452 ETHERDEV_SELECT_REG_PAGE(1);
454 // Retrieve current receive buffer page
455 current = etherdev_reg_read(CURR);
457 // Select RTL8019AS register page 1.
458 ETHERDEV_SELECT_REG_PAGE(0);
460 // Check if last packet has been removed from rx buffer.
463 // Clear packet received interrupt flag.
464 etherdev_reg_write(ISR, PRX);
468 // Set remote DMA byte count registers to packet header length.
469 etherdev_reg_write(RBCR0, 0x04);
470 etherdev_reg_write(RBCR1, 0x00);
472 // Clear remote DMA complete interrupt status register bit.
473 etherdev_reg_write(ISR, RDC);
475 // Initiate DMA transfer of packet header.
476 etherdev_reg_write(CR, RD0 | STA);
479 status = etherdev_reg_read(RDMA);
481 // Save next packet pointer.
482 next_rx_packet = etherdev_reg_read(RDMA);
484 // Retrieve packet data length and subtract CRC bytes.
485 len = etherdev_reg_read(RDMA);
486 len += etherdev_reg_read(RDMA) << 8;
489 // Wait until remote DMA operation completes.
490 while(!(etherdev_reg_read(ISR) & RDC)) continue;
492 // Abort/ complete DMA operation.
493 etherdev_reg_write(CR, RD2 | STA);
496 etherdev_reg_write(ISR, RDC);
498 if (len < 60 || len > 1518) // XXX DROP!!!
505 if ((status & 0x0F) != RXSOK) // XXX DROP!!!
512 // Retrieve packet data.
514 // Check if incoming packet will fit into rx buffer.
515 if(len <= sizeof(uip_buf))
518 // Set remote DMA start address registers to packet data.
519 etherdev_reg_write(RSAR0, 0x04);
520 etherdev_reg_write(RSAR1, bnry);
522 // Set remote DMA byte count registers to packet data length.
523 etherdev_reg_write(RBCR0, (unsigned char)(len & 0xFF));
524 etherdev_reg_write(RBCR1, (unsigned char)(len >> 8));
526 // Initiate DMA transfer of packet data.
527 etherdev_reg_write(CR, RD0 | STA);
529 // Read packet data directly into uip_buf.
531 for(i = 0; i < 14; i++)
533 etherdev_reg_read(RDMA); // XXX descarto cabecera eth
535 for(i = 14; i < len; i++)
537 uip_buf[i] = etherdev_reg_read(RDMA); // XXX copio el resto
540 // Wait until remote DMA operation complete.
541 while(!(etherdev_reg_read(ISR) & RDC)) continue;
543 // Abort/ complete DMA operation.
544 etherdev_reg_write(CR, RD2 | STA);
546 // Clear remote DMA complete interrupt status register bit.
547 etherdev_reg_write(ISR, RDC);
552 // Incoming packet too big, so dump it.
556 // Advance boundary pointer to next packet start.
557 etherdev_reg_write(BNRY, next_rx_packet - 1);
559 // Select RTL8019AS register page 0.
560 ETHERDEV_SELECT_REG_PAGE(0);