net: add fd_readv() handler to qemu_new_vlan_client() args
[qemu] / hw / e1000.c
index 71781e6..01ee57f 100644 (file)
@@ -19,7 +19,7 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
  */
 
 
@@ -41,12 +41,12 @@ enum {
 #define DBGBIT(x)      (1<<DEBUG_##x)
 static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
 
-#define        DBGOUT(what, fmt, params...) do { \
+#define        DBGOUT(what, fmt, ...) do { \
     if (debugflags & DBGBIT(what)) \
-        fprintf(stderr, "e1000: " fmt, ##params); \
+        fprintf(stderr, "e1000: " fmt, ## __VA_ARGS__); \
     } while (0)
 #else
-#define        DBGOUT(what, fmt, params...) do {} while (0)
+#define        DBGOUT(what, fmt, ...) do {} while (0)
 #endif
 
 #define IOPORT_SIZE       0x40
@@ -75,8 +75,6 @@ enum {
 typedef struct E1000State_st {
     PCIDevice dev;
     VLANClientState *vc;
-    NICInfo *nd;
-    uint32_t mmio_base;
     int mmio_index;
 
     uint32_t mac_reg[0x8000];
@@ -192,6 +190,13 @@ rxbufsize(uint32_t v)
 }
 
 static void
+set_ctrl(E1000State *s, int index, uint32_t val)
+{
+    /* RST is self clearing */
+    s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
+}
+
+static void
 set_rx_control(E1000State *s, int index, uint32_t val)
 {
     s->mac_reg[RCTL] = val;
@@ -571,6 +576,21 @@ receive_filter(E1000State *s, const uint8_t *buf, int size)
     return 0;
 }
 
+static void
+e1000_set_link_status(VLANClientState *vc)
+{
+    E1000State *s = vc->opaque;
+    uint32_t old_status = s->mac_reg[STATUS];
+
+    if (vc->link_down)
+        s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
+    else
+        s->mac_reg[STATUS] |= E1000_STATUS_LU;
+
+    if (s->mac_reg[STATUS] != old_status)
+        set_ics(s, 0, E1000_ICR_LSC);
+}
+
 static int
 e1000_can_receive(void *opaque)
 {
@@ -652,8 +672,8 @@ e1000_receive(void *opaque, const uint8_t *buf, int size)
     n = E1000_ICS_RXT0;
     if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH])
         rdt += s->mac_reg[RDLEN] / sizeof(desc);
-    if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) << s->rxbuf_min_shift >=
-        s->mac_reg[RDLEN])
+    if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) <= s->mac_reg[RDLEN] >>
+        s->rxbuf_min_shift)
         n |= E1000_ICS_RXDMT0;
 
     set_ics(s, 0, n);
@@ -764,29 +784,29 @@ static uint32_t (*macreg_readops[])(E1000State *, int) = {
     [MTA ... MTA+127] = &mac_readreg,
     [VFTA ... VFTA+127] = &mac_readreg,
 };
-enum { NREADOPS = sizeof(macreg_readops) / sizeof(*macreg_readops) };
+enum { NREADOPS = ARRAY_SIZE(macreg_readops) };
 
 #define putreg(x)      [x] = mac_writereg
 static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
     putreg(PBA),       putreg(EERD),   putreg(SWSM),   putreg(WUFC),
     putreg(TDBAL),     putreg(TDBAH),  putreg(TXDCTL), putreg(RDBAH),
-    putreg(RDBAL),     putreg(LEDCTL), putreg(CTRL),   putreg(VET),
+    putreg(RDBAL),     putreg(LEDCTL), putreg(VET),
     [TDLEN] = set_dlen,        [RDLEN] = set_dlen,     [TCTL] = set_tctl,
     [TDT] = set_tctl,  [MDIC] = set_mdic,      [ICS] = set_ics,
     [TDH] = set_16bit, [RDH] = set_16bit,      [RDT] = set_rdt,
     [IMC] = set_imc,   [IMS] = set_ims,        [ICR] = set_icr,
-    [EECD] = set_eecd, [RCTL] = set_rx_control,
+    [EECD] = set_eecd, [RCTL] = set_rx_control, [CTRL] = set_ctrl,
     [RA ... RA+31] = &mac_writereg,
     [MTA ... MTA+127] = &mac_writereg,
     [VFTA ... VFTA+127] = &mac_writereg,
 };
-enum { NWRITEOPS = sizeof(macreg_writeops) / sizeof(*macreg_writeops) };
+enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
 
 static void
 e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     E1000State *s = opaque;
-    unsigned int index = ((addr - s->mmio_base) & 0x1ffff) >> 2;
+    unsigned int index = (addr & 0x1ffff) >> 2;
 
 #ifdef TARGET_WORDS_BIGENDIAN
     val = bswap32(val);
@@ -820,7 +840,7 @@ static uint32_t
 e1000_mmio_readl(void *opaque, target_phys_addr_t addr)
 {
     E1000State *s = opaque;
-    unsigned int index = ((addr - s->mmio_base) & 0x1ffff) >> 2;
+    unsigned int index = (addr & 0x1ffff) >> 2;
 
     if (index < NREADOPS && macreg_readops[index])
     {
@@ -855,13 +875,13 @@ static const int mac_regtosave[] = {
     TDT,       TORH,   TORL,   TOTH,   TOTL,   TPR,    TPT,    TXDCTL, WUFC,
     VET,
 };
-enum { MAC_NSAVE = sizeof mac_regtosave/sizeof *mac_regtosave };
+enum { MAC_NSAVE = ARRAY_SIZE(mac_regtosave) };
 
 static const struct {
     int size;
     int array0;
 } mac_regarraystosave[] = { {32, RA}, {128, MTA}, {128, VFTA} };
-enum { MAC_NARRAYS = sizeof mac_regarraystosave/sizeof *mac_regarraystosave };
+enum { MAC_NARRAYS = ARRAY_SIZE(mac_regarraystosave) };
 
 static void
 nic_save(QEMUFile *f, void *opaque)
@@ -870,7 +890,7 @@ nic_save(QEMUFile *f, void *opaque)
     int i, j;
 
     pci_device_save(&s->dev, f);
-    qemu_put_be32s(f, &s->mmio_base);
+    qemu_put_be32(f, 0);
     qemu_put_be32s(f, &s->rxbuf_size);
     qemu_put_be32s(f, &s->rxbuf_min_shift);
     qemu_put_be32s(f, &s->eecd_state.val_in);
@@ -916,7 +936,7 @@ nic_load(QEMUFile *f, void *opaque, int version_id)
         return ret;
     if (version_id == 1)
         qemu_get_sbe32s(f, &i); /* once some unused instance id */
-    qemu_get_be32s(f, &s->mmio_base);
+    qemu_get_be32(f); /* Ignored.  Was mmio_base.  */
     qemu_get_be32s(f, &s->rxbuf_size);
     qemu_get_be32s(f, &s->rxbuf_min_shift);
     qemu_get_be32s(f, &s->eecd_state.val_in);
@@ -1002,35 +1022,59 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num,
                 uint32_t addr, uint32_t size, int type)
 {
     E1000State *d = (E1000State *)pci_dev;
+    int i;
+    const uint32_t excluded_regs[] = {
+        E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS,
+        E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE
+    };
+
 
     DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size);
 
-    d->mmio_base = addr;
     cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
+    qemu_register_coalesced_mmio(addr, excluded_regs[0]);
+
+    for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++)
+        qemu_register_coalesced_mmio(addr + excluded_regs[i] + 4,
+                                     excluded_regs[i + 1] -
+                                     excluded_regs[i] - 4);
+}
+
+static void
+e1000_cleanup(VLANClientState *vc)
+{
+    E1000State *d = vc->opaque;
+
+    unregister_savevm("e1000", d);
+}
+
+static int
+pci_e1000_uninit(PCIDevice *dev)
+{
+    E1000State *d = (E1000State *) dev;
+
+    cpu_unregister_io_memory(d->mmio_index);
+
+    return 0;
 }
 
-void
-pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
+static void pci_e1000_init(PCIDevice *pci_dev)
 {
-    E1000State *d;
+    E1000State *d = (E1000State *)pci_dev;
     uint8_t *pci_conf;
     uint16_t checksum = 0;
     static const char info_str[] = "e1000";
     int i;
-
-    d = (E1000State *)pci_register_device(bus, "e1000",
-                sizeof(E1000State), devfn, NULL, NULL);
+    uint8_t macaddr[6];
 
     pci_conf = d->dev.config;
-    memset(pci_conf, 0, 256);
 
-    *(uint16_t *)(pci_conf+0x00) = cpu_to_le16(0x8086);
-    *(uint16_t *)(pci_conf+0x02) = cpu_to_le16(E1000_DEVID);
+    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
+    pci_config_set_device_id(pci_conf, E1000_DEVID);
     *(uint16_t *)(pci_conf+0x04) = cpu_to_le16(0x0407);
     *(uint16_t *)(pci_conf+0x06) = cpu_to_le16(0x0010);
     pci_conf[0x08] = 0x03;
-    pci_conf[0x0a] = 0x00; // ethernet network controller
-    pci_conf[0x0b] = 0x02;
+    pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
     pci_conf[0x0c] = 0x10;
 
     pci_conf[0x3d] = 1; // interrupt pin 0
@@ -1044,11 +1088,11 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
     pci_register_io_region((PCIDevice *)d, 1, IOPORT_SIZE,
                            PCI_ADDRESS_SPACE_IO, ioport_map);
 
-    d->nd = nd;
     memmove(d->eeprom_data, e1000_eeprom_template,
         sizeof e1000_eeprom_template);
+    qdev_get_macaddr(&d->dev.qdev, macaddr);
     for (i = 0; i < 3; i++)
-        d->eeprom_data[i] = (nd->macaddr[2*i+1]<<8) | nd->macaddr[2*i];
+        d->eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i];
     for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
         checksum += d->eeprom_data[i];
     checksum = (uint16_t) EEPROM_SUM - checksum;
@@ -1061,13 +1105,20 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
     d->rxbuf_min_shift = 1;
     memset(&d->tx, 0, sizeof d->tx);
 
-    d->vc = qemu_new_vlan_client(nd->vlan, e1000_receive,
-                                 e1000_can_receive, d);
+    d->vc = qdev_get_vlan_client(&d->dev.qdev,
+                                 e1000_can_receive, e1000_receive,
+                                 NULL, e1000_cleanup, d);
+    d->vc->link_status_changed = e1000_set_link_status;
 
-    snprintf(d->vc->info_str, sizeof(d->vc->info_str),
-             "%s macaddr=%02x:%02x:%02x:%02x:%02x:%02x", info_str,
-             d->nd->macaddr[0], d->nd->macaddr[1], d->nd->macaddr[2],
-             d->nd->macaddr[3], d->nd->macaddr[4], d->nd->macaddr[5]);
+    qemu_format_nic_info_str(d->vc, macaddr);
 
     register_savevm(info_str, -1, 2, nic_save, nic_load, d);
+    d->dev.unregister = pci_e1000_uninit;
 }
+
+static void e1000_register_devices(void)
+{
+    pci_qdev_register("e1000", sizeof(E1000State), pci_e1000_init);
+}
+
+device_init(e1000_register_devices)