void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, qemu_irq irq, void* mem_opaque, void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write)) { dp8393xState *s; qemu_check_nic_model(nd, "dp83932"); s = qemu_mallocz(sizeof(dp8393xState)); s->mem_opaque = mem_opaque; s->memory_rw = memory_rw; s->it_shift = it_shift; s->irq = irq; s->watchdog = qemu_new_timer(vm_clock, dp8393x_watchdog, s); s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */ s->conf.macaddr = nd->macaddr; s->conf.vlan = nd->vlan; s->conf.peer = nd->netdev; s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, nd->model, nd->name, s); qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); qemu_register_reset(nic_reset, s); nic_reset(s); s->mmio_index = cpu_register_io_memory(dp8393x_read, dp8393x_write, s); cpu_register_physical_memory(base, 0x40 << it_shift, s->mmio_index); }
void dp83932_init(NICInfo *nd, hwaddr base, int it_shift, MemoryRegion *address_space, qemu_irq irq, void* mem_opaque, void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write)) { dp8393xState *s; qemu_check_nic_model(nd, "dp83932"); s = g_malloc0(sizeof(dp8393xState)); s->address_space = address_space; s->mem_opaque = mem_opaque; s->memory_rw = memory_rw; s->it_shift = it_shift; s->irq = irq; s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s); s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */ s->conf.macaddr = nd->macaddr; s->conf.peers.ncs[0] = nd->netdev; s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, nd->model, nd->name, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); qemu_register_reset(nic_reset, s); nic_reset(s); memory_region_init_io(&s->mmio, NULL, &dp8393x_ops, s, "dp8393x", 0x40 << it_shift); memory_region_add_subregion(address_space, base, &s->mmio); }
//************************************ //************************************ //********** INITIALISE NIC ********** //************************************ //************************************ //Call with: //0 = allow speed 10 / 100 Mbps //1 = force speed to 10 Mbps void nic_initialise (BYTE init_config) { WORD data; //----------------------------- //----- DO HARDWARE RESET ----- //----------------------------- //POWER UP - WAIT 50MS nic_delay_ms(50); //RESET THE NIC nic_reset(); //WAIT 50MS nic_delay_ms(50); //------------------------------------------------- //----- WRITE THE NIC CONFIGURATION REGISTERS ----- //------------------------------------------------- //(The eeprom is not present so the nic defaults to base address 0x0300) //----- SEND MMU RESET COMMAND ----- //Set nic bank 2 nic_write(NIC_REG_BANK, 0x3302); //MMU Command //(Reset MMU to initial state) nic_write(NIC_REG_MMU_COMMAND, 0x0040); //Wait for the busy flag to clear while (nic_read(NIC_REG_MMU_COMMAND) & 0x0001) ; //----- DO BANK 0 REGISTERS ----- //Set bank 0 nic_write(NIC_REG_BANK, 0x3300); //Transmit Control (done at end) //nic_write(NIC_REG_TCR, 0x0000); //EPH Status //nic_write(NIC_REG_EPH_STATUS, 0x0000); //Receive Control (done at end) //nic_write(NIC_REG_RCR, 0x0000); //Counter //nic_write(NIC_REG_COUNTER, 0x0000); //Memory Information //nic_write(NIC_REG_MIR, 0x0000); //Receive / Phy Control Register //(Speed and duplex auto negotiation on, LEDA function, LED B function) nic_write(NIC_REG_RPCR, NIC_CONST_PPCR_REGISTER); //Reserved //nic_write(NIC_REG_RESERVED, 0x0000); //----- DO BANK 1 REGISTERS ----- //Set Bank 1 nic_write(NIC_REG_BANK, 0x3301); //Configuration //(No wait states on ARDY except for data reg if not ready, external MII disabled) nic_write(NIC_REG_CONFIG, 0xb0b1); //Base Address //nic_write(NIC_REG_BASE, 0x0000); //Individual Address (MAC) 0-1 (Bit 0 is first bit of address on the cable) nic_write(NIC_REG_IA0_1, (((WORD)our_mac_address.v[1] << 8) + (WORD)our_mac_address.v[0])); //(Litle endian) //Individual Address (MAC) 2-3 nic_write(NIC_REG_IA2_3, (((WORD)our_mac_address.v[3] << 8) + (WORD)our_mac_address.v[2])); //(Litle endian) //Individual Address (MAC) 4-5 nic_write(NIC_REG_IA4_5, (((WORD)our_mac_address.v[5] << 8) + (WORD)our_mac_address.v[4])); //(Litle endian) //General Purpose //nic_write(NIC_REG_GEN_PURPOSE, 0x0000); //Control //(Bad CRC packets are dumped, Auto release TX memory after good TX, Link Irq on, counter roll over irq off, tx error irq off) nic_write(NIC_REG_CONTROL, 0x1a90); //----- DO BANK 2 REGISTERS ----- //Set bank 2 nic_write(NIC_REG_BANK, 0x3302); //MMU Command //(Reset MMU to initial state - already done above) //nic_write(NIC_REG_MMU_COMMAND, 0x0040); //Wait for the busy flag to clear //while (nic_read(NIC_REG_MMU_COMMAND) & 0x0001) // ; //Packet Number //nic_write(NIC_REG_PNR, 0x0000); //(Litle endian) //Fifo ports //nic_write(NIC_REG_FIFO_PORTS, 0x0000); //Pointer //nic_write(NIC_REG_POINTER, 0x0000); //Data //nic_write(NIC_REG_DATA, 0x0000); //Data High //nic_write(NIC_REG_DATA_H, 0x0000); //Interrupt Status //nic_write(NIC_REG_INTERRUPT, 0x001f); //(Litle endian) //----- DO BANK 3 REGISTERS ----- //Select bank 3 nic_write(NIC_REG_BANK, 0x3303); //Multicast 0-1 nic_write(NIC_REG_MT0_1, 0x0000); //Multicast 2-3 nic_write(NIC_REG_MT2_3, 0x0000); //Multicast 4-5 nic_write(NIC_REG_MT4_5, 0x0000); //Multicast 6-7 nic_write(NIC_REG_MT6_7, 0x0000); //Management //nic_write(NIC_REG_MGMT, 0x0000); //Revision //nic_write(NIC_REG_REVISION, 0x0000); //Early Receive //(Receive IRQ Threshold = max) nic_write(NIC_REG_ERCV, 0x001f); //---------------------------------------------- //----- WRITE TO THE PHY CONTROL REGISTERS ----- //---------------------------------------------- //----- SET 'AUTO NEGOTIATE AVAILABLE SPEEDS AND DUPLEX MODES' ----- //WE USE HALF DUPLEX MODE if (init_config) { //Only 10Mbps available data = 0x0021; } else { //10/100Mbps available data = 0x00a1; } nic_write_phy_register(NIC_PHY_AUTO_NEG_ADVERTISEMENT, data); //----- TURN OFF ISOLATION MODE SO AUTO NEGOTIATION STARTS ----- nic_write_phy_register(NIC_PHY_CONTROL, 0x1000); //---------------------------- //----- ENABLE TX AND RX ----- //---------------------------- //Set bank 0 nic_write(NIC_REG_BANK, 0x3300); //Transmit Control nic_write(NIC_REG_TCR, NIC_CONST_TX_CTRL_REGISTER); //Receive Control nic_write(NIC_REG_RCR, NIC_CONST_RX_CTRL_REGISTER); //Select nic bank 2 nic_write(NIC_REG_BANK, 0x3302); //Interrupt Status //(Clear the TX INT bit if set) nic_write(NIC_REG_INTERRUPT, (NIC_CONST_IRQ_REGISTER | 0x0002)); //(little endian) nic_is_linked = 0; nic_speed_is_100mbps = 0; nic_rx_packet_waiting_to_be_dumped = 0; }
//************************************ //************************************ //********** INITIALISE NIC ********** //************************************ //************************************ //Call with: //init_config = don't care (speed configuration options not available with this IC) void nic_initialise (BYTE init_config) { //----------------------------- //----- DO HARDWARE RESET ----- //----------------------------- nic_delay_ms(10); //RESET THE NIC nic_reset(); nic_delay_ms(50); //Wait for reset bit to be set while((nic_read(NIC_REG_ISR) & 0x80) == 0); //------------------------------------------------- //----- WRITE THE NIC CONFIGURATION REGISTERS ----- //------------------------------------------------- //As the nic doesn't have its own eeprom we need to setup the bank3 config registers //Note that the DO pin of where the eeprom would be connected must be pulled low. //Config 1 and 2 are not altered by the eeprom change as in jumper mode they use the default state of defined pins //Config 3 is affected by the eeprom and contains several bits that are read only (i.e. can only be set by the eeprom). The important pin //is the FUDUP pin which must be low, or the nic looses transmissions by assuming that it can tx while rx is active. This means that the //LED control pins also have to be low. Ideally the LED pins would be high as it gives the more useful 'Link' and 'Active' led outptus, //but this is the compromise. //Stop DMA and Set page 3 nic_write(NIC_REG_CR, 0xe1); //Enable writing to the config registers nic_write(NIC_REG_9346CR, 0xc0); //Config 0 is read only //nic_write(NIC_REG_CONFIG0, 0x); //Disable IRQ's (rest is set by jumpers) nic_write(NIC_REG_CONFIG1, 0x00); //Set network medium type nic_write(NIC_REG_CONFIG2, 0x00); //Set not in sleep mode, not in powerdown mode nic_write(NIC_REG_CONFIG3, 0x30); //Disable writing to the config registers nic_write(NIC_REG_9346CR, 0x00); nic_delay_ms(50); //Set page 0 nic_write(NIC_REG_CR, 0x21); //Setup the the Data Configuration Register (DCR) nic_write(NIC_REG_DCR, 0x58); //Clear the remote byte count registers nic_write(NIC_REG_RBCR0, 0x00); nic_write(NIC_REG_RBCR1, 0x00); //Initialise the receive configuration register (monitor mode) nic_write(NIC_REG_RCR, 0x20); //Turn on loopback mode nic_write(NIC_REG_TCR, 0x02); //Initialise the receive buffer ring //RTL8019AS has 16K bytes of ram //Tx buffer starts at 0x4000 //Rx ring starts / tx buffer ends at 0x0x4600 - this gives 1536 bytes to tx, max tx size allowed on ethernet is 1500 bytes. //Rx ring ends at 0x6000 - this gives 6656 bytes to rx (used in 256 byte pages by nic) nic_write(NIC_REG_BNDRY, NIC_RX_START_LOC_IN_RING); nic_write(NIC_REG_PSTART, NIC_RX_START_LOC_IN_RING); nic_write(NIC_REG_PSTOP, NIC_RX_END_LOC_IN_RING); //Clear the Interrupt Status Register nic_write(NIC_REG_ISR, 0xff); //Initialise the interrupt mask register (all irq's disabled) nic_write(NIC_REG_IMR, 0x00); //Stop DMA and Set page 1 nic_write(NIC_REG_CR, 0x61); //Set the MAC address in the nic registers nic_write(NIC_REG_PAR0, our_mac_address.v[0]); nic_write(NIC_REG_PAR1, our_mac_address.v[1]); nic_write(NIC_REG_PAR2, our_mac_address.v[2]); nic_write(NIC_REG_PAR3, our_mac_address.v[3]); nic_write(NIC_REG_PAR4, our_mac_address.v[4]); nic_write(NIC_REG_PAR5, our_mac_address.v[5]); //Initialise the multicast address registers //Set all MARx to 0 = reject all multicast nic_write(NIC_REG_MAR0, 0x00); nic_write(NIC_REG_MAR1, 0x00); nic_write(NIC_REG_MAR2, 0x00); nic_write(NIC_REG_MAR3, 0x00); nic_write(NIC_REG_MAR4, 0x00); nic_write(NIC_REG_MAR5, 0x00); nic_write(NIC_REG_MAR6, 0x00); nic_write(NIC_REG_MAR7, 0x00); //Initialise the current pointer (to the same addr as the rx buffer start) nic_write(NIC_REG_CURR, NIC_RX_START_LOC_IN_RING); //Initialize the interface //Set page 0 nic_write(NIC_REG_CR, 0x21); //Wait 1.6mS for any tx/rx to complete nic_delay_ms(2); //Normal operation, initialize remote dma, fifo threshhold 8 bytes nic_write(NIC_REG_DCR, 0xd8); //Remote dma byte count = 0000h nic_write(NIC_REG_RBCR0, 0x00); nic_write(NIC_REG_RBCR1, 0x00); //Remote dma start address = 4000h nic_write(NIC_REG_RSAR0, 0x00); nic_write(NIC_REG_RSAR1, NIC_TX_START_LOC_IN_RING); //Monitor mode nic_write(NIC_REG_RCR, 0x20); //Place NIC in loopback nic_write(NIC_REG_TCR, 0x02); //Clear all interrupt flags nic_write(NIC_REG_ISR, 0xff); //Unmask all interrupts nic_write(NIC_REG_IMR, 0xff); //4000h < tx buffer nic_write(NIC_REG_TPSR, NIC_TX_START_LOC_IN_RING); //Stop nic, change to register page 1 nic_write(NIC_REG_CR, 0x61); //Next place to rx a packet nic_write(NIC_REG_CURR, NIC_RX_START_LOC_IN_RING); //Start nic, abort remote dma (page 0) nic_write(NIC_REG_CR, 0x22); //Change from loopback mode to normal op nic_write(NIC_REG_TCR, 0x00); //Accept broadcast packets nic_write(NIC_REG_RCR, 0x04); //Clear any pending interrupts nic_write(NIC_REG_ISR, 0xff); //Put in start mode //Start nic and set page 1 nic_write(NIC_REG_CR, 0x22); //Initialise the Transmit Configuration register nic_write(NIC_REG_TCR, 0x00); //Normal tx, CRC appended by transmitter, remote tx disable command disabled (also set in the receive overlflow routine) //Accept broadcast packets nic_write(NIC_REG_RCR, 0x04); //Accept broadcast but not multicast, packets with receive errors are rejected //----- DO FINAL FLAGS SETUP ----- nic_is_linked = 0; nic_speed_is_100mbps = 0; nic_rx_packet_waiting_to_be_dumped = 0; }