Commit 5198cfd9277af376c0d1c667f5a1943f100fee45
1 parent
68998c5d
smc91c111 fixes (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1713 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
27 additions
and
5 deletions
hw/smc91c111.c
@@ -35,8 +35,10 @@ typedef struct { | @@ -35,8 +35,10 @@ typedef struct { | ||
35 | int tx_fifo[NUM_PACKETS]; | 35 | int tx_fifo[NUM_PACKETS]; |
36 | int rx_fifo_len; | 36 | int rx_fifo_len; |
37 | int rx_fifo[NUM_PACKETS]; | 37 | int rx_fifo[NUM_PACKETS]; |
38 | + int tx_fifo_done_len; | ||
39 | + int tx_fifo_done[NUM_PACKETS]; | ||
38 | /* Packet buffer memory. */ | 40 | /* Packet buffer memory. */ |
39 | - uint8_t data[2048][NUM_PACKETS]; | 41 | + uint8_t data[NUM_PACKETS][2048]; |
40 | uint8_t int_level; | 42 | uint8_t int_level; |
41 | uint8_t int_mask; | 43 | uint8_t int_mask; |
42 | uint8_t macaddr[6]; | 44 | uint8_t macaddr[6]; |
@@ -81,6 +83,8 @@ static void smc91c111_update(smc91c111_state *s) | @@ -81,6 +83,8 @@ static void smc91c111_update(smc91c111_state *s) | ||
81 | 83 | ||
82 | if (s->tx_fifo_len == 0) | 84 | if (s->tx_fifo_len == 0) |
83 | s->int_level |= INT_TX_EMPTY; | 85 | s->int_level |= INT_TX_EMPTY; |
86 | + if (s->tx_fifo_done_len != 0) | ||
87 | + s->int_level |= INT_TX; | ||
84 | level = (s->int_level & s->int_mask) != 0; | 88 | level = (s->int_level & s->int_mask) != 0; |
85 | pic_set_irq_new(s->pic, s->irq, level); | 89 | pic_set_irq_new(s->pic, s->irq, level); |
86 | } | 90 | } |
@@ -128,6 +132,18 @@ static void smc91c111_pop_rx_fifo(smc91c111_state *s) | @@ -128,6 +132,18 @@ static void smc91c111_pop_rx_fifo(smc91c111_state *s) | ||
128 | smc91c111_update(s); | 132 | smc91c111_update(s); |
129 | } | 133 | } |
130 | 134 | ||
135 | +/* Remove an item from the TX completion FIFO. */ | ||
136 | +static void smc91c111_pop_tx_fifo_done(smc91c111_state *s) | ||
137 | +{ | ||
138 | + int i; | ||
139 | + | ||
140 | + if (s->tx_fifo_done_len == 0) | ||
141 | + return; | ||
142 | + s->tx_fifo_done_len--; | ||
143 | + for (i = 0; i < s->tx_fifo_done_len; i++) | ||
144 | + s->tx_fifo_done[i] = s->tx_fifo_done[i + 1]; | ||
145 | +} | ||
146 | + | ||
131 | /* Release the memory allocated to a packet. */ | 147 | /* Release the memory allocated to a packet. */ |
132 | static void smc91c111_release_packet(smc91c111_state *s, int packet) | 148 | static void smc91c111_release_packet(smc91c111_state *s, int packet) |
133 | { | 149 | { |
@@ -184,12 +200,13 @@ static void smc91c111_do_tx(smc91c111_state *s) | @@ -184,12 +200,13 @@ static void smc91c111_do_tx(smc91c111_state *s) | ||
184 | add_crc = 0; | 200 | add_crc = 0; |
185 | #endif | 201 | #endif |
186 | if (s->ctr & CTR_AUTO_RELEASE) | 202 | if (s->ctr & CTR_AUTO_RELEASE) |
203 | + /* Race? */ | ||
187 | smc91c111_release_packet(s, packetnum); | 204 | smc91c111_release_packet(s, packetnum); |
205 | + else if (s->tx_fifo_done_len < NUM_PACKETS) | ||
206 | + s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum; | ||
188 | qemu_send_packet(s->vc, p, len); | 207 | qemu_send_packet(s->vc, p, len); |
189 | } | 208 | } |
190 | s->tx_fifo_len = 0; | 209 | s->tx_fifo_len = 0; |
191 | - if ((s->ctr & CTR_AUTO_RELEASE) == 0) | ||
192 | - s->int_level |= INT_TX; | ||
193 | smc91c111_update(s); | 210 | smc91c111_update(s); |
194 | } | 211 | } |
195 | 212 | ||
@@ -206,6 +223,7 @@ static void smc91c111_reset(smc91c111_state *s) | @@ -206,6 +223,7 @@ static void smc91c111_reset(smc91c111_state *s) | ||
206 | { | 223 | { |
207 | s->bank = 0; | 224 | s->bank = 0; |
208 | s->tx_fifo_len = 0; | 225 | s->tx_fifo_len = 0; |
226 | + s->tx_fifo_done_len = 0; | ||
209 | s->rx_fifo_len = 0; | 227 | s->rx_fifo_len = 0; |
210 | s->allocated = 0; | 228 | s->allocated = 0; |
211 | s->packet_num = 0; | 229 | s->packet_num = 0; |
@@ -306,6 +324,7 @@ static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, | @@ -306,6 +324,7 @@ static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, | ||
306 | case 2: /* Reset MMU. */ | 324 | case 2: /* Reset MMU. */ |
307 | s->allocated = 0; | 325 | s->allocated = 0; |
308 | s->tx_fifo_len = 0; | 326 | s->tx_fifo_len = 0; |
327 | + s->tx_fifo_done_len = 0; | ||
309 | s->rx_fifo_len = 0; | 328 | s->rx_fifo_len = 0; |
310 | s->tx_alloc = 0; | 329 | s->tx_alloc = 0; |
311 | break; | 330 | break; |
@@ -326,6 +345,7 @@ static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, | @@ -326,6 +345,7 @@ static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, | ||
326 | break; | 345 | break; |
327 | case 7: /* Reset TX FIFO. */ | 346 | case 7: /* Reset TX FIFO. */ |
328 | s->tx_fifo_len = 0; | 347 | s->tx_fifo_len = 0; |
348 | + s->tx_fifo_done_len = 0; | ||
329 | break; | 349 | break; |
330 | } | 350 | } |
331 | return; | 351 | return; |
@@ -364,6 +384,8 @@ static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, | @@ -364,6 +384,8 @@ static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, | ||
364 | return; | 384 | return; |
365 | case 12: /* Interrupt ACK. */ | 385 | case 12: /* Interrupt ACK. */ |
366 | s->int_level &= ~(value & 0xd6); | 386 | s->int_level &= ~(value & 0xd6); |
387 | + if (value & INT_TX) | ||
388 | + smc91c111_pop_tx_fifo_done(s); | ||
367 | smc91c111_update(s); | 389 | smc91c111_update(s); |
368 | return; | 390 | return; |
369 | case 13: /* Interrupt mask. */ | 391 | case 13: /* Interrupt mask. */ |
@@ -473,10 +495,10 @@ static uint32_t smc91c111_readb(void *opaque, target_phys_addr_t offset) | @@ -473,10 +495,10 @@ static uint32_t smc91c111_readb(void *opaque, target_phys_addr_t offset) | ||
473 | case 3: /* Allocation Result. */ | 495 | case 3: /* Allocation Result. */ |
474 | return s->tx_alloc; | 496 | return s->tx_alloc; |
475 | case 4: /* TX FIFO */ | 497 | case 4: /* TX FIFO */ |
476 | - if (s->tx_fifo_len == 0) | 498 | + if (s->tx_fifo_done_len == 0) |
477 | return 0x80; | 499 | return 0x80; |
478 | else | 500 | else |
479 | - return s->tx_fifo[0]; | 501 | + return s->tx_fifo_done[0]; |
480 | case 5: /* RX FIFO */ | 502 | case 5: /* RX FIFO */ |
481 | if (s->rx_fifo_len == 0) | 503 | if (s->rx_fifo_len == 0) |
482 | return 0x80; | 504 | return 0x80; |