1 // vim: set et sw=4 sts=4 :
7 void sleep(unsigned char);
9 static xdata at 0x0080 byte leds0;
10 static xdata at 0x00c0 byte leds1;
12 static byte xdata leds0 _at_ 0x0080;
13 static byte xdata leds1 _at_ 0x00c0;
17 /// Datos persistentes del módulo
20 byte send_len; ///> Tamaño del frame que será enviado
21 byte next_pkt; ///> Próximo frame a obtener
25 /// Cambia de página sin modificar los demás bits del CR
26 #define SELECT_REG_PAGE(page) \
29 write_reg(CR, read_reg(CR) & ~(PS1 | PS0)); \
30 write_reg(CR, read_reg(CR) | (page << 6)); \
34 /// Aborta (o completa) el DMA limpiando el ISR
35 #define ABORT_DMA(flags) \
38 write_reg(CR, flags); \
39 write_reg(ISR, RDC); \
44 static void write_reg(unsigned char reg, unsigned char wr_data)
46 // Select register address.
47 ADDR_PORT &= ~ADDR_PORT_MASK;
50 // Output register data to port.
53 // Clock register data into RTL8019AS.
54 // IOR & IOW are both active low.
60 // Set register data port as input again.
61 DATA_PORT = DATA_PORT_MASK;
65 static unsigned char read_reg(unsigned char reg)
67 // Select register address.
68 ADDR_PORT &= ~ADDR_PORT_MASK;
71 // Enable register data output from RTL8019AS.
75 // Read register data from port.
78 // Disable register data output from RTL8019AS.
85 /** Resetea placa de red en caso de buffer overflow */
88 bit retransmit = read_reg(CR) & TXP;
90 // If the receive buffer ring has overflowed we dump the whole
91 // thing and start over. There is no way of knowing whether the
92 // data it contains is uncorrupted, or will cause us grief.
94 // Stop RTL8019AS and abort DMA operation.
97 // Wait for controller to halt after any current tx completes.
98 while(!(read_reg(ISR) & RST)) continue;
100 // Reset remote byte count registers.
101 write_reg(RBCR0, 0x00);
102 write_reg(RBCR1, 0x00);
104 // Check whether currently transmitting a packet.
107 // If neither a successful transmission nor a tx abort error
108 // has occured, then flag current tx packet for resend.
109 if(read_reg(ISR) & (PTX | TXE))
115 // Set transmit configuration register to loopback internally.
116 write_reg(TCR, MODE1);
118 // Restart the RTL8019AS.
119 write_reg(CR, START);
121 // Re-initialise last receive buffer read pointer.
122 write_reg(BNRY, RX_PAGE_START);
124 // Select RTL8019AS register page 1.
127 // Re-initialise current packet receive buffer page pointer.
128 write_reg(CURR, RX_PAGE_START + 1);
130 // Select RTL8019AS register page 0.
133 // Clear rx buffer overflow & packet received interrupt flags.
134 write_reg(ISR, PRX | OVW);
136 // Re-itialise transmit configuration reg for normal operation.
137 write_reg(TCR, MODE0);
141 // Retransmit packet in RTL8019AS local tx buffer.
142 write_reg(CR, START | TXP);
147 /** Inicializa dispositivo de red
148 * @return true si se inicializó correctamente, false si no
152 // Set IOR & IOW as they're active low.
157 // Set register data port as input.
158 DATA_PORT = DATA_PORT_MASK;
160 // Configure RTL8019AS ethernet controller.
162 // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).
163 // That leaves plenty of time for the RTL8019AS to read it's
164 // configuration in from the 9346 EEPROM before we get here.
166 // Select RTL8019AS register page 0.
169 // Check if RTL8019AS fully reset.
170 if(!(read_reg(ISR) & RST))
175 // Stop RTL8019AS, select page 0 and abort DMA operation.
178 // Initialise data configuration register.
179 // FIFO threshold 8 bytes, no loopback, don't use auto send packet.
180 write_reg(DCR, FT1 | LS);
182 // Reset remote byte count registers.
183 write_reg(RBCR0, 0u);
184 write_reg(RBCR1, 0u);
186 // Receive configuration register to monitor mode.
189 // Initialise transmit configuration register to loopback internally.
190 write_reg(TCR, MODE1);
192 // Clear interrupt status register bits by writing 1 to each.
195 // Mask all interrupts in mask register.
196 write_reg(IMR, NONE);
198 // Obtengo MAC de la placa
199 write_reg(RBCR0, 12u); // Vamos a leer 12 bytes (2 x 6)
200 write_reg(RBCR1, 0u);
201 write_reg(RSAR0, 0u); // En la dirección 0x0000
202 write_reg(RSAR1, 0u);
203 write_reg(CR, READ); // Comienza lectura
204 eth_addr_local[0] = read_reg(RDMA);
205 read_reg(RDMA); // Ignoramos porque viene como un word
206 eth_addr_local[1] = read_reg(RDMA);
207 read_reg(RDMA); // Ignoramos porque viene como un word
208 eth_addr_local[2] = read_reg(RDMA);
209 read_reg(RDMA); // Ignoramos porque viene como un word
210 eth_addr_local[3] = read_reg(RDMA);
211 read_reg(RDMA); // Ignoramos porque viene como un word
212 eth_addr_local[4] = read_reg(RDMA);
213 read_reg(RDMA); // Ignoramos porque viene como un word
214 eth_addr_local[5] = read_reg(RDMA);
215 read_reg(RDMA); // Ignoramos porque viene como un word
217 // Abort/ complete DMA operation.
220 // Set transmit page start.
221 write_reg(TPSR, TX_PAGE_START);
223 // Set receive buffer page start.
224 write_reg(PSTART, RX_PAGE_START);
226 // Initialise last receive buffer read pointer.
227 write_reg(BNRY, RX_PAGE_START);
229 // Set receive buffer page stop.
230 write_reg(PSTOP, RX_PAGE_STOP);
232 // Select RTL8019AS register page 1.
235 // Initialise current packet receive buffer page pointer
236 write_reg(CURR, RX_PAGE_START + 1);
238 // Set physical address
239 write_reg(PAR0, eth_addr_local[0]);
240 write_reg(PAR1, eth_addr_local[1]);
241 write_reg(PAR2, eth_addr_local[2]);
242 write_reg(PAR3, eth_addr_local[3]);
243 write_reg(PAR4, eth_addr_local[4]);
244 write_reg(PAR5, eth_addr_local[5]);
246 // Restart RTL8019AS.
247 write_reg(CR, START);
249 // Initialise transmit configuration register for normal operation.
250 write_reg(TCR, MODE0);
252 // Receive configuration register to accept broadcast packets.
259 /** Comienza el envío de un nuevo frame
260 * @param len Tamaño del frame a enviar
262 void netdev_send_start()
264 persistent.send_len = 0;
265 // Wait until pending transmit operation completes.
266 while(read_reg(CR) & TXP) continue;
268 // Set remote DMA start address registers to indicate where to load packet.
269 write_reg(RSAR0, 0u);
270 write_reg(RSAR1, TX_PAGE_START);
272 // Set remote DMA byte count registers to indicate length of packet load.
273 write_reg(RBCR0, MAX_PACKET_LEN); // Tamaño máximo en principio
274 write_reg(RBCR1, 0u);
276 // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
277 write_reg(CR, WRITE | STA);
280 /** Escribe un byte al buffer de la placa de red para ser enviado
281 * @precond netdev_send_start() debe haber sido ejecutada
282 * @param b Byte a enviar
284 void netdev_send_byte(byte b)
286 persistent.send_len++;
290 /** Escribe un word al buffer de la placa de red para ser enviado
291 * @precond netdev_send_start() debe haber sido ejecutada
292 * @param w Word a enviar
294 void netdev_send_word(uint16 w)
296 persistent.send_len += 2;
297 write_reg(RDMA, HIGH(w));
298 write_reg(RDMA, LOW(w));
301 /** Finaliza el envío del frame
302 * @precond netdev_send_start() debe haber sido ejecutada
304 void netdev_send_end()
306 // Abort/ complete DMA operation.
309 // Set transmit page start to indicate packet start.
310 write_reg(TPSR, TX_PAGE_START);
312 // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.
313 if (persistent.send_len < MIN_PACKET_LEN)
315 persistent.send_len = MIN_PACKET_LEN;
318 // Set transmit byte count registers to indicate packet length.
319 write_reg(TBCR0, LOW(persistent.send_len));
320 write_reg(TBCR1, 0u);
322 // Issue command for RTL8019AS to transmit packet from it's local buffer.
323 write_reg(CR, START | TXP);
326 /** Comienza la lectura de un nuevo frame
327 * @return Cantidad de bytes del frame leído
329 byte netdev_recv_start()
331 // Check if the rx buffer has overflowed.
332 if (read_reg(ISR) & OVW)
336 // Select RTL8019AS register page 1.
339 // Retrieve current receive buffer page
340 current = read_reg(CURR);
342 // Select RTL8019AS register page 1.
345 if (read_reg(BNRY) == current)
349 leds2 = ~read_reg(ISR);
352 leds2 = ~read_reg(BNRY);
362 // Check if there is a packet in the rx buffer.
363 else if (read_reg(ISR) & PRX)
367 byte status; // Estado del frame recibido
368 byte next; // Offset del próximo frame
369 uint16 len; // Tamaño del frame
375 // Retrieve packet header. (status, next_ptr, length_l, length_h)
377 // Set remote DMA start address registers to packet header.
378 bnry = read_reg(BNRY) + 1;
379 if (bnry >= RX_PAGE_STOP)
380 bnry = RX_PAGE_START;
381 write_reg(RSAR0, 0u);
382 write_reg(RSAR1, bnry);
384 // Select RTL8019AS register page 1.
387 // Retrieve current receive buffer page
388 current = read_reg(CURR);
390 // Select RTL8019AS register page 1.
393 // Check if last packet has been removed from rx buffer.
396 // Clear packet received interrupt flag.
397 write_reg(ISR, PRX | RXE);
401 // Set remote DMA byte count registers to packet header length.
402 write_reg(RBCR0, sizeof(struct buf_hdr_t));
403 write_reg(RBCR1, 0u);
405 // Clear remote DMA complete interrupt status register bit.
408 // Initiate DMA transfer of packet header.
412 buf_hdr.status = read_reg(RDMA);
414 // Save next packet pointer.
415 buf_hdr.next = persistent.next_pkt = read_reg(RDMA);
417 // Retrieve packet data length and subtract CRC bytes.
418 buf_hdr.len = read_reg(RDMA) - sizeof(struct buf_hdr_t);
420 // Si es muy grande, muy chico o hubo error, lo descartamos
421 if ((buf_hdr.len < MIN_PACKET_LEN) || (buf_hdr.len > MAX_PACKET_LEN)
422 || ((buf_hdr.status & 0x0F) != RXSOK)
423 || read_reg(RDMA)) // Parte alta del tamaño
425 ABORT_DMA(START); // Termina DMA
426 write_reg(BNRY, buf_hdr.next - 1); // Pasa al próximo frame
430 // Abort/ complete DMA operation.
433 // Set remote DMA start address registers to packet data.
434 write_reg(RSAR0, sizeof(struct buf_hdr_t));
435 write_reg(RSAR1, bnry);
437 // Set remote DMA byte count registers to packet data length.
438 write_reg(RBCR0, buf_hdr.len);
439 write_reg(RBCR1, 0u);
441 // Initiate DMA transfer of packet data.
449 /** Lee un byte del buffer de la placa de red
450 * @precond netdev_recv_start() debe haber sido ejecutada
452 byte netdev_recv_byte()
454 return read_reg(RDMA);
457 /** Lee un word del buffer de la placa de red
458 * @precond netdev_recv_start() debe haber sido ejecutada
460 uint16 netdev_recv_word()
462 uint16 w = netdev_recv_byte() << 8;
463 return w + netdev_recv_byte();
466 /** Finaliza la lectura del frame
467 * @precond netdev_recv_start() debe haber sido ejecutada
469 void netdev_recv_end()
471 // Abort/ complete DMA operation.
474 // Advance boundary pointer to next packet start.
475 write_reg(BNRY, persistent.next_pkt - 1);