1 // vim: set et sw=4 sts=4 :
8 /** Tamaño del frame */
11 // Próximo frame a obtener
20 /// Tamaño de la cabecera de los buffers de la placa de red
21 #define BUF_HDR_SIZE 4
23 /// Cambia de página sin modificar los demás bits del CR
24 #define SELECT_REG_PAGE(page) \
27 write_reg(CR, read_reg(CR) & ~(PS1 | PS0)); \
28 write_reg(CR, read_reg(CR) | (page << 6)); \
32 /// Aborta (o completa) el DMA limpiando el ISR
33 #define ABORT_DMA(flags) \
36 write_reg(CR, flags); \
37 write_reg(ISR, RDC); \
42 static void write_reg(unsigned char reg, unsigned char wr_data)
45 // Select register address.
46 ADDR_PORT &= ~ADDR_PORT_MASK;
49 // Output register data to port.
52 // Clock register data into RTL8019AS.
53 // IOR & IOW are both active low.
59 // Set register data port as input again.
60 DATA_PORT = DATA_PORT_MASK;
65 static unsigned char read_reg(unsigned char reg)
68 // Select register address.
69 ADDR_PORT &= ~ADDR_PORT_MASK;
72 // Enable register data output from RTL8019AS.
76 // Read register data from port.
79 // Disable register data output from RTL8019AS.
87 /** Resetea placa de red en caso de buffer overflow */
90 bit retransmit = read_reg(CR) & TXP;
92 // If the receive buffer ring has overflowed we dump the whole
93 // thing and start over. There is no way of knowing whether the
94 // data it contains is uncorrupted, or will cause us grief.
96 // Stop RTL8019AS and abort DMA operation.
99 // Wait for controller to halt after any current tx completes.
100 while(!(read_reg(ISR) & RST)) continue;
102 // Reset remote byte count registers.
103 write_reg(RBCR0, 0x00);
104 write_reg(RBCR1, 0x00);
106 // Check whether currently transmitting a packet.
109 // If neither a successful transmission nor a tx abort error
110 // has occured, then flag current tx packet for resend.
111 if(read_reg(ISR) & (PTX | TXE))
117 // Set transmit configuration register to loopback internally.
118 write_reg(TCR, MODE1);
120 // Restart the RTL8019AS.
121 write_reg(CR, START);
123 // Re-initialise last receive buffer read pointer.
124 write_reg(BNRY, RX_PAGE_START);
126 // Select RTL8019AS register page 1.
129 // Re-initialise current packet receive buffer page pointer.
130 write_reg(CURR, RX_PAGE_START + 1);
132 // Select RTL8019AS register page 0.
135 // Clear rx buffer overflow & packet received interrupt flags.
136 write_reg(ISR, PRX | OVW);
138 // Re-itialise transmit configuration reg for normal operation.
139 write_reg(TCR, MODE0);
143 // Retransmit packet in RTL8019AS local tx buffer.
144 write_reg(CR, START | TXP);
149 /** Inicializa dispositivo de red
150 * @return true si se inicializó correctamente, false si no
156 // Set IOR & IOW as they're active low.
161 // Set register data port as input.
162 DATA_PORT = DATA_PORT_MASK;
164 // Configure RTL8019AS ethernet controller.
166 // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).
167 // That leaves plenty of time for the RTL8019AS to read it's
168 // configuration in from the 9346 EEPROM before we get here.
170 // Select RTL8019AS register page 0.
173 // Check if RTL8019AS fully reset.
174 if(!(read_reg(ISR) & RST))
179 // Stop RTL8019AS, select page 0 and abort DMA operation.
182 // Initialise data configuration register.
183 // FIFO threshold 8 bytes, no loopback, don't use auto send packet.
184 write_reg(DCR, FT1 | LS);
186 // Reset remote byte count registers.
187 write_reg(RBCR0, 0u);
188 write_reg(RBCR1, 0u);
190 // Receive configuration register to monitor mode.
193 // Initialise transmit configuration register to loopback internally.
194 write_reg(TCR, MODE1);
196 // Clear interrupt status register bits by writing 1 to each.
199 // Mask all interrupts in mask register.
200 write_reg(IMR, NONE);
202 // Obtengo MAC de la placa
203 write_reg(RBCR0, 12u); // Vamos a leer 12 bytes (2 x 6)
204 write_reg(RBCR1, 0u);
205 write_reg(RSAR0, 0u); // En la dirección 0x0000
206 write_reg(RSAR1, 0u);
207 write_reg(CR, READ); // Comienza lectura
208 for (i = 0; i < ETH_ADDR_SIZE; ++i)
210 eth_addr_local[i] = read_reg(RDMA);
211 read_reg(RDMA); // Ignoramos porque viene como un word
214 // Abort/ complete DMA operation.
217 // Set transmit page start.
218 write_reg(TPSR, TX_PAGE_START);
220 // Set receive buffer page start.
221 write_reg(PSTART, RX_PAGE_START);
223 // Initialise last receive buffer read pointer.
224 write_reg(BNRY, RX_PAGE_START);
226 // Set receive buffer page stop.
227 write_reg(PSTOP, RX_PAGE_STOP);
229 // Select RTL8019AS register page 1.
232 // Initialise current packet receive buffer page pointer
233 write_reg(CURR, RX_PAGE_START + 1);
235 // Set physical address
236 for (i = 0; i < ETH_ADDR_SIZE; ++i)
237 write_reg(PAR_BASE + i, eth_addr_local[i]);
239 // Restart RTL8019AS.
240 write_reg(CR, START);
242 // Initialise transmit configuration register for normal operation.
243 write_reg(TCR, MODE0);
245 // Receive configuration register to accept broadcast packets.
252 /** Comienza el envío de un nuevo frame */
253 void netdev_send_start()
255 // Wait until pending transmit operation completes.
256 while (read_reg(CR) & TXP) continue;
257 write_reg(ISR, PTX); // Limpio bit de interrupción
259 // Set remote DMA start address registers to indicate where to load packet.
260 write_reg(RSAR0, 0u);
261 write_reg(RSAR1, TX_PAGE_START);
264 /** Finaliza el envío del frame
265 * @precond netdev_send_start() debe haber sido ejecutada
266 * @precond se copiaron datos al dispositivo para enviar
267 * @param len Cantidad de bytes a transmitir
269 void netdev_send_end(byte len)
271 // Set transmit page start to indicate packet start.
272 write_reg(TPSR, TX_PAGE_START);
274 // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.
275 if (len < MIN_PACKET_LEN)
276 len = MIN_PACKET_LEN;
278 // Set transmit byte count registers to indicate packet length.
279 write_reg(TBCR0, len);
280 write_reg(TBCR1, 0u);
282 // Issue command for RTL8019AS to transmit packet from it's local buffer.
283 write_reg(CR, START | TXP);
286 void netdev_write_start(byte len)
288 // Set remote DMA byte count registers to indicate length of packet load.
289 write_reg(RBCR0, len);
290 write_reg(RBCR1, 0u);
292 // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
293 write_reg(CR, WRITE);
296 void netdev_write_start_at(byte offset, byte len)
298 // Set remote DMA start address registers to packet data.
299 write_reg(RSAR0, offset);
300 write_reg(RSAR1, TX_PAGE_START);
302 // Set remote DMA byte count registers to indicate length of packet load.
303 write_reg(RBCR0, len);
304 write_reg(RBCR1, 0u);
306 // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
307 write_reg(CR, WRITE);
310 /** Escribe un byte al buffer de la placa de red para ser enviado
311 * @precond netdev_send_start() debe haber sido ejecutada
312 * @param b Byte a enviar
314 void netdev_write_byte(byte b)
319 /** Escribe un word al buffer de la placa de red para ser enviado
320 * @precond netdev_send_start() debe haber sido ejecutada
321 * @param w Word a enviar
323 void netdev_write_word(uint16 w)
325 write_reg(RDMA, HIGH(w));
326 write_reg(RDMA, LOW(w));
329 void netdev_write_end()
331 // Abort/ complete DMA operation.
335 /** Comienza la lectura de un nuevo frame
336 * @return Cantidad de bytes a recibir
338 byte netdev_recv_start()
340 // Check if the rx buffer has overflowed.
341 if (read_reg(ISR) & OVW)
346 current = read_reg(CURR);
349 // Hack: a veces reporta mal el flag de OVW, así que verificamos que
350 // relamente haya habido overflow.
351 if (read_reg(BNRY) == current)
353 printb(read_reg(ISR), 0x01);
354 printb(read_reg(BNRY), 0x02);
355 printb(current, 0x04);
361 // Check if there is a packet in the rx buffer.
362 else if (read_reg(ISR) & PRX)
368 // Retrieve packet header. (status, next_ptr, length_l, length_h)
370 // Obtiene el buffer a leer actualmente
371 recv_state.curr_buf = read_reg(BNRY) + 1;
372 if (recv_state.curr_buf >= RX_PAGE_STOP)
373 recv_state.curr_buf = RX_PAGE_START;
375 // Select RTL8019AS register page 1.
378 // Retrieve current receive buffer page
379 current = read_reg(CURR);
381 // Select RTL8019AS register page 1.
384 // Check if last packet has been removed from rx buffer.
385 if(recv_state.curr_buf == current)
387 // Clear packet received interrupt flag.
388 write_reg(ISR, PRX | RXE);
392 // Set remote DMA byte count registers to packet header length.
393 recv_state.curr_off = 0;
394 netdev_read_start(BUF_HDR_SIZE);
397 status = netdev_read_byte();
399 // Save next packet pointer.
400 recv_state.next_buf = netdev_read_byte() - 1;
402 // Retrieve packet data length and subtract CRC bytes.
403 len = netdev_read_byte() - BUF_HDR_SIZE;
405 // Si es muy grande, muy chico o hubo error, lo descartamos
406 if ((len < MIN_PACKET_LEN) || (len > MAX_PACKET_LEN)
407 || ((status & 0x0F) != RXSOK)
408 || netdev_read_byte()) // Parte alta del tamaño
410 // Terminamos DMA y pasamos al próximo frame
412 write_reg(BNRY, recv_state.next_buf);
416 // Abort/ complete DMA operation.
425 /** Finaliza la recepción del frame
426 * @precond netdev_recv_start() debe haber sido ejecutada
428 void netdev_recv_end()
430 // Pasa el próximo frame
431 write_reg(BNRY, recv_state.next_buf);
434 void netdev_read_start(byte len)
436 // Set remote DMA start address registers to packet data.
437 write_reg(RSAR0, recv_state.curr_off);
438 write_reg(RSAR1, recv_state.curr_buf);
439 recv_state.curr_off += len;
441 // Set remote DMA byte count registers to packet data length.
442 write_reg(RBCR0, len);
445 // 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_read_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_read_word()
462 uint16 w = read_reg(RDMA) << 8;
463 return w + read_reg(RDMA);
466 /** Finaliza la lectura del frame
467 * @precond netdev_recv_start() debe haber sido ejecutada
469 void netdev_read_end()