Now that QEMU 2.10 is out, here's the next set of patches in preparation for improving the NIC support for PPC Mac machines (sungem) and sun4u machines (sunhme).
Also included is a little rework of the Forth ob_pci_bus_map_in() so PCI BARs can be mapped within the various _cb C functions which is needed to extract the MAC address from the sungem hardware and add it to the DT.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Mark Cave-Ayland (6): pci: move pci_decode_pci_addr() towards the top of pci.c pci: split the PCI mapping code out of ob_pci_bus_map_in() into ob_pci_map() pci: add basic support for Apple SunGEM pci: add ob_pci_unmap() to unmap PCI memory pci: add SUN hme network device pci: add Intel e1000 network device to PCI database
drivers/pci.c | 134 ++++++++++++++++++++++++++++++++++-------------- drivers/pci_database.c | 18 +++++++ drivers/pci_database.h | 2 + include/drivers/pci.h | 3 ++ 4 files changed, 118 insertions(+), 39 deletions(-)
This is in anticipation of using in several other places.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 7d16f3a..88f11c6 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -150,6 +150,30 @@ static unsigned long pci_bus_addr_to_host_addr(int space, uint32_t ba) } }
+static inline void pci_decode_pci_addr(pci_addr addr, int *flags, + int *space_code, uint32_t *mask) +{ + *flags = 0; + + if (addr & 0x01) { + *space_code = IO_SPACE; + *mask = 0x00000001; + } else { + if (addr & 0x04) { + *space_code = MEMORY_SPACE_64; + *flags |= IS_NOT_RELOCATABLE; /* XXX: why not relocatable? */ + } else { + *space_code = MEMORY_SPACE_32; + } + + if (addr & 0x08) { + *flags |= IS_PREFETCHABLE; + } + + *mask = 0x0000000F; + } +} + static void ob_pci_open(int *idx) { @@ -648,30 +672,6 @@ int rtl8139_config_cb(const pci_config_t *config) return eth_config_cb(config); }
-static inline void pci_decode_pci_addr(pci_addr addr, int *flags, - int *space_code, uint32_t *mask) -{ - *flags = 0; - - if (addr & 0x01) { - *space_code = IO_SPACE; - *mask = 0x00000001; - } else { - if (addr & 0x04) { - *space_code = MEMORY_SPACE_64; - *flags |= IS_NOT_RELOCATABLE; /* XXX: why not relocatable? */ - } else { - *space_code = MEMORY_SPACE_32; - } - - if (addr & 0x08) { - *flags |= IS_PREFETCHABLE; - } - - *mask = 0x0000000F; - } -} - /* * "Designing PCI Cards and Drivers for Power Macintosh Computers", p. 454 *
This is so that it can be called directly from C rather than just the pci-map-in Forth binding.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 53 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 20 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index 88f11c6..e16ce3c 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -367,28 +367,20 @@ ob_pci_encode_unit(int *idx) ss, dev, fn, buf); }
-/* ( pci-addr.lo pci-addr.mid pci-addr.hi size -- virt ) */ - -static void -ob_pci_bus_map_in(int *idx) -{ +/* Map PCI MMIO or IO space from the BAR address. Note it is up to the caller + to understand whether the resulting address is in MEM or IO space and + use the appropriate accesses */ +static ucell ob_pci_map(uint32_t ba, ucell size) { phys_addr_t phys; - uint32_t ba; - ucell size, virt, tmp; - int space; - - PCI_DPRINTF("ob_pci_bar_map_in idx=%p\n", idx); - - size = POP(); - tmp = POP(); - POP(); - ba = POP(); - - /* Get the space from the pci-addr.hi */ - space = ((tmp & PCI_RANGE_TYPE_MASK) >> 24); - - phys = pci_bus_addr_to_host_addr(space, ba); + uint32_t mask; + int flags, space_code; + ucell virt; + + pci_decode_pci_addr(ba, &flags, &space_code, &mask);
+ phys = pci_bus_addr_to_host_addr(space_code, + ba & ~mask); + #if defined(CONFIG_OFMEM) ofmem_claim_phys(phys, size, 0);
@@ -406,6 +398,27 @@ ob_pci_bus_map_in(int *idx) virt = phys; #endif
+ return virt; +} + +/* ( pci-addr.lo pci-addr.mid pci-addr.hi size -- virt ) */ + +static void +ob_pci_bus_map_in(int *idx) +{ + uint32_t ba; + ucell size; + ucell virt; + + PCI_DPRINTF("ob_pci_bar_map_in idx=%p\n", idx); + + size = POP(); + POP(); + POP(); + ba = POP(); + + virt = ob_pci_map(ba, size); + PUSH(virt); }
No driver, but we read the MAC address from the chip and write it into the device-tree where Linux and MacOS look for it. We also set the right compatible property for MacOS to pick it up.
Signed-off-by: Benjamin Herrenschmidt benh@kernel.crashing.org Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 29 +++++++++++++++++++++++++++++ drivers/pci_database.c | 6 ++++++ drivers/pci_database.h | 1 + include/drivers/pci.h | 1 + 4 files changed, 37 insertions(+)
diff --git a/drivers/pci.c b/drivers/pci.c index e16ce3c..f45e743 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -685,6 +685,35 @@ int rtl8139_config_cb(const pci_config_t *config) return eth_config_cb(config); }
+int sungem_config_cb (const pci_config_t *config) +{ + phandle_t ph = get_cur_dev(); + uint32_t val, *mmio; + uint8_t mac[6]; + ucell virt; + +#define MAC_ADDR0 (0x6080UL/4) /* MAC Address 0 Register */ +#define MAC_ADDR1 (0x6084UL/4) /* MAC Address 1 Register */ +#define MAC_ADDR2 (0x6088UL/4) /* MAC Address 2 Register */ + + /* Map PCI memory BAR 0 to access the sungem registers */ + virt = ob_pci_map(config->assigned[0], 0x8000); + mmio = (void *)(uintptr_t)virt; + + val = __le32_to_cpu(*(mmio + MAC_ADDR0)); + mac[5] = val & 0xff; + mac[4] = (val >> 8) & 0xff; + val = __le32_to_cpu(*(mmio + MAC_ADDR1)); + mac[3] = val & 0xff; + mac[2] = (val >> 8) & 0xff; + val = __le32_to_cpu(*(mmio + MAC_ADDR2)); + mac[1] = val & 0xff; + mac[0] = (val >> 8) & 0xff; + set_property(ph, "local-mac-address", (char *)mac, 6); + + return 0; +} + /* * "Designing PCI Cards and Drivers for Power Macintosh Computers", p. 454 * diff --git a/drivers/pci_database.c b/drivers/pci_database.c index 3155ee3..c685540 100644 --- a/drivers/pci_database.c +++ b/drivers/pci_database.c @@ -135,6 +135,12 @@ static const pci_dev_t eth_devices[] = { rtl8139_config_cb, "ethernet", }, { + PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_GMAC, + NULL, "ethernet", NULL, "gmac\0", + 0, 0, 0, + sungem_config_cb, "ethernet", + }, + { /* Virtio-network controller */ PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_NET, NULL, "virtio-net", NULL, diff --git a/drivers/pci_database.h b/drivers/pci_database.h index 241bac3..53eadbd 100644 --- a/drivers/pci_database.h +++ b/drivers/pci_database.h @@ -41,6 +41,7 @@ extern int ebus_config_cb(const pci_config_t *config); extern int i82378_config_cb(const pci_config_t *config); extern int usb_ohci_config_cb(const pci_config_t *config); extern int rtl8139_config_cb(const pci_config_t *config); +extern int sungem_config_cb (const pci_config_t *config);
static inline int pci_compat_len(const pci_dev_t *dev) { diff --git a/include/drivers/pci.h b/include/drivers/pci.h index e9f20a1..c03268c 100644 --- a/include/drivers/pci.h +++ b/include/drivers/pci.h @@ -202,6 +202,7 @@ extern const pci_arch_t *arch; #define PCI_DEVICE_ID_APPLE_UNI_N_I_PCI 0x001e #define PCI_DEVICE_ID_APPLE_UNI_N_PCI 0x001f #define PCI_DEVICE_ID_APPLE_UNI_N_AGP 0x0020 +#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC 0x0021 #define PCI_DEVICE_ID_APPLE_UNI_N_KEYL 0x0022 #define PCI_DEVICE_ID_APPLE_KEYL_USB 0x003f #define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b
This can now be used in sungem_config_cb() to unmap the PCI BAR used to configure the MAC address.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/pci.c b/drivers/pci.c index f45e743..cf6d50c 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -401,6 +401,10 @@ static ucell ob_pci_map(uint32_t ba, ucell size) { return virt; }
+static void ob_pci_unmap(ucell virt, ucell size) { + ofmem_unmap(virt, size); +} + /* ( pci-addr.lo pci-addr.mid pci-addr.hi size -- virt ) */
static void @@ -711,6 +715,7 @@ int sungem_config_cb (const pci_config_t *config) mac[0] = (val >> 8) & 0xff; set_property(ph, "local-mac-address", (char *)mac, 6); + ob_pci_unmap(virt, 0x8000); return 0; }
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 9 +++++++++ drivers/pci_database.c | 6 ++++++ drivers/pci_database.h | 1 + include/drivers/pci.h | 1 + 4 files changed, 17 insertions(+)
diff --git a/drivers/pci.c b/drivers/pci.c index cf6d50c..184dfcd 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -674,6 +674,15 @@ int eth_config_cb (const pci_config_t *config) return 0; }
+int sunhme_config_cb(const pci_config_t *config) +{ + phandle_t ph = get_cur_dev(); + + set_int_property(ph, "hm-rev", 0x21); + + return eth_config_cb(config); +} + int rtl8139_config_cb(const pci_config_t *config) { #ifdef CONFIG_PPC diff --git a/drivers/pci_database.c b/drivers/pci_database.c index c685540..432a63d 100644 --- a/drivers/pci_database.c +++ b/drivers/pci_database.c @@ -141,6 +141,12 @@ static const pci_dev_t eth_devices[] = { sungem_config_cb, "ethernet", }, { + PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_HME, + NULL, "sunhme", NULL, "SUNW,hme\0", + 0, 0, 0, + sunhme_config_cb, "ethernet", + }, + { /* Virtio-network controller */ PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_NET, NULL, "virtio-net", NULL, diff --git a/drivers/pci_database.h b/drivers/pci_database.h index 53eadbd..ac72284 100644 --- a/drivers/pci_database.h +++ b/drivers/pci_database.h @@ -42,6 +42,7 @@ extern int i82378_config_cb(const pci_config_t *config); extern int usb_ohci_config_cb(const pci_config_t *config); extern int rtl8139_config_cb(const pci_config_t *config); extern int sungem_config_cb (const pci_config_t *config); +extern int sunhme_config_cb(const pci_config_t *config);
static inline int pci_compat_len(const pci_dev_t *dev) { diff --git a/include/drivers/pci.h b/include/drivers/pci.h index c03268c..0fd6e39 100644 --- a/include/drivers/pci.h +++ b/include/drivers/pci.h @@ -209,6 +209,7 @@ extern const pci_arch_t *arch;
#define PCI_VENDOR_ID_SUN 0x108e #define PCI_DEVICE_ID_SUN_EBUS 0x1000 +#define PCI_DEVICE_ID_SUN_HME 0x1001 #define PCI_DEVICE_ID_SUN_SIMBA 0x5000 #define PCI_DEVICE_ID_SUN_PBM 0x8000 #define PCI_DEVICE_ID_SUN_SABRE 0xa000
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci_database.c | 6 ++++++ include/drivers/pci.h | 1 + 2 files changed, 7 insertions(+)
diff --git a/drivers/pci_database.c b/drivers/pci_database.c index 432a63d..999b42b 100644 --- a/drivers/pci_database.c +++ b/drivers/pci_database.c @@ -147,6 +147,12 @@ static const pci_dev_t eth_devices[] = { sunhme_config_cb, "ethernet", }, { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E1000, + NULL, "e1000", NULL, "pci1086,100e\0", + 0, 0, 0, + eth_config_cb, "ethernet", + }, + { /* Virtio-network controller */ PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_NET, NULL, "virtio-net", NULL, diff --git a/include/drivers/pci.h b/include/drivers/pci.h index 0fd6e39..f0e386d 100644 --- a/include/drivers/pci.h +++ b/include/drivers/pci.h @@ -230,6 +230,7 @@ extern const pci_arch_t *arch;
#define PCI_VENDOR_ID_INTEL 0x8086 #define PCI_DEVICE_ID_INTEL_82378 0x0484 +#define PCI_DEVICE_ID_INTEL_E1000 0x100e #define PCI_DEVICE_ID_INTEL_82441 0x1237
#endif /* _H_PCI */
On 06/09/17 20:21, Mark Cave-Ayland wrote:
Now that QEMU 2.10 is out, here's the next set of patches in preparation for improving the NIC support for PPC Mac machines (sungem) and sun4u machines (sunhme).
Also included is a little rework of the Forth ob_pci_bus_map_in() so PCI BARs can be mapped within the various _cb C functions which is needed to extract the MAC address from the sungem hardware and add it to the DT.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
No further comments, so I've pushed this to git master.
ATB,
Mark.