1 // vim: set et sw=4 sts=4 :
7 /** Tamaño del frame */
10 // Próximo frame a obtener
19 /// Tamaño de la cabecera de los buffers de la placa de red
20 #define BUF_HDR_SIZE 4
22 /// Cambia de página sin modificar los demás bits del CR
23 #define SELECT_REG_PAGE(page) \
26 write_reg(CR, read_reg(CR) & ~(PS1 | PS0)); \
27 write_reg(CR, read_reg(CR) | (page << 6)); \
31 /// Aborta (o completa) el DMA limpiando el ISR
32 #define ABORT_DMA(flags) \
35 write_reg(CR, flags); \
36 write_reg(ISR, RDC); \
41 static void write_reg(unsigned char reg, unsigned char wr_data)
43 // Select register address.
44 ADDR_PORT &= ~ADDR_PORT_MASK;
47 // Output register data to port.
50 // Clock register data into RTL8019AS.
51 // IOR & IOW are both active low.
57 // Set register data port as input again.
58 DATA_PORT = DATA_PORT_MASK;
62 static unsigned char read_reg(unsigned char reg)
64 // Select register address.
65 ADDR_PORT &= ~ADDR_PORT_MASK;
68 // Enable register data output from RTL8019AS.
72 // Read register data from port.
75 // Disable register data output from RTL8019AS.
82 /** Resetea placa de red en caso de buffer overflow */
85 bit retransmit = read_reg(CR) & TXP;
87 // If the receive buffer ring has overflowed we dump the whole
88 // thing and start over. There is no way of knowing whether the
89 // data it contains is uncorrupted, or will cause us grief.
91 // Stop RTL8019AS and abort DMA operation.
94 // Wait for controller to halt after any current tx completes.
95 while(!(read_reg(ISR) & RST)) continue;
97 // Reset remote byte count registers.
98 write_reg(RBCR0, 0x00);
99 write_reg(RBCR1, 0x00);
101 // Check whether currently transmitting a packet.
104 // If neither a successful transmission nor a tx abort error
105 // has occured, then flag current tx packet for resend.
106 if(read_reg(ISR) & (PTX | TXE))
112 // Set transmit configuration register to loopback internally.
113 write_reg(TCR, MODE1);
115 // Restart the RTL8019AS.
116 write_reg(CR, START);
118 // Re-initialise last receive buffer read pointer.
119 write_reg(BNRY, RX_PAGE_START);
121 // Select RTL8019AS register page 1.
124 // Re-initialise current packet receive buffer page pointer.
125 write_reg(CURR, RX_PAGE_START + 1);
127 // Select RTL8019AS register page 0.
130 // Clear rx buffer overflow & packet received interrupt flags.
131 write_reg(ISR, PRX | OVW);
133 // Re-itialise transmit configuration reg for normal operation.
134 write_reg(TCR, MODE0);
138 // Retransmit packet in RTL8019AS local tx buffer.
139 write_reg(CR, START | TXP);
144 /** Inicializa dispositivo de red
145 * @return true si se inicializó correctamente, false si no
151 // Set IOR & IOW as they're active low.
156 // Set register data port as input.
157 DATA_PORT = DATA_PORT_MASK;
159 // Configure RTL8019AS ethernet controller.
161 // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).
162 // That leaves plenty of time for the RTL8019AS to read it's
163 // configuration in from the 9346 EEPROM before we get here.
165 // Select RTL8019AS register page 0.
168 // Check if RTL8019AS fully reset.
169 if(!(read_reg(ISR) & RST))
174 // Stop RTL8019AS, select page 0 and abort DMA operation.
177 // Initialise data configuration register.
178 // FIFO threshold 8 bytes, no loopback, don't use auto send packet.
179 write_reg(DCR, FT1 | LS);
181 // Reset remote byte count registers.
182 write_reg(RBCR0, 0u);
183 write_reg(RBCR1, 0u);
185 // Receive configuration register to monitor mode.
188 // Initialise transmit configuration register to loopback internally.
189 write_reg(TCR, MODE1);
191 // Clear interrupt status register bits by writing 1 to each.
194 // Mask all interrupts in mask register.
195 write_reg(IMR, NONE);
197 // Obtengo MAC de la placa
198 write_reg(RBCR0, 12u); // Vamos a leer 12 bytes (2 x 6)
199 write_reg(RBCR1, 0u);
200 write_reg(RSAR0, 0u); // En la dirección 0x0000
201 write_reg(RSAR1, 0u);
202 write_reg(CR, READ); // Comienza lectura
203 for (i = 0; i < ETH_ADDR_SIZE; ++i)
205 eth_addr_local[i] = read_reg(RDMA);
206 read_reg(RDMA); // Ignoramos porque viene como un word
209 // Abort/ complete DMA operation.
212 // Set transmit page start.
213 write_reg(TPSR, TX_PAGE_START);
215 // Set receive buffer page start.
216 write_reg(PSTART, RX_PAGE_START);
218 // Initialise last receive buffer read pointer.
219 write_reg(BNRY, RX_PAGE_START);
221 // Set receive buffer page stop.
222 write_reg(PSTOP, RX_PAGE_STOP);
224 // Select RTL8019AS register page 1.
227 // Initialise current packet receive buffer page pointer
228 write_reg(CURR, RX_PAGE_START + 1);
230 // Set physical address
231 for (i = 0; i < ETH_ADDR_SIZE; ++i)
232 write_reg(PAR_BASE + i, eth_addr_local[i]);
234 // Restart RTL8019AS.
235 write_reg(CR, START);
237 // Initialise transmit configuration register for normal operation.
238 write_reg(TCR, MODE0);
240 // Receive configuration register to accept broadcast packets.
247 /** Comienza el envío de un nuevo frame */
248 void netdev_send_start()
250 // Wait until pending transmit operation completes.
251 while (read_reg(CR) & TXP) continue;
252 write_reg(ISR, PTX); // Limpio bit de interrupción
254 // Set remote DMA start address registers to indicate where to load packet.
255 write_reg(RSAR0, 0u);
256 write_reg(RSAR1, TX_PAGE_START);
259 /** Finaliza el envío del frame
260 * @precond netdev_send_start() debe haber sido ejecutada
261 * @precond se copiaron datos al dispositivo para enviar
262 * @param len Cantidad de bytes a transmitir
264 void netdev_send_end(byte len)
266 // Set transmit page start to indicate packet start.
267 write_reg(TPSR, TX_PAGE_START);
269 // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.
270 if (len < MIN_PACKET_LEN)
271 len = MIN_PACKET_LEN;
273 // Set transmit byte count registers to indicate packet length.
274 write_reg(TBCR0, len);
275 write_reg(TBCR1, 0u);
277 // Issue command for RTL8019AS to transmit packet from it's local buffer.
278 write_reg(CR, START | TXP);
281 void netdev_write_start(byte len)
283 // Set remote DMA byte count registers to indicate length of packet load.
284 write_reg(RBCR0, len);
285 write_reg(RBCR1, 0u);
287 // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
288 write_reg(CR, WRITE);
291 void netdev_write_start_at(byte offset, byte len)
293 // Set remote DMA start address registers to packet data.
294 write_reg(RSAR0, offset);
295 write_reg(RSAR1, TX_PAGE_START);
297 // Set remote DMA byte count registers to indicate length of packet load.
298 write_reg(RBCR0, len);
299 write_reg(RBCR1, 0u);
301 // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
302 write_reg(CR, WRITE);
305 /** Escribe un byte al buffer de la placa de red para ser enviado
306 * @precond netdev_send_start() debe haber sido ejecutada
307 * @param b Byte a enviar
309 void netdev_write_byte(byte b)
314 /** Escribe un word al buffer de la placa de red para ser enviado
315 * @precond netdev_send_start() debe haber sido ejecutada
316 * @param w Word a enviar
318 void netdev_write_word(uint16 w)
320 write_reg(RDMA, HIGH(w));
321 write_reg(RDMA, LOW(w));
324 void netdev_write_end()
326 // Abort/ complete DMA operation.
330 /** Comienza la lectura de un nuevo frame
331 * @return Cantidad de bytes a recibir
333 byte netdev_recv_start()
335 // Check if the rx buffer has overflowed.
336 if (read_reg(ISR) & OVW)
341 current = read_reg(CURR);
344 // Hack: a veces reporta mal el flag de OVW, así que verificamos que
345 // relamente haya habido overflow.
346 if (read_reg(BNRY) == current)
348 printb(read_reg(ISR), 0x01);
349 printb(read_reg(BNRY), 0x02);
350 printb(current, 0x04);
356 // Check if there is a packet in the rx buffer.
357 else if (read_reg(ISR) & PRX)
363 // Retrieve packet header. (status, next_ptr, length_l, length_h)
365 // Obtiene el buffer a leer actualmente
366 recv_state.curr_buf = read_reg(BNRY) + 1;
367 if (recv_state.curr_buf >= RX_PAGE_STOP)
368 recv_state.curr_buf = RX_PAGE_START;
370 // Select RTL8019AS register page 1.
373 // Retrieve current receive buffer page
374 current = read_reg(CURR);
376 // Select RTL8019AS register page 1.
379 // Check if last packet has been removed from rx buffer.
380 if(recv_state.curr_buf == current)
382 // Clear packet received interrupt flag.
383 write_reg(ISR, PRX | RXE);
387 // Set remote DMA byte count registers to packet header length.
388 recv_state.curr_off = 0;
389 netdev_read_start(BUF_HDR_SIZE);
392 status = netdev_read_byte();
394 // Save next packet pointer.
395 recv_state.next_buf = netdev_read_byte() - 1;
397 // Retrieve packet data length and subtract CRC bytes.
398 len = netdev_read_byte() - BUF_HDR_SIZE;
400 // Si es muy grande, muy chico o hubo error, lo descartamos
401 if ((len < MIN_PACKET_LEN) || (len > MAX_PACKET_LEN)
402 || ((status & 0x0F) != RXSOK)
403 || netdev_read_byte()) // Parte alta del tamaño
405 // Terminamos DMA y pasamos al próximo frame
407 write_reg(BNRY, recv_state.next_buf);
411 // Abort/ complete DMA operation.
420 /** Finaliza la recepción del frame
421 * @precond netdev_recv_start() debe haber sido ejecutada
423 void netdev_recv_end()
425 // Pasa el próximo frame
426 write_reg(BNRY, recv_state.next_buf);
429 void netdev_read_start(byte len)
431 // Set remote DMA start address registers to packet data.
432 write_reg(RSAR0, recv_state.curr_off);
433 write_reg(RSAR1, recv_state.curr_buf);
434 recv_state.curr_off += len;
436 // Set remote DMA byte count registers to packet data length.
437 write_reg(RBCR0, len);
440 // Initiate DMA transfer of packet data.
444 /** Lee un byte del buffer de la placa de red
445 * @precond netdev_recv_start() debe haber sido ejecutada
447 byte netdev_read_byte()
449 return read_reg(RDMA);
452 /** Lee un word del buffer de la placa de red
453 * @precond netdev_recv_start() debe haber sido ejecutada
455 uint16 netdev_read_word()
457 uint16 w = read_reg(RDMA) << 8;
458 return w + read_reg(RDMA);
461 /** Finaliza la lectura del frame
462 * @precond netdev_recv_start() debe haber sido ejecutada
464 void netdev_read_end()