static void smc91c111_writeb(void *opaque, hwaddr offset, uint32_t value) { smc91c111_state *s = (smc91c111_state *)opaque; if (offset == 14) { s->bank = value; return; } if (offset == 15) return; switch (s->bank) { case 0: switch (offset) { case 0: /* TCR */ SET_LOW(tcr, value); return; case 1: SET_HIGH(tcr, value); return; case 4: /* RCR */ SET_LOW(rcr, value); return; case 5: SET_HIGH(rcr, value); if (s->rcr & RCR_SOFT_RST) smc91c111_reset(s); return; case 10: case 11: /* RPCR */ /* Ignored */ return; } break; case 1: switch (offset) { case 0: /* CONFIG */ SET_LOW(cr, value); return; case 1: SET_HIGH(cr,value); return; case 2: case 3: /* BASE */ case 4: case 5: case 6: case 7: case 8: case 9: /* IA */ /* Not implemented. */ return; case 10: /* Genral Purpose */ SET_LOW(gpr, value); return; case 11: SET_HIGH(gpr, value); return; case 12: /* Control */ if (value & 1) fprintf(stderr, "smc91c111:EEPROM store not implemented\n"); if (value & 2) fprintf(stderr, "smc91c111:EEPROM reload not implemented\n"); value &= ~3; SET_LOW(ctr, value); return; case 13: SET_HIGH(ctr, value); return; } break; case 2: switch (offset) { case 0: /* MMU Command */ switch (value >> 5) { case 0: /* no-op */ break; case 1: /* Allocate for TX. */ s->tx_alloc = 0x80; s->int_level &= ~INT_ALLOC; smc91c111_update(s); smc91c111_tx_alloc(s); break; case 2: /* Reset MMU. */ s->allocated = 0; s->tx_fifo_len = 0; s->tx_fifo_done_len = 0; s->rx_fifo_len = 0; s->tx_alloc = 0; break; case 3: /* Remove from RX FIFO. */ smc91c111_pop_rx_fifo(s); break; case 4: /* Remove from RX FIFO and release. */ if (s->rx_fifo_len > 0) { smc91c111_release_packet(s, s->rx_fifo[0]); } smc91c111_pop_rx_fifo(s); break; case 5: /* Release. */ smc91c111_release_packet(s, s->packet_num); break; case 6: /* Add to TX FIFO. */ smc91c111_queue_tx(s, s->packet_num); break; case 7: /* Reset TX FIFO. */ s->tx_fifo_len = 0; s->tx_fifo_done_len = 0; break; } return; case 1: /* Ignore. */ return; case 2: /* Packet Number Register */ s->packet_num = value; return; case 3: case 4: case 5: /* Should be readonly, but linux writes to them anyway. Ignore. */ return; case 6: /* Pointer */ SET_LOW(ptr, value); return; case 7: SET_HIGH(ptr, value); return; case 8: case 9: case 10: case 11: /* Data */ { int p; int n; if (s->ptr & 0x8000) n = s->rx_fifo[0]; else n = s->packet_num; p = s->ptr & 0x07ff; if (s->ptr & 0x4000) { s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff); } else { p += (offset & 3); } s->data[n][p] = value; } return; case 12: /* Interrupt ACK. */ s->int_level &= ~(value & 0xd6); if (value & INT_TX) smc91c111_pop_tx_fifo_done(s); smc91c111_update(s); return; case 13: /* Interrupt mask. */ s->int_mask = value; smc91c111_update(s); return; } break;; case 3: switch (offset) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: /* Multicast table. */ /* Not implemented. */ return; case 8: case 9: /* Management Interface. */ /* Not implemented. */ return; case 12: /* Early receive. */ s->ercv = value & 0x1f; case 13: /* Ignore. */ return; } break; } hw_error("smc91c111_write: Bad reg %d:%x\n", s->bank, (int)offset); }
static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, uint32_t value) { smc91c111_state *s = (smc91c111_state *)opaque; if (offset == 14) { s->bank = value; return; } if (offset == 15) return; switch (s->bank) { case 0: switch (offset) { case 0: SET_LOW(tcr, value); return; case 1: SET_HIGH(tcr, value); return; case 4: SET_LOW(rcr, value); return; case 5: SET_HIGH(rcr, value); if (s->rcr & RCR_SOFT_RST) smc91c111_reset(s); return; case 10: case 11: return; } break; case 1: switch (offset) { case 0: SET_LOW(cr, value); return; case 1: SET_HIGH(cr,value); return; case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: return; case 10: SET_LOW(gpr, value); return; case 11: SET_HIGH(gpr, value); return; case 12: if (value & 1) fprintf(stderr, "smc91c111:EEPROM store not implemented\n"); if (value & 2) fprintf(stderr, "smc91c111:EEPROM reload not implemented\n"); value &= ~3; SET_LOW(ctr, value); return; case 13: SET_HIGH(ctr, value); return; } break; case 2: switch (offset) { case 0: switch (value >> 5) { case 0: break; case 1: s->tx_alloc = 0x80; s->int_level &= ~INT_ALLOC; smc91c111_update(s); smc91c111_tx_alloc(s); break; case 2: s->allocated = 0; s->tx_fifo_len = 0; s->tx_fifo_done_len = 0; s->rx_fifo_len = 0; s->tx_alloc = 0; break; case 3: smc91c111_pop_rx_fifo(s); break; case 4: if (s->rx_fifo_len > 0) { smc91c111_release_packet(s, s->rx_fifo[0]); } smc91c111_pop_rx_fifo(s); break; case 5: smc91c111_release_packet(s, s->packet_num); break; case 6: smc91c111_queue_tx(s, s->packet_num); break; case 7: s->tx_fifo_len = 0; s->tx_fifo_done_len = 0; break; } return; case 1: return; case 2: s->packet_num = value; return; case 3: case 4: case 5: return; case 6: SET_LOW(ptr, value); return; case 7: SET_HIGH(ptr, value); return; case 8: case 9: case 10: case 11: { int p; int n; if (s->ptr & 0x8000) n = s->rx_fifo[0]; else n = s->packet_num; p = s->ptr & 0x07ff; if (s->ptr & 0x4000) { s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff); } else { p += (offset & 3); } s->data[n][p] = value; } return; case 12: s->int_level &= ~(value & 0xd6); if (value & INT_TX) smc91c111_pop_tx_fifo_done(s); smc91c111_update(s); return; case 13: s->int_mask = value; smc91c111_update(s); return; } break;; case 3: switch (offset) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: return; case 8: case 9: return; case 12: s->ercv = value & 0x1f; case 13: return; } break; } hw_error("smc91c111_write: Bad reg %d:%x\n", s->bank, (int)offset); }