e1000: rewrite tx a bit

This commit is contained in:
K. Lange 2021-09-17 21:37:30 +09:00
parent aabbde7877
commit 3f94c70293

View File

@ -214,27 +214,32 @@ static int irq_handler(struct regs *r) {
return handled; return handled;
} }
static int tx_full(struct e1000_nic * device, int tx_tail, int tx_head) {
if (tx_tail == tx_head) return 0;
if (device->tx_index == tx_head) return 1;
if (((device->tx_index + 1) & E1000_NUM_TX_DESC) == tx_head) return 1;
return 0;
}
static void send_packet(struct e1000_nic * device, uint8_t* payload, size_t payload_size) { static void send_packet(struct e1000_nic * device, uint8_t* payload, size_t payload_size) {
spin_lock(device->tx_lock); spin_lock(device->tx_lock);
int tx_tail = read_command(device, E1000_REG_TXDESCTAIL); int tx_tail = read_command(device, E1000_REG_TXDESCTAIL);
int tx_head = read_command(device, E1000_REG_TXDESCHEAD); int tx_head = read_command(device, E1000_REG_TXDESCHEAD);
if (tx_tail != tx_head) { if (tx_full(device, tx_tail, tx_head)) {
/* Queue is not empty, make sure we don't fill it... */ int timeout = 1000;
if ((device->tx_index + 1) % E1000_NUM_TX_DESC == tx_head) { do {
int timeout = 1000; spin_unlock(device->tx_lock);
do { delay_yield(10000);
spin_unlock(device->tx_lock); timeout--;
delay_yield(10000); if (timeout == 0) {
timeout--; printf("e1000: wait for tx timed out, giving up\n");
if (timeout == 0) { return;
printf("e1000: wait for tx timed out, giving up\n"); }
return; spin_lock(device->tx_lock);
} tx_tail = read_command(device, E1000_REG_TXDESCTAIL);
spin_lock(device->tx_lock); tx_head = read_command(device, E1000_REG_TXDESCHEAD);
tx_head = read_command(device, E1000_REG_TXDESCHEAD); } while (tx_full(device, tx_tail, tx_head));
} while ((device->tx_index + 1) % E1000_NUM_TX_DESC == tx_head);
}
} }
memcpy(device->tx_virt[device->tx_index], payload, payload_size); memcpy(device->tx_virt[device->tx_index], payload, payload_size);
@ -280,10 +285,18 @@ static void init_tx(struct e1000_nic * device) {
device->tx_index = 0; device->tx_index = 0;
write_command(device, E1000_REG_TCTRL, uint32_t tctl = read_command(device, E1000_REG_TCTRL);
TCTL_EN |
TCTL_PSP | /* Collision threshold */
read_command(device, E1000_REG_TCTRL)); tctl &= ~(0xFF << 4);
tctl |= (15 << 4);
/* Turn it on */
tctl |= TCTL_EN;
tctl |= TCTL_PSP;
tctl |= (1 << 24); /* retransmit on late collision */
write_command(device, E1000_REG_TCTRL, tctl);
} }
static int ioctl_e1000(fs_node_t * node, unsigned long request, void * argp) { static int ioctl_e1000(fs_node_t * node, unsigned long request, void * argp) {
@ -360,13 +373,22 @@ static ssize_t e1000_debug_func(fs_node_t * node, off_t offset, size_t size, uin
struct e1000_nic * e1000_debug_nic = devices[i]; struct e1000_nic * e1000_debug_nic = devices[i];
uint32_t creg = read_command(e1000_debug_nic, E1000_REG_CTRL); uint32_t creg = read_command(e1000_debug_nic, E1000_REG_CTRL);
uint32_t sreg = read_command(e1000_debug_nic, E1000_REG_STATUS); uint32_t sreg = read_command(e1000_debug_nic, E1000_REG_STATUS);
int rx_head = read_command(e1000_debug_nic, E1000_REG_RXDESCHEAD);
int rx_tail = read_command(e1000_debug_nic, E1000_REG_RXDESCTAIL);
int tx_head = read_command(e1000_debug_nic, E1000_REG_TXDESCHEAD);
int tx_tail = read_command(e1000_debug_nic, E1000_REG_TXDESCTAIL);
out += snprintf(out, 4095, out += snprintf(out, 4095,
"Device %d\n" "Device %d\n"
"Ctrl reg:\t%#x\n" "Ctrl reg:\t%#x\n"
"Status reg:\t%#x\n", "Status reg:\t%#x\n"
"rx head/tail:\t%d %d\n"
"tx head/tail:\t%d %d\n",
i, i,
creg, creg,
sreg); sreg,
rx_head, rx_tail,
tx_head, tx_tail
);
} }
size_t _bsize = strlen(buf); size_t _bsize = strlen(buf);