Annotation of qemu/hw/pcnet-pci.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * QEMU AMD PC-Net II (Am79C970A) PCI emulation
        !             3:  *
        !             4:  * Copyright (c) 2004 Antony T Curtis
        !             5:  *
        !             6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !             7:  * of this software and associated documentation files (the "Software"), to deal
        !             8:  * in the Software without restriction, including without limitation the rights
        !             9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            10:  * copies of the Software, and to permit persons to whom the Software is
        !            11:  * furnished to do so, subject to the following conditions:
        !            12:  *
        !            13:  * The above copyright notice and this permission notice shall be included in
        !            14:  * all copies or substantial portions of the Software.
        !            15:  *
        !            16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
        !            19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            22:  * THE SOFTWARE.
        !            23:  */
        !            24: 
        !            25: /* This software was written to be compatible with the specification:
        !            26:  * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
        !            27:  * AMD Publication# 19436  Rev:E  Amendment/0  Issue Date: June 2000
        !            28:  */
        !            29: 
        !            30: #include "pci.h"
        !            31: #include "net.h"
        !            32: #include "loader.h"
        !            33: #include "qemu-timer.h"
        !            34: 
        !            35: #include "pcnet.h"
        !            36: 
        !            37: //#define PCNET_DEBUG
        !            38: //#define PCNET_DEBUG_IO
        !            39: //#define PCNET_DEBUG_BCR
        !            40: //#define PCNET_DEBUG_CSR
        !            41: //#define PCNET_DEBUG_RMD
        !            42: //#define PCNET_DEBUG_TMD
        !            43: //#define PCNET_DEBUG_MATCH
        !            44: 
        !            45: 
        !            46: typedef struct {
        !            47:     PCIDevice pci_dev;
        !            48:     PCNetState state;
        !            49: } PCIPCNetState;
        !            50: 
        !            51: static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
        !            52: {
        !            53:     PCNetState *s = opaque;
        !            54: #ifdef PCNET_DEBUG
        !            55:     printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
        !            56: #endif
        !            57:     /* Check APROMWE bit to enable write access */
        !            58:     if (pcnet_bcr_readw(s,2) & 0x100)
        !            59:         s->prom[addr & 15] = val;
        !            60: }
        !            61: 
        !            62: static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
        !            63: {
        !            64:     PCNetState *s = opaque;
        !            65:     uint32_t val = s->prom[addr & 15];
        !            66: #ifdef PCNET_DEBUG
        !            67:     printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
        !            68: #endif
        !            69:     return val;
        !            70: }
        !            71: 
        !            72: static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
        !            73:                              pcibus_t addr, pcibus_t size, int type)
        !            74: {
        !            75:     PCNetState *d = &DO_UPCAST(PCIPCNetState, pci_dev, pci_dev)->state;
        !            76: 
        !            77: #ifdef PCNET_DEBUG_IO
        !            78:     printf("pcnet_ioport_map addr=0x%04"FMT_PCIBUS" size=0x%04"FMT_PCIBUS"\n",
        !            79:            addr, size);
        !            80: #endif
        !            81: 
        !            82:     register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
        !            83:     register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
        !            84: 
        !            85:     register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
        !            86:     register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
        !            87:     register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
        !            88:     register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
        !            89: }
        !            90: 
        !            91: static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
        !            92: {
        !            93:     PCNetState *d = opaque;
        !            94: #ifdef PCNET_DEBUG_IO
        !            95:     printf("pcnet_mmio_writeb addr=0x" TARGET_FMT_plx" val=0x%02x\n", addr,
        !            96:            val);
        !            97: #endif
        !            98:     if (!(addr & 0x10))
        !            99:         pcnet_aprom_writeb(d, addr & 0x0f, val);
        !           100: }
        !           101: 
        !           102: static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr)
        !           103: {
        !           104:     PCNetState *d = opaque;
        !           105:     uint32_t val = -1;
        !           106:     if (!(addr & 0x10))
        !           107:         val = pcnet_aprom_readb(d, addr & 0x0f);
        !           108: #ifdef PCNET_DEBUG_IO
        !           109:     printf("pcnet_mmio_readb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr,
        !           110:            val & 0xff);
        !           111: #endif
        !           112:     return val;
        !           113: }
        !           114: 
        !           115: static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
        !           116: {
        !           117:     PCNetState *d = opaque;
        !           118: #ifdef PCNET_DEBUG_IO
        !           119:     printf("pcnet_mmio_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr,
        !           120:            val);
        !           121: #endif
        !           122:     if (addr & 0x10)
        !           123:         pcnet_ioport_writew(d, addr & 0x0f, val);
        !           124:     else {
        !           125:         addr &= 0x0f;
        !           126:         pcnet_aprom_writeb(d, addr, val & 0xff);
        !           127:         pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
        !           128:     }
        !           129: }
        !           130: 
        !           131: static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr)
        !           132: {
        !           133:     PCNetState *d = opaque;
        !           134:     uint32_t val = -1;
        !           135:     if (addr & 0x10)
        !           136:         val = pcnet_ioport_readw(d, addr & 0x0f);
        !           137:     else {
        !           138:         addr &= 0x0f;
        !           139:         val = pcnet_aprom_readb(d, addr+1);
        !           140:         val <<= 8;
        !           141:         val |= pcnet_aprom_readb(d, addr);
        !           142:     }
        !           143: #ifdef PCNET_DEBUG_IO
        !           144:     printf("pcnet_mmio_readw addr=0x" TARGET_FMT_plx" val = 0x%04x\n", addr,
        !           145:            val & 0xffff);
        !           146: #endif
        !           147:     return val;
        !           148: }
        !           149: 
        !           150: static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
        !           151: {
        !           152:     PCNetState *d = opaque;
        !           153: #ifdef PCNET_DEBUG_IO
        !           154:     printf("pcnet_mmio_writel addr=0x" TARGET_FMT_plx" val=0x%08x\n", addr,
        !           155:            val);
        !           156: #endif
        !           157:     if (addr & 0x10)
        !           158:         pcnet_ioport_writel(d, addr & 0x0f, val);
        !           159:     else {
        !           160:         addr &= 0x0f;
        !           161:         pcnet_aprom_writeb(d, addr, val & 0xff);
        !           162:         pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
        !           163:         pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
        !           164:         pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
        !           165:     }
        !           166: }
        !           167: 
        !           168: static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
        !           169: {
        !           170:     PCNetState *d = opaque;
        !           171:     uint32_t val;
        !           172:     if (addr & 0x10)
        !           173:         val = pcnet_ioport_readl(d, addr & 0x0f);
        !           174:     else {
        !           175:         addr &= 0x0f;
        !           176:         val = pcnet_aprom_readb(d, addr+3);
        !           177:         val <<= 8;
        !           178:         val |= pcnet_aprom_readb(d, addr+2);
        !           179:         val <<= 8;
        !           180:         val |= pcnet_aprom_readb(d, addr+1);
        !           181:         val <<= 8;
        !           182:         val |= pcnet_aprom_readb(d, addr);
        !           183:     }
        !           184: #ifdef PCNET_DEBUG_IO
        !           185:     printf("pcnet_mmio_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr,
        !           186:            val);
        !           187: #endif
        !           188:     return val;
        !           189: }
        !           190: 
        !           191: static const VMStateDescription vmstate_pci_pcnet = {
        !           192:     .name = "pcnet",
        !           193:     .version_id = 3,
        !           194:     .minimum_version_id = 2,
        !           195:     .minimum_version_id_old = 2,
        !           196:     .fields      = (VMStateField []) {
        !           197:         VMSTATE_PCI_DEVICE(pci_dev, PCIPCNetState),
        !           198:         VMSTATE_STRUCT(state, PCIPCNetState, 0, vmstate_pcnet, PCNetState),
        !           199:         VMSTATE_END_OF_LIST()
        !           200:     }
        !           201: };
        !           202: 
        !           203: /* PCI interface */
        !           204: 
        !           205: static CPUWriteMemoryFunc * const pcnet_mmio_write[] = {
        !           206:     &pcnet_mmio_writeb,
        !           207:     &pcnet_mmio_writew,
        !           208:     &pcnet_mmio_writel
        !           209: };
        !           210: 
        !           211: static CPUReadMemoryFunc * const pcnet_mmio_read[] = {
        !           212:     &pcnet_mmio_readb,
        !           213:     &pcnet_mmio_readw,
        !           214:     &pcnet_mmio_readl
        !           215: };
        !           216: 
        !           217: static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
        !           218:                             pcibus_t addr, pcibus_t size, int type)
        !           219: {
        !           220:     PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
        !           221: 
        !           222: #ifdef PCNET_DEBUG_IO
        !           223:     printf("pcnet_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n",
        !           224:            addr, size);
        !           225: #endif
        !           226: 
        !           227:     cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->state.mmio_index);
        !           228: }
        !           229: 
        !           230: static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
        !           231:                                       uint8_t *buf, int len, int do_bswap)
        !           232: {
        !           233:     cpu_physical_memory_write(addr, buf, len);
        !           234: }
        !           235: 
        !           236: static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
        !           237:                                      uint8_t *buf, int len, int do_bswap)
        !           238: {
        !           239:     cpu_physical_memory_read(addr, buf, len);
        !           240: }
        !           241: 
        !           242: static void pci_pcnet_cleanup(VLANClientState *nc)
        !           243: {
        !           244:     PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque;
        !           245: 
        !           246:     pcnet_common_cleanup(d);
        !           247: }
        !           248: 
        !           249: static int pci_pcnet_uninit(PCIDevice *dev)
        !           250: {
        !           251:     PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, dev);
        !           252: 
        !           253:     cpu_unregister_io_memory(d->state.mmio_index);
        !           254:     qemu_del_timer(d->state.poll_timer);
        !           255:     qemu_free_timer(d->state.poll_timer);
        !           256:     qemu_del_vlan_client(&d->state.nic->nc);
        !           257:     return 0;
        !           258: }
        !           259: 
        !           260: static NetClientInfo net_pci_pcnet_info = {
        !           261:     .type = NET_CLIENT_TYPE_NIC,
        !           262:     .size = sizeof(NICState),
        !           263:     .can_receive = pcnet_can_receive,
        !           264:     .receive = pcnet_receive,
        !           265:     .cleanup = pci_pcnet_cleanup,
        !           266: };
        !           267: 
        !           268: static int pci_pcnet_init(PCIDevice *pci_dev)
        !           269: {
        !           270:     PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev, pci_dev);
        !           271:     PCNetState *s = &d->state;
        !           272:     uint8_t *pci_conf;
        !           273: 
        !           274: #if 0
        !           275:     printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
        !           276:         sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
        !           277: #endif
        !           278: 
        !           279:     pci_conf = pci_dev->config;
        !           280: 
        !           281:     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AMD);
        !           282:     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_AMD_LANCE);
        !           283:     pci_set_word(pci_conf + PCI_STATUS,
        !           284:                  PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
        !           285:     pci_conf[PCI_REVISION_ID] = 0x10;
        !           286:     pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
        !           287: 
        !           288:     pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, 0x0);
        !           289:     pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0);
        !           290: 
        !           291:     pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0
        !           292:     pci_conf[PCI_MIN_GNT] = 0x06;
        !           293:     pci_conf[PCI_MAX_LAT] = 0xff;
        !           294: 
        !           295:     /* Handler for memory-mapped I/O */
        !           296:     s->mmio_index =
        !           297:       cpu_register_io_memory(pcnet_mmio_read, pcnet_mmio_write, &d->state,
        !           298:                              DEVICE_NATIVE_ENDIAN);
        !           299: 
        !           300:     pci_register_bar(pci_dev, 0, PCNET_IOPORT_SIZE,
        !           301:                            PCI_BASE_ADDRESS_SPACE_IO, pcnet_ioport_map);
        !           302: 
        !           303:     pci_register_bar(pci_dev, 1, PCNET_PNPMMIO_SIZE,
        !           304:                            PCI_BASE_ADDRESS_SPACE_MEMORY, pcnet_mmio_map);
        !           305: 
        !           306:     s->irq = pci_dev->irq[0];
        !           307:     s->phys_mem_read = pci_physical_memory_read;
        !           308:     s->phys_mem_write = pci_physical_memory_write;
        !           309: 
        !           310:     if (!pci_dev->qdev.hotplugged) {
        !           311:         static int loaded = 0;
        !           312:         if (!loaded) {
        !           313:             rom_add_option("pxe-pcnet.bin", -1);
        !           314:             loaded = 1;
        !           315:         }
        !           316:     }
        !           317: 
        !           318:     return pcnet_common_init(&pci_dev->qdev, s, &net_pci_pcnet_info);
        !           319: }
        !           320: 
        !           321: static void pci_reset(DeviceState *dev)
        !           322: {
        !           323:     PCIPCNetState *d = DO_UPCAST(PCIPCNetState, pci_dev.qdev, dev);
        !           324: 
        !           325:     pcnet_h_reset(&d->state);
        !           326: }
        !           327: 
        !           328: static PCIDeviceInfo pcnet_info = {
        !           329:     .qdev.name  = "pcnet",
        !           330:     .qdev.size  = sizeof(PCIPCNetState),
        !           331:     .qdev.reset = pci_reset,
        !           332:     .qdev.vmsd  = &vmstate_pci_pcnet,
        !           333:     .init       = pci_pcnet_init,
        !           334:     .exit       = pci_pcnet_uninit,
        !           335:     .qdev.props = (Property[]) {
        !           336:         DEFINE_NIC_PROPERTIES(PCIPCNetState, state.conf),
        !           337:         DEFINE_PROP_END_OF_LIST(),
        !           338:     }
        !           339: };
        !           340: 
        !           341: static void pci_pcnet_register_devices(void)
        !           342: {
        !           343:     pci_qdev_register(&pcnet_info);
        !           344: }
        !           345: 
        !           346: device_init(pci_pcnet_register_devices)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.