diff options
author | Helge Deller <deller@gmx.de> | 2023-09-21 23:37:50 +0200 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2023-10-11 03:24:39 +0200 |
commit | ae2b0d735fba482f9e29945c2af0cfe033887756 (patch) | |
tree | a639e25e399e30e41cd275560274cd52fcd56b7e | |
parent | 40c5a5a8ab1391b9d50e57ee349c04f0009d7714 (diff) | |
download | seabios-hppa-ae2b0d735fba482f9e29945c2af0cfe033887756.zip seabios-hppa-ae2b0d735fba482f9e29945c2af0cfe033887756.tar.gz seabios-hppa-ae2b0d735fba482f9e29945c2af0cfe033887756.tar.bz2 |
Add support for HP C3700 worksation emulation
-rw-r--r-- | .vimrc | 4 | ||||
-rw-r--r-- | src/Kconfig | 2 | ||||
-rw-r--r-- | src/block.c | 2 | ||||
-rw-r--r-- | src/boot.c | 6 | ||||
-rw-r--r-- | src/fw/pciinit.c | 34 | ||||
-rw-r--r-- | src/hw/ata.h | 8 | ||||
-rw-r--r-- | src/hw/pci.c | 67 | ||||
-rw-r--r-- | src/hw/pcidevice.c | 5 | ||||
-rw-r--r-- | src/hw/pcidevice.h | 1 | ||||
-rw-r--r-- | src/hw/rtc.h | 7 | ||||
-rw-r--r-- | src/hw/serialio.c | 3 | ||||
-rw-r--r-- | src/hw/usb-ohci.c | 91 | ||||
-rw-r--r-- | src/hw/usb.c | 14 | ||||
-rw-r--r-- | src/kbd.c | 2 | ||||
-rw-r--r-- | src/parisc/c3700.h | 284 | ||||
-rw-r--r-- | src/parisc/hppa.h | 69 | ||||
-rw-r--r-- | src/parisc/hppa_hardware.h | 18 | ||||
-rw-r--r-- | src/parisc/lasips2.c | 11 | ||||
-rw-r--r-- | src/parisc/machine-create.h | 20 | ||||
-rw-r--r-- | src/parisc/malloc.c | 2 | ||||
-rw-r--r-- | src/parisc/parisc.c | 925 | ||||
-rw-r--r-- | src/parisc/pdc.h | 3 | ||||
-rw-r--r-- | src/parisc/stirom.c | 2 |
23 files changed, 1292 insertions, 288 deletions
@@ -0,0 +1,4 @@ +set expandtab +set shiftwidth=4 +set smarttab +autocmd FileType asm setlocal ts=8 sts=8 sw=8 noexpandtab nosmarttab diff --git a/src/Kconfig b/src/Kconfig index 158ffb4..4e26dca 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -163,7 +163,7 @@ endmenu menu "Hardware support" config ATA - depends on DRIVES + depends on DRIVES && !PARISC bool "ATA controllers" default y help diff --git a/src/block.c b/src/block.c index 1b85154..ed08bb7 100644 --- a/src/block.c +++ b/src/block.c @@ -623,7 +623,7 @@ process_op_16(struct disk_op_s *op) int process_op(struct disk_op_s *op) { - dprintf(DEBUG_HDL_13, "disk_op d=%p lba=%d buf=%p count=%d cmd=%d\n" + if (0) dprintf(DEBUG_HDL_13, "disk_op d=%p lba=%d buf=%p count=%d cmd=%d\n" , op->drive_fl, (u32)op->lba, op->buf_fl , op->count, op->command); @@ -50,7 +50,7 @@ glob_prefix(const char *glob, const char *str) } #if CONFIG_PARISC -#define FW_PCI_DOMAIN "/dino-pcihost" +#define FW_PCI_DOMAIN (has_astro ? "/elroy-pcihost" : "/dino-pcihost") #else #define FW_PCI_DOMAIN "/pci@i0cf8" #endif @@ -178,7 +178,7 @@ loadBiosGeometry(void) static BootDeviceLCHS * boot_lchs_find(const char *glob) { - dprintf(1, "Searching bios-geometry for: %s\n", glob); + // dprintf(1, "Searching bios-geometry for: %s\n", glob); int i; for (i = 0; i < BiosGeometryCount; i++) if (glob_prefix(glob, BiosGeometry[i].name)) @@ -291,7 +291,7 @@ loadBootOrder(void) static int find_prio(const char *glob) { - dprintf(1, "Searching bootorder for: %s\n", glob); + // dprintf(1, "Searching bootorder for: %s\n", glob); int i; for (i = 0; i < BootorderCount; i++) if (glob_prefix(glob, Bootorder[i])) diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 4c16ea0..c4e60ae 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -536,6 +536,33 @@ static void dino_mem_addr_setup(struct pci_device *dev, void *arg) /* setup io address space */ pci_io_low_end = 0xa000; } + +static int astro_pci_slot_get_irq(struct pci_device *pci, int pin) +{ + int bus = pci_bdf_to_bus(pci->bdf); + int slot = pci_bdf_to_dev(pci->bdf); + return (bus + 1) * 4 + (slot & 0x03); +} + +static void astro_mem_addr_setup(struct pci_device *dev, void *arg) +{ + pcimem_start = LMMIO_DIST_BASE_ADDR; + pcimem_end = pcimem_start + LMMIO_DIST_BASE_SIZE / ROPES_PER_IOC; + + MaxPCIBus = 4; + pci_slot_get_irq = astro_pci_slot_get_irq; + + /* setup io address space */ + pci_io_low_end = IOS_DIST_BASE_SIZE / ROPES_PER_IOC; +} + +static void parisc_mem_addr_setup(struct pci_device *dev, void *arg) +{ + if (has_astro) + return astro_mem_addr_setup(dev, arg); + else + return dino_mem_addr_setup(dev, arg); +} #endif /* CONFIG_PARISC */ @@ -558,7 +585,7 @@ static void pci_bios_init_platform(void) } #if CONFIG_PARISC - dino_mem_addr_setup(NULL, NULL); + parisc_mem_addr_setup(NULL, NULL); #endif } @@ -608,7 +635,7 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus) int bdf; u16 class; - dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus); + // dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus); /* prevent accidental access to unintended devices */ foreachbdf(bdf, bus) { @@ -693,6 +720,7 @@ pci_bios_init_bus(void) pci_bios_init_bus_rec(0 /* host bus */, &pci_bus); +dprintf(1,"EXTRA ROOTS %d\n", extraroots); if (extraroots) { while (pci_bus < 0xff) { pci_bus++; @@ -900,7 +928,7 @@ static int pci_bios_check_devices(struct pci_bus *busses) busses[pci->secondary_bus].bus_dev = pci; struct pci_bus *bus = &busses[pci_bdf_to_bus(pci->bdf)]; - if (!bus->bus_dev) + if (!bus->bus_dev && !CONFIG_PARISC) /* * Resources for all root busses go in busses[0] */ diff --git a/src/hw/ata.h b/src/hw/ata.h index dff209a..36c333d 100644 --- a/src/hw/ata.h +++ b/src/hw/ata.h @@ -29,18 +29,10 @@ int ata_process_op(struct disk_op_s *op); int ata_atapi_process_op(struct disk_op_s *op); void ata_setup(void); -#if CONFIG_X86 #define PORT_ATA2_CMD_BASE 0x0170 #define PORT_ATA1_CMD_BASE 0x01f0 #define PORT_ATA2_CTRL_BASE 0x0374 #define PORT_ATA1_CTRL_BASE 0x03f4 -#elif CONFIG_PARISC -#include "parisc/hppa_hardware.h" -#define PORT_ATA2_CMD_BASE (IDE_HPA+0x0170) -#define PORT_ATA1_CMD_BASE (IDE_HPA+0x01f0) -#define PORT_ATA2_CTRL_BASE (IDE_HPA+0x0374) -#define PORT_ATA1_CTRL_BASE (IDE_HPA+0x03f4) -#endif // Global defines -- ATA register and register bits. // command block & control block regs diff --git a/src/hw/pci.c b/src/hw/pci.c index ecc724b..3f35250 100644 --- a/src/hw/pci.c +++ b/src/hw/pci.c @@ -31,8 +31,40 @@ static u32 ioconfig_cmd(u16 bdf, u32 addr) return 0x80000000 | (bdf << 8) | (addr & 0xfc); } +/* + * Memory mapped I/O + * + * readX()/writeX() do byteswapping and take an ioremapped address + * __raw_readX()/__raw_writeX() don't byteswap and take an ioremapped address. + * gsc_*() don't byteswap and operate on physical addresses; + * eg dev->hpa or 0xfee00000. + */ + +/* each elroy has 0x2000 offset */ +#define ELROY_MAX_BUSSES 4 +unsigned long elroy_offset(u16 bdf) +{ + static const int elroy_hpa_offsets[ELROY_MAX_BUSSES] = { 0x30000, 0x32000, 0x38000, 0x3c000 }; + int bus = pci_bdf_to_bus(bdf); + if (bus >= ELROY_MAX_BUSSES) + return -1UL; + return elroy_hpa_offsets[bus] - elroy_hpa_offsets[0]; +} + +void *elroy_port(unsigned long port, unsigned long offs) +{ + return (void *)(port + offs); +} + void pci_config_writel(u16 bdf, u32 addr, u32 val) { + if (has_astro) { + unsigned long offs = elroy_offset(bdf); + if (offs == -1UL) + return; + writel(elroy_port(PORT_PCI_CMD, offs), ioconfig_cmd((u8)bdf, addr)); + writel(elroy_port(PORT_PCI_DATA, offs), val); + } else if (!MODESEGMENT && mmconfig) { writel(mmconfig_addr(bdf, addr), val); } else { @@ -43,6 +75,13 @@ void pci_config_writel(u16 bdf, u32 addr, u32 val) void pci_config_writew(u16 bdf, u32 addr, u16 val) { + if (has_astro) { + unsigned long offs = elroy_offset(bdf); + if (offs == -1UL) + return; + writel(elroy_port(PORT_PCI_CMD, offs), ioconfig_cmd((u8)bdf, addr)); + writew(elroy_port(PORT_PCI_DATA + (addr & 2), offs), val); + } else if (!MODESEGMENT && mmconfig) { writew(mmconfig_addr(bdf, addr), val); } else { @@ -53,6 +92,13 @@ void pci_config_writew(u16 bdf, u32 addr, u16 val) void pci_config_writeb(u16 bdf, u32 addr, u8 val) { + if (has_astro) { + unsigned long offs = elroy_offset(bdf); + if (offs == -1UL) + return; + writel(elroy_port(PORT_PCI_CMD, offs), ioconfig_cmd((u8)bdf, addr)); + writeb(elroy_port(PORT_PCI_DATA + (addr & 3), offs), val); + } else if (!MODESEGMENT && mmconfig) { writeb(mmconfig_addr(bdf, addr), val); } else { @@ -63,6 +109,13 @@ void pci_config_writeb(u16 bdf, u32 addr, u8 val) u32 pci_config_readl(u16 bdf, u32 addr) { + if (has_astro) { + unsigned long offs = elroy_offset(bdf); + if (offs == -1UL) + return -1; + writel(elroy_port(PORT_PCI_CMD, offs), ioconfig_cmd((u8)bdf, addr)); + return readl(elroy_port(PORT_PCI_DATA, offs)); + } else if (!MODESEGMENT && mmconfig) { return readl(mmconfig_addr(bdf, addr)); } else { @@ -73,6 +126,13 @@ u32 pci_config_readl(u16 bdf, u32 addr) u16 pci_config_readw(u16 bdf, u32 addr) { + if (has_astro) { + unsigned long offs = elroy_offset(bdf); + if (offs == -1UL) + return -1; + writel(elroy_port(PORT_PCI_CMD, offs), ioconfig_cmd((u8)bdf, addr)); + return readw(elroy_port(PORT_PCI_DATA + (addr & 2), offs)); + } else if (!MODESEGMENT && mmconfig) { return readw(mmconfig_addr(bdf, addr)); } else { @@ -83,6 +143,13 @@ u16 pci_config_readw(u16 bdf, u32 addr) u8 pci_config_readb(u16 bdf, u32 addr) { + if (has_astro) { + unsigned long offs = elroy_offset(bdf); + if (offs == -1UL) + return -1; + writel(elroy_port(PORT_PCI_CMD, offs), ioconfig_cmd((u8)bdf, addr)); + return readb(elroy_port(PORT_PCI_DATA + (addr & 3), offs)); + } else if (!MODESEGMENT && mmconfig) { return readb(mmconfig_addr(bdf, addr)); } else { diff --git a/src/hw/pcidevice.c b/src/hw/pcidevice.c index 8853cf7..ed3e15d 100644 --- a/src/hw/pcidevice.c +++ b/src/hw/pcidevice.c @@ -66,6 +66,7 @@ pci_probe_devices(void) dev->class = classrev >> 16; dev->prog_if = classrev >> 8; dev->revision = classrev & 0xff; + dev->irq = pci_config_readb(bdf, PCI_INTERRUPT_PIN); dev->header_type = pci_config_readb(bdf, PCI_HEADER_TYPE); u8 v = dev->header_type & 0x7f; if (v == PCI_HEADER_TYPE_BRIDGE || v == PCI_HEADER_TYPE_CARDBUS) { @@ -76,8 +77,8 @@ pci_probe_devices(void) if (secbus > MaxPCIBus) MaxPCIBus = secbus; } - dprintf(4, "PCI device %pP (vd=%04x:%04x c=%04x)\n" - , dev, dev->vendor, dev->device, dev->class); + dprintf(4, "PCI device %pP (vd=%04x:%04x c=%04x, irq=%d)\n" + , dev, dev->vendor, dev->device, dev->class, dev->irq); } } dprintf(1, "Found %d PCI devices (max PCI bus is %02x)\n", count, MaxPCIBus); diff --git a/src/hw/pcidevice.h b/src/hw/pcidevice.h index 225d545..eb3de39 100644 --- a/src/hw/pcidevice.h +++ b/src/hw/pcidevice.h @@ -16,6 +16,7 @@ struct pci_device { u8 prog_if, revision; u8 header_type; u8 secondary_bus; + u8 irq; // Local information on device. int have_driver; diff --git a/src/hw/rtc.h b/src/hw/rtc.h index 7bacc49..252e73a 100644 --- a/src/hw/rtc.h +++ b/src/hw/rtc.h @@ -1,15 +1,8 @@ #ifndef __RTC_H #define __RTC_H -#if CONFIG_X86 #define PORT_CMOS_INDEX 0x0070 #define PORT_CMOS_DATA 0x0071 -#elif CONFIG_PARISC -#include "parisc/hppa_hardware.h" -#define PORT_CMOS_INDEX (IDE_HPA+0x0070) -#define PORT_CMOS_DATA (IDE_HPA+0x0071) -#endif - // PORT_CMOS_INDEX nmi disable bit #define NMI_DISABLE_BIT 0x80 diff --git a/src/hw/serialio.c b/src/hw/serialio.c index 07958b3..c6cafaa 100644 --- a/src/hw/serialio.c +++ b/src/hw/serialio.c @@ -111,6 +111,7 @@ qemu_debug_preinit(void) return; /* Check if the QEMU debug output port is active */ + /* PARISC may use serial console */ if (CONFIG_DEBUG_IO && inb(GET_GLOBAL(DebugOutputPort)) != QEMU_DEBUGCON_READBACK) DebugOutputPort = 0; @@ -122,7 +123,7 @@ qemu_debug_putc(char c) { if (!CONFIG_DEBUG_IO || !runningOnQEMU()) return; - u16 port = GET_GLOBAL(DebugOutputPort); + portaddr_t port = GET_GLOBAL(DebugOutputPort); if (port) // Send character to debug port. outb(c, port); diff --git a/src/hw/usb-ohci.c b/src/hw/usb-ohci.c index 90f60e6..f8a8067 100644 --- a/src/hw/usb-ohci.c +++ b/src/hw/usb-ohci.c @@ -126,7 +126,7 @@ static void ohci_waittick(struct ohci_regs *regs) { barrier(); - struct ohci_hcca *hcca = (void*)regs->hcca; + struct ohci_hcca *hcca = (void*)readl(®s->hcca); u32 startframe = hcca->frame_no; u32 end = timer_calc(1000 * 5); for (;;) { @@ -153,7 +153,7 @@ ohci_free_pipes(struct usb_ohci_s *cntl) u32 *pos = &cntl->regs->ed_controlhead; for (;;) { - struct ohci_ed *next = (void*)*pos; + struct ohci_ed *next = (void*)le32_to_cpu(*pos); if (!next) break; struct ohci_pipe *pipe = container_of(next, struct ohci_pipe, ed); @@ -200,7 +200,7 @@ start_ohci(struct usb_ohci_s *cntl, struct ohci_hcca *hcca) // Init memory writel(&cntl->regs->ed_controlhead, 0); writel(&cntl->regs->ed_bulkhead, 0); - writel(&cntl->regs->hcca, (u32)hcca); + writel(&cntl->regs->hcca, cpu_to_le32((u32)hcca)); // Init fminterval u32 fi = oldfminterval & 0x3fff; @@ -243,10 +243,10 @@ configure_ohci(void *data) } memset(hcca, 0, sizeof(*hcca)); memset(intr_ed, 0, sizeof(*intr_ed)); - intr_ed->hwINFO = ED_SKIP; + intr_ed->hwINFO = cpu_to_le32(ED_SKIP); int i; for (i=0; i<ARRAY_SIZE(hcca->int_table); i++) - hcca->int_table[i] = (u32)intr_ed; + hcca->int_table[i] = cpu_to_le32((u32)intr_ed); int ret = start_ohci(cntl, hcca); if (ret) @@ -318,9 +318,10 @@ ohci_desc2pipe(struct ohci_pipe *pipe, struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc) { usb_desc2pipe(&pipe->pipe, usbdev, epdesc); - pipe->ed.hwINFO = (ED_SKIP | usbdev->devaddr | (pipe->pipe.ep << 7) + pipe->ed.hwINFO = cpu_to_le32( + (ED_SKIP | usbdev->devaddr | (pipe->pipe.ep << 7) | (epdesc->wMaxPacketSize << 16) - | (usbdev->speed ? ED_LOWSPEED : 0)); + | (usbdev->speed ? ED_LOWSPEED : 0))); struct usb_ohci_s *cntl = container_of( usbdev->hub->cntl, struct usb_ohci_s, usb); pipe->regs = cntl->regs; @@ -348,37 +349,37 @@ ohci_alloc_intr_pipe(struct usbdevice_s *usbdev goto err; memset(pipe, 0, sizeof(*pipe)); ohci_desc2pipe(pipe, usbdev, epdesc); - pipe->ed.hwINFO &= ~ED_SKIP; + pipe->ed.hwINFO &= cpu_to_le32(~ED_SKIP); pipe->data = data; pipe->count = count; pipe->tds = tds; struct ohci_ed *ed = &pipe->ed; - ed->hwHeadP = (u32)&tds[0]; - ed->hwTailP = (u32)&tds[count-1]; + ed->hwHeadP = cpu_to_le32((u32)&tds[0]); + ed->hwTailP = cpu_to_le32((u32)&tds[count-1]); int i; for (i=0; i<count-1; i++) { - tds[i].hwINFO = TD_DP_IN | TD_T_TOGGLE | TD_CC; - tds[i].hwCBP = (u32)data + maxpacket * i; - tds[i].hwNextTD = (u32)&tds[i+1]; - tds[i].hwBE = tds[i].hwCBP + maxpacket - 1; + tds[i].hwINFO = cpu_to_le32(TD_DP_IN | TD_T_TOGGLE | TD_CC); + tds[i].hwCBP = cpu_to_le32((u32)data + maxpacket * i); + tds[i].hwNextTD = cpu_to_le32((u32)&tds[i+1]); + tds[i].hwBE = cpu_to_le32(le32_to_cpu(tds[i].hwCBP) + maxpacket - 1); } // Add to interrupt schedule. - struct ohci_hcca *hcca = (void*)cntl->regs->hcca; + struct ohci_hcca *hcca = (void*)readl(&cntl->regs->hcca); if (frameexp == 0) { // Add to existing interrupt entry. - struct ohci_ed *intr_ed = (void*)hcca->int_table[0]; + struct ohci_ed *intr_ed = (void*)le32_to_cpu(hcca->int_table[0]); ed->hwNextED = intr_ed->hwNextED; barrier(); - intr_ed->hwNextED = (u32)ed; + intr_ed->hwNextED = cpu_to_le32((u32)ed); } else { int startpos = 1<<(frameexp-1); ed->hwNextED = hcca->int_table[startpos]; barrier(); for (i=startpos; i<ARRAY_SIZE(hcca->int_table); i+=ms) - hcca->int_table[i] = (u32)ed; + hcca->int_table[i] = cpu_to_le32((u32)ed); } return &pipe->pipe; @@ -433,7 +434,7 @@ ohci_realloc_pipe(struct usbdevice_s *usbdev, struct usb_pipe *upipe head = &cntl->regs->ed_bulkhead; pipe->ed.hwNextED = *head; barrier(); - *head = (u32)&pipe->ed; + *head = cpu_to_le32((u32)&pipe->ed); return &pipe->pipe; } @@ -442,12 +443,13 @@ wait_ed(struct ohci_ed *ed, int timeout) { u32 end = timer_calc(timeout); for (;;) { - if ((ed->hwHeadP & ~(ED_C|ED_H)) == ed->hwTailP) + if ((le32_to_cpu(ed->hwHeadP) & ~(ED_C|ED_H)) == le32_to_cpu(ed->hwTailP)) return 0; if (timer_check(end)) { warn_timeout(); - dprintf(1, "ohci ed info=%x tail=%x head=%x next=%x\n" - , ed->hwINFO, ed->hwTailP, ed->hwHeadP, ed->hwNextED); + dprintf(1, "ohci ed info=%x tail=%x head=%x next=%x\n", + le32_to_cpu(ed->hwINFO), le32_to_cpu(ed->hwTailP), + le32_to_cpu(ed->hwHeadP), le32_to_cpu(ed->hwNextED)); return -1; } yield(); @@ -464,7 +466,7 @@ ohci_send_pipe(struct usb_pipe *p, int dir, const void *cmd ASSERT32FLAT(); if (! CONFIG_USB_OHCI) return -1; - dprintf(7, "ohci_send_pipe %p\n", p); + dprintf(7, "ohci_send_pipe %p cmd=%p datasize = %d XXXXXXXXXXXXXXX\n", p, cmd, datasize); struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe); // Allocate tds on stack (with required alignment) @@ -477,10 +479,10 @@ ohci_send_pipe(struct usb_pipe *p, int dir, const void *cmd u32 toggle = 0, statuscmd = OHCI_BLF; if (cmd) { // Send setup pid on control transfers - td->hwINFO = TD_DP_SETUP | TD_T_DATA0 | TD_CC; - td->hwCBP = (u32)cmd; - td->hwNextTD = (u32)&td[1]; - td->hwBE = (u32)cmd + USB_CONTROL_SETUP_SIZE - 1; + td->hwINFO = cpu_to_le32(TD_DP_SETUP | TD_T_DATA0 | TD_CC); + td->hwCBP = cpu_to_le32((u32)cmd); + td->hwNextTD = cpu_to_le32((u32)&td[1]); + td->hwBE = cpu_to_le32((u32)cmd + USB_CONTROL_SETUP_SIZE - 1); td++; toggle = TD_T_DATA1; statuscmd = OHCI_CLF; @@ -496,10 +498,10 @@ ohci_send_pipe(struct usb_pipe *p, int dir, const void *cmd int transfer = dataend - dest; if (transfer > maxtransfer) transfer = ALIGN_DOWN(maxtransfer, maxpacket); - td->hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | toggle | TD_CC; - td->hwCBP = dest; - td->hwNextTD = (u32)&td[1]; - td->hwBE = dest + transfer - 1; + td->hwINFO = cpu_to_le32((dir ? TD_DP_IN : TD_DP_OUT) | toggle | TD_CC); + td->hwCBP = cpu_to_le32(dest); + td->hwNextTD = cpu_to_le32((u32)&td[1]); + td->hwBE = cpu_to_le32(dest + transfer - 1); td++; dest += transfer; } @@ -509,24 +511,25 @@ ohci_send_pipe(struct usb_pipe *p, int dir, const void *cmd warn_noalloc(); return -1; } - td->hwINFO = (dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC; + td->hwINFO = cpu_to_le32((dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC); td->hwCBP = 0; - td->hwNextTD = (u32)&td[1]; + td->hwNextTD = cpu_to_le32((u32)&td[1]); td->hwBE = 0; td++; } // Transfer data - pipe->ed.hwHeadP = (u32)tds | (pipe->ed.hwHeadP & ED_C); - pipe->ed.hwTailP = (u32)td; + pipe->ed.hwHeadP = cpu_to_le32((u32)tds | (le32_to_cpu(pipe->ed.hwHeadP) & ED_C)); + pipe->ed.hwTailP = cpu_to_le32((u32)td); barrier(); - pipe->ed.hwINFO &= ~ED_SKIP; + pipe->ed.hwINFO &= cpu_to_le32(~ED_SKIP); writel(&pipe->regs->cmdstatus, statuscmd); int ret = wait_ed(&pipe->ed, usb_xfer_time(p, datasize)); - pipe->ed.hwINFO |= ED_SKIP; + pipe->ed.hwINFO |= cpu_to_le32(ED_SKIP); if (ret) ohci_waittick(pipe->regs); + dprintf(7, "ohci_send_pipe ENDE XXXXXXXXXXXXXXX ret=%d\n", ret); return ret; } @@ -539,8 +542,8 @@ ohci_poll_intr(struct usb_pipe *p, void *data) struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe); struct ohci_td *tds = GET_LOWFLAT(pipe->tds); - struct ohci_td *head = (void*)(GET_LOWFLAT(pipe->ed.hwHeadP) & ~(ED_C|ED_H)); - struct ohci_td *tail = (void*)GET_LOWFLAT(pipe->ed.hwTailP); + struct ohci_td *head = (void*)(le32_to_cpu(GET_LOWFLAT(pipe->ed.hwHeadP)) & ~(ED_C|ED_H)); + struct ohci_td *tail = (void*)le32_to_cpu(GET_LOWFLAT(pipe->ed.hwTailP)); int count = GET_LOWFLAT(pipe->count); int pos = (tail - tds + 1) % count; struct ohci_td *next = &tds[pos]; @@ -556,13 +559,13 @@ ohci_poll_intr(struct usb_pipe *p, void *data) memcpy_far(GET_SEG(SS), data, SEG_LOW, LOWFLAT2LOW(intrdata), maxpacket); // Reenable this td. - SET_LOWFLAT(tail->hwINFO, TD_DP_IN | TD_T_TOGGLE | TD_CC); + SET_LOWFLAT(tail->hwINFO, cpu_to_le32(TD_DP_IN | TD_T_TOGGLE | TD_CC)); intrdata = pipedata + maxpacket * (tail-tds); - SET_LOWFLAT(tail->hwCBP, (u32)intrdata); - SET_LOWFLAT(tail->hwNextTD, (u32)next); - SET_LOWFLAT(tail->hwBE, (u32)intrdata + maxpacket - 1); + SET_LOWFLAT(tail->hwCBP, cpu_to_le32((u32)intrdata)); + SET_LOWFLAT(tail->hwNextTD, cpu_to_le32((u32)next)); + SET_LOWFLAT(tail->hwBE, cpu_to_le32((u32)intrdata + maxpacket - 1)); barrier(); - SET_LOWFLAT(pipe->ed.hwTailP, (u32)next); + SET_LOWFLAT(pipe->ed.hwTailP, cpu_to_le32((u32)next)); return 0; } diff --git a/src/hw/usb.c b/src/hw/usb.c index 38a866a..7d3e452 100644 --- a/src/hw/usb.c +++ b/src/hw/usb.c @@ -227,9 +227,9 @@ get_device_info8(struct usb_pipe *pipe, struct usb_device_descriptor *dinfo) struct usb_ctrlrequest req; req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; req.bRequest = USB_REQ_GET_DESCRIPTOR; - req.wValue = USB_DT_DEVICE<<8; + req.wValue = cpu_to_le16(USB_DT_DEVICE<<8); req.wIndex = 0; - req.wLength = 8; + req.wLength = cpu_to_le16(8); return usb_send_default_control(pipe, &req, dinfo); } @@ -241,9 +241,9 @@ get_device_config(struct usb_pipe *pipe) struct usb_ctrlrequest req; req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; req.bRequest = USB_REQ_GET_DESCRIPTOR; - req.wValue = USB_DT_CONFIG<<8; + req.wValue = cpu_to_le16(USB_DT_CONFIG<<8); req.wIndex = 0; - req.wLength = sizeof(cfg); + req.wLength = cpu_to_le16(sizeof(cfg)); int ret = usb_send_default_control(pipe, &req, &cfg); if (ret) return NULL; @@ -253,7 +253,7 @@ get_device_config(struct usb_pipe *pipe) warn_noalloc(); return NULL; } - req.wLength = cfg.wTotalLength; + req.wLength = cpu_to_le16(cfg.wTotalLength); ret = usb_send_default_control(pipe, &req, config); if (ret || config->wTotalLength != cfg.wTotalLength) { free(config); @@ -269,7 +269,7 @@ set_configuration(struct usb_pipe *pipe, u16 val) struct usb_ctrlrequest req; req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; req.bRequest = USB_REQ_SET_CONFIGURATION; - req.wValue = val; + req.wValue = cpu_to_le16(val); req.wIndex = 0; req.wLength = 0; return usb_send_default_control(pipe, &req, NULL); @@ -313,7 +313,7 @@ usb_set_address(struct usbdevice_s *usbdev) struct usb_ctrlrequest req; req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; req.bRequest = USB_REQ_SET_ADDRESS; - req.wValue = cntl->maxaddr + 1; + req.wValue = cpu_to_le16(cntl->maxaddr + 1); req.wIndex = 0; req.wLength = 0; int ret = usb_send_default_control(usbdev->defpipe, &req, NULL); @@ -245,7 +245,7 @@ set_leds(void) void VISIBLE16 handle_16(struct bregs *regs) { - debug_enter(regs, DEBUG_HDL_16); + // debug_enter(regs, DEBUG_HDL_16); if (! CONFIG_KEYBOARD) return; diff --git a/src/parisc/c3700.h b/src/parisc/c3700.h new file mode 100644 index 0000000..b32312b --- /dev/null +++ b/src/parisc/c3700.h @@ -0,0 +1,284 @@ +/* AUTO-GENERATED HEADER FILE FOR SEABIOS FIRMWARE */ +/* generated with Linux kernel */ +/* search for PARISC_QEMU_MACHINE_HEADER in Linux */ + +#define PARISC_MODEL "9000/785/C3700" + +#define PARISC_PDC_MODEL 0x5dc0, 0x481, 0x0, 0x2, 0x777c3e84, 0x100000f0, 0x8, 0xb2, 0xb2 + +#define PARISC_PDC_VERSION 0x0301 + +#define PARISC_PDC_CPUID 0x01e8 + +#define PARISC_PDC_CAPABILITIES 0x0007 + +#define PARISC_PDC_ENTRY_ORG 0xf0000018 + +#define PARISC_PDC_CACHE_INFO \ + 0xc0000, 0x91802000, 0x20000, 0x0040, 0x0c00 \ + , 0x0001, 0x180000, 0xb1802000, 0x0000, 0x0040 \ + , 0x6000, 0x0001, 0x00f0, 0xd2300, 0x0000 \ + , 0x0000, 0x0001, 0x0000, 0x0000, 0x0001 \ + , 0x0001, 0x00f0, 0xd2000, 0x0000, 0x0000 \ + , 0x0001, 0x0000, 0x0000, 0x0001, 0x0001 + + +#define HPA_fed00000_DESCRIPTION "Astro BC Runway Port" +static struct pdc_system_map_mod_info mod_info_hpa_fed00000 = { + .mod_addr = 0xfed00000, + .mod_pgs = 0x8, + .add_addrs = 0x0, +}; +static struct pdc_module_path mod_path_hpa_fed00000 = { + .path = { .flags = 0x0, .bc = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, .mod = ASTRO_BUS_MODULE }, + .layers = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } +}; +static struct pdc_iodc iodc_data_hpa_fed00000 = { + .hversion_model = 0x0058, + .hversion = 0x0020, + .spa = 0x0000, + .type = 0x000c, + .sversion_rev = 0x0000, + .sversion_model = 0x0005, + .sversion_opt = 0x0088, + .rev = 0x0000, + .dep = 0x0000, + .features = 0x0000, + .checksum = 0x0000, + .length = 0x0000, + /* pad: 0x0000, 0x0000 */ +}; +#define HPA_fed00000_num_addr 0 +#define HPA_fed00000_add_addr 0 + + +#define HPA_fed30000_DESCRIPTION "Elroy PCI Bridge" +static struct pdc_system_map_mod_info mod_info_hpa_fed30000 = { + .mod_addr = 0xfed30000, + .mod_pgs = 0x2, + .add_addrs = 0x0, +}; +static struct pdc_module_path mod_path_hpa_fed30000 = { + .path = { .flags = 0x0, .bc = { 0xff, 0xff, 0xff, 0xff, 0xff, ASTRO_BUS_MODULE }, .mod = 0x0 }, + .layers = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } +}; +static struct pdc_iodc iodc_data_hpa_fed30000 = { + .hversion_model = 0x0078, + .hversion = 0x0020, + .spa = 0x0000, + .type = 0x000d, + .sversion_rev = 0x0000, + .sversion_model = 0x0005, + .sversion_opt = 0x0000, + .rev = 0x0000, + .dep = 0x0000, + .features = 0x0000, + .checksum = 0x0000, + .length = 0x0000, + /* pad: 0x0000, 0x0000 */ +}; +#define HPA_fed30000_num_addr 0 +#define HPA_fed30000_add_addr 0 + + +#define HPA_fed32000_DESCRIPTION "Elroy PCI Bridge" +static struct pdc_system_map_mod_info mod_info_hpa_fed32000 = { + .mod_addr = 0xfed32000, + .mod_pgs = 0x2, + .add_addrs = 0x0, +}; +static struct pdc_module_path mod_path_hpa_fed32000 = { + .path = { .flags = 0x0, .bc = { 0xff, 0xff, 0xff, 0xff, 0xff, ASTRO_BUS_MODULE }, .mod = 0x1 }, + .layers = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } +}; +static struct pdc_iodc iodc_data_hpa_fed32000 = { + .hversion_model = 0x0078, + .hversion = 0x0020, + .spa = 0x0000, + .type = 0x000d, + .sversion_rev = 0x0000, + .sversion_model = 0x0005, + .sversion_opt = 0x0000, + .rev = 0x0000, + .dep = 0x0000, + .features = 0x0000, + .checksum = 0x0000, + .length = 0x0000, + /* pad: 0x0000, 0x0000 */ +}; +#define HPA_fed32000_num_addr 0 +#define HPA_fed32000_add_addr 0 + + +#define HPA_fed38000_DESCRIPTION "Elroy PCI Bridge" +static struct pdc_system_map_mod_info mod_info_hpa_fed38000 = { + .mod_addr = 0xfed38000, + .mod_pgs = 0x2, + .add_addrs = 0x0, +}; +static struct pdc_module_path mod_path_hpa_fed38000 = { + .path = { .flags = 0x0, .bc = { 0xff, 0xff, 0xff, 0xff, 0xff, ASTRO_BUS_MODULE }, .mod = 0x4 }, + .layers = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } +}; +static struct pdc_iodc iodc_data_hpa_fed38000 = { + .hversion_model = 0x0078, + .hversion = 0x0020, + .spa = 0x0000, + .type = 0x000d, + .sversion_rev = 0x0000, + .sversion_model = 0x0005, + .sversion_opt = 0x0000, + .rev = 0x0000, + .dep = 0x0000, + .features = 0x0000, + .checksum = 0x0000, + .length = 0x0000, + /* pad: 0x0000, 0x0000 */ +}; +#define HPA_fed38000_num_addr 0 +#define HPA_fed38000_add_addr 0 + + +#define HPA_fed3c000_DESCRIPTION "Elroy PCI Bridge" +static struct pdc_system_map_mod_info mod_info_hpa_fed3c000 = { + .mod_addr = 0xfed3c000, + .mod_pgs = 0x2, + .add_addrs = 0x0, +}; +static struct pdc_module_path mod_path_hpa_fed3c000 = { + .path = { .flags = 0x0, .bc = { 0xff, 0xff, 0xff, 0xff, 0xff, ASTRO_BUS_MODULE }, .mod = 0x6 }, + .layers = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } +}; +static struct pdc_iodc iodc_data_hpa_fed3c000 = { + .hversion_model = 0x0078, + .hversion = 0x0020, + .spa = 0x0000, + .type = 0x000d, + .sversion_rev = 0x0000, + .sversion_model = 0x0005, + .sversion_opt = 0x0000, + .rev = 0x0000, + .dep = 0x0000, + .features = 0x0000, + .checksum = 0x0000, + .length = 0x0000, + /* pad: 0x0000, 0x0000 */ +}; +#define HPA_fed3c000_num_addr 0 +#define HPA_fed3c000_add_addr 0 + + +#define HPA_fffa0000_DESCRIPTION "Allegro W2" +static struct pdc_system_map_mod_info mod_info_hpa_fffa0000 = { + .mod_addr = CPU_HPA /* 0xfffa0000 */, + .mod_pgs = 0x1, + .add_addrs = 0x0, +}; +static struct pdc_module_path mod_path_hpa_fffa0000 = { + .path = { .flags = 0x0, .bc = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, .mod = 0x10 }, + .layers = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } +}; +static struct pdc_iodc iodc_data_hpa_fffa0000 = { +#if 0 // original C3700: + .hversion_model = 0x005d, + .hversion = 0x00c0, + .spa = 0x0000, + .type = 0x0040, + .sversion_rev = 0x0000, + .sversion_model = 0x0002, + .sversion_opt = 0x0040, +#else + /* this is from B160L */ + .hversion_model = 0x0050, + .hversion = 0x0020, + .spa = 0x0000, + .type = 0x0040, + .sversion_rev = 0x0000, + .sversion_model = 0x0002, + .sversion_opt = 0x0040, +#endif + .rev = 0x0000, + .dep = 0x0000, + .features = 0x0000, + .checksum = 0x0000, + .length = 0x0000, + /* pad: 0x0000, 0x0000 */ +}; +#define HPA_fffa0000_num_addr 0 +#define HPA_fffa0000_add_addr 0 + + +#define HPA_fed10200_DESCRIPTION "Memory" +static struct pdc_system_map_mod_info mod_info_hpa_fed10200 = { + .mod_addr = 0xfed10200, + .mod_pgs = 0x8, + .add_addrs = 0x0, +}; +static struct pdc_module_path mod_path_hpa_fed10200 = { + .path = { .flags = 0x0, .bc = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, .mod = 0x2f }, + .layers = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } +}; +static struct pdc_iodc iodc_data_hpa_fed10200 = { + .hversion_model = 0x0009, + .hversion = 0x00c0, + .spa = 0x001f, + .type = 0x0041, + .sversion_rev = 0x0000, + .sversion_model = 0x0004, + .sversion_opt = 0x0080, + .rev = 0x0000, + .dep = 0x0000, + .features = 0x0000, + .checksum = 0x0000, + .length = 0x0000, + /* pad: 0x0000, 0x0000 */ +}; +#define HPA_fed10200_num_addr 0 +#define HPA_fed10200_add_addr 0 + + + +#define PARISC_DEVICE_LIST \ + { .hpa = 0xfed00000,\ + .iodc = &iodc_data_hpa_fed00000,\ + .mod_info = &mod_info_hpa_fed00000,\ + .mod_path = &mod_path_hpa_fed00000,\ + .num_addr = HPA_fed00000_num_addr,\ + .add_addr = { HPA_fed00000_add_addr } },\ + { .hpa = 0xfed30000,\ + .iodc = &iodc_data_hpa_fed30000,\ + .mod_info = &mod_info_hpa_fed30000,\ + .mod_path = &mod_path_hpa_fed30000,\ + .num_addr = HPA_fed30000_num_addr,\ + .add_addr = { HPA_fed30000_add_addr } },\ + { .hpa = 0xfed32000,\ + .iodc = &iodc_data_hpa_fed32000,\ + .mod_info = &mod_info_hpa_fed32000,\ + .mod_path = &mod_path_hpa_fed32000,\ + .num_addr = HPA_fed32000_num_addr,\ + .add_addr = { HPA_fed32000_add_addr } },\ + { .hpa = 0xfed38000,\ + .iodc = &iodc_data_hpa_fed38000,\ + .mod_info = &mod_info_hpa_fed38000,\ + .mod_path = &mod_path_hpa_fed38000,\ + .num_addr = HPA_fed38000_num_addr,\ + .add_addr = { HPA_fed38000_add_addr } },\ + { .hpa = 0xfed3c000,\ + .iodc = &iodc_data_hpa_fed3c000,\ + .mod_info = &mod_info_hpa_fed3c000,\ + .mod_path = &mod_path_hpa_fed3c000,\ + .num_addr = HPA_fed3c000_num_addr,\ + .add_addr = { HPA_fed3c000_add_addr } },\ + { .hpa = 0xfed10200,\ + .iodc = &iodc_data_hpa_fed10200,\ + .mod_info = &mod_info_hpa_fed10200,\ + .mod_path = &mod_path_hpa_fed10200,\ + .num_addr = HPA_fed10200_num_addr,\ + .add_addr = { HPA_fed10200_add_addr } },\ + { .hpa = CPU_HPA /* XXX: 0xfffa0000 */ ,\ + .iodc = &iodc_data_hpa_fffa0000,\ + .mod_info = &mod_info_hpa_fffa0000,\ + .mod_path = &mod_path_hpa_fffa0000,\ + .num_addr = HPA_fffa0000_num_addr,\ + .add_addr = { HPA_fffa0000_add_addr } },\ + { 0, } diff --git a/src/parisc/hppa.h b/src/parisc/hppa.h index 0ac0992..e83ebb8 100644 --- a/src/parisc/hppa.h +++ b/src/parisc/hppa.h @@ -3,8 +3,8 @@ /* this file is included by x86.h */ /* version number of this SeaBIOS firmware */ -#define SEABIOS_HPPA_VERSION 9 -#define SEABIOS_HPPA_VERSION_STR "9" +#define SEABIOS_HPPA_VERSION 10 +#define SEABIOS_HPPA_VERSION_STR "10" #include "parisc/hppa_hardware.h" @@ -204,9 +204,20 @@ static inline u32 ror(u32 word, unsigned int shift) return (word >> (shift & 31)) | (word << ((-shift) & 31)); } +extern char has_astro; /* false for B160L machine with Dino PCI chip */ +extern unsigned long hppa_port_pci_cmd; +extern unsigned long hppa_port_pci_data; + + #define pci_ioport_addr(port) ((port >= 0x1000) && (port < FIRMWARE_START)) +#define is_astro_ioport(port) (has_astro && (port < IOS_DIST_BASE_SIZE)) + +#define astro_ioport_addr(port) ((void *)(portaddr_t)(IOS_DIST_BASE_ADDR + port)) static inline void outl(u32 value, portaddr_t port) { + if (is_astro_ioport(port)) + *(volatile u32 *)(astro_ioport_addr(port)) = value; + else if (!pci_ioport_addr(port)) { *(volatile u32 *)(port) = be32_to_cpu(value); } else { @@ -218,6 +229,9 @@ static inline void outl(u32 value, portaddr_t port) { } static inline void outw(u16 value, portaddr_t port) { + if (is_astro_ioport(port)) + *(volatile u16 *)(astro_ioport_addr(port)) = value; + else if (!pci_ioport_addr(port)) { *(volatile u16 *)(port) = be16_to_cpu(value); } else { @@ -229,6 +243,9 @@ static inline void outw(u16 value, portaddr_t port) { } static inline void outb(u8 value, portaddr_t port) { + if (is_astro_ioport(port)) + *(volatile u8 *)(astro_ioport_addr(port)) = value; + else if (!pci_ioport_addr(port)) { *(volatile u8 *)(port) = value; } else { @@ -240,7 +257,10 @@ static inline void outb(u8 value, portaddr_t port) { } static inline u8 inb(portaddr_t port) { - if (!pci_ioport_addr(port)) { + if (is_astro_ioport(port)) + return *(volatile u8 *)(astro_ioport_addr(port)); + else + if (has_astro || !pci_ioport_addr(port)) { return *(volatile u8 *)(port); } else { /* write PCI I/O address to Dino's PCI_CONFIG_ADDR */ @@ -251,6 +271,9 @@ static inline u8 inb(portaddr_t port) { } static inline u16 inw(portaddr_t port) { + if (is_astro_ioport(port)) + return *(volatile u16 *)(astro_ioport_addr(port)); + else if (!pci_ioport_addr(port)) { return *(volatile u16 *)(port); } else { @@ -261,6 +284,9 @@ static inline u16 inw(portaddr_t port) { } } static inline u32 inl(portaddr_t port) { + if (is_astro_ioport(port)) + return *(volatile u32 *)(astro_ioport_addr(port)); + else if (!pci_ioport_addr(port)) { return *(volatile u32 *)(port); } else { @@ -321,13 +347,15 @@ static inline void smp_wmb(void) { barrier(); } +/* readX()/writeX() do byteswapping */ + static inline void writel(void *addr, u32 val) { barrier(); - *(volatile u32 *)addr = val; + *(volatile u32 *)addr = cpu_to_le32(val); } static inline void writew(void *addr, u16 val) { barrier(); - *(volatile u16 *)addr = val; + *(volatile u16 *)addr = cpu_to_le16(val); } static inline void writeb(void *addr, u8 val) { barrier(); @@ -336,17 +364,17 @@ static inline void writeb(void *addr, u8 val) { static inline u64 readq(const void *addr) { u64 val = *(volatile const u64 *)addr; barrier(); - return val; + return le64_to_cpu(val); } static inline u32 readl(const void *addr) { u32 val = *(volatile const u32 *)addr; barrier(); - return val; + return le32_to_cpu(val); } static inline u16 readw(const void *addr) { u16 val = *(volatile const u16 *)addr; barrier(); - return val; + return le16_to_cpu(val); } static inline u8 readb(const void *addr) { u8 val = *(volatile const u8 *)addr; @@ -354,6 +382,27 @@ static inline u8 readb(const void *addr) { return val; } +/* gsc_readX()/gsc_writeX() do no byteswapping */ + +static inline void gsc_writel(void *addr, u32 val) { + barrier(); + *(volatile u32 *)addr = val; +} +static inline void gsc_writeb(void *addr, u8 val) { + barrier(); + *(volatile u8 *)addr = val; +} +static inline u32 gsc_readl(const void *addr) { + u32 val = *(volatile const u32 *)addr; + barrier(); + return val; +} +static inline u8 gsc_readb(const void *addr) { + u8 val = *(volatile const u8 *)addr; + barrier(); + return val; +} + // FLASH_FLOPPY not supported #define GDT_CODE (0) #define GDT_DATA (0) @@ -378,5 +427,9 @@ static inline void wrmsr(u32 index, u64 val) // x86.c void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); +// pci.c +unsigned long elroy_offset(u16 bdf); +void *elroy_port(unsigned long port, unsigned long offs); + #endif // !__ASSEMBLY__ #endif diff --git a/src/parisc/hppa_hardware.h b/src/parisc/hppa_hardware.h index c036d46..cc5ea89 100644 --- a/src/parisc/hppa_hardware.h +++ b/src/parisc/hppa_hardware.h @@ -29,15 +29,14 @@ #define MEMORY_HPA 0xfffff000 #define PCI_HPA DINO_HPA /* PCI bus */ -#define IDE_HPA 0xf9000000 /* Boot disc controller */ /* offsets to DINO HPA: */ #define DINO_PCI_ADDR 0x064 #define DINO_CONFIG_DATA 0x068 #define DINO_IO_DATA 0x06c -#define PORT_PCI_CMD (PCI_HPA + DINO_PCI_ADDR) -#define PORT_PCI_DATA (PCI_HPA + DINO_CONFIG_DATA) +#define PORT_PCI_CMD hppa_port_pci_cmd +#define PORT_PCI_DATA hppa_port_pci_data #define FW_CFG_IO_BASE 0xfffa0000 @@ -50,4 +49,17 @@ #define CPU_HPA_CR_REG 7 /* store CPU HPA in cr7 (SeaBIOS internal) */ #define PIM_STORAGE_SIZE 600 /* storage size of pdc_pim_toc_struct (64bit) */ + +#define ASTRO_BUS_MODULE 0x0a /* original: 0x0a, use 0 ? */ + +/* ASTRO Memory and I/O regions */ +#define LMMIO_DIST_BASE_ADDR 0xf4000000UL +#define LMMIO_DIST_BASE_SIZE 0x4000000UL + +#define IOS_DIST_BASE_ADDR 0xfee00000UL +#define IOS_DIST_BASE_SIZE 0x10000UL + +#define ROPES_PER_IOC 8 /* per Ike half or Pluto/Astro */ + + #endif diff --git a/src/parisc/lasips2.c b/src/parisc/lasips2.c index e86cbff..a7bb9fe 100644 --- a/src/parisc/lasips2.c +++ b/src/parisc/lasips2.c @@ -14,14 +14,15 @@ #include "string.h" #include "lasips2.h" + int lasips2_kbd_in(char *c, int max) { struct bregs regs; volatile int count = 0; // check if PS2 reported new keys, if so queue them up. - while((readl(LASIPS2_KBD_STATUS) & LASIPS2_KBD_STATUS_RBNE)) { - process_key(readb(LASIPS2_KBD_DATA)); + while((gsc_readl(LASIPS2_KBD_STATUS) & LASIPS2_KBD_STATUS_RBNE)) { + process_key(gsc_readb(LASIPS2_KBD_DATA)); } while(count < max) { @@ -50,13 +51,13 @@ int ps2_kbd_command(int command, u8 *param) int lasips2_command(u16 cmd) { - while(readl(LASIPS2_KBD_STATUS) & LASIPS2_KBD_STATUS_TBNE) + while(gsc_readl(LASIPS2_KBD_STATUS) & LASIPS2_KBD_STATUS_TBNE) udelay(10); writeb(LASIPS2_KBD_DATA, cmd & 0xff); - while(!(readl(LASIPS2_KBD_STATUS) & LASIPS2_KBD_STATUS_RBNE)) + while(!(gsc_readl(LASIPS2_KBD_STATUS) & LASIPS2_KBD_STATUS_RBNE)) udelay(10); - return readb(LASIPS2_KBD_DATA); + return gsc_readb(LASIPS2_KBD_DATA); } void ps2port_setup(void) diff --git a/src/parisc/machine-create.h b/src/parisc/machine-create.h new file mode 100644 index 0000000..8b15f3a --- /dev/null +++ b/src/parisc/machine-create.h @@ -0,0 +1,20 @@ +static struct machine_info CONCAT(machine_, MACHINE) = { + .pdc_modelstr = PARISC_MODEL, + .pdc_model = { PARISC_PDC_MODEL }, + .pdc_version = PARISC_PDC_VERSION, + .pdc_cpuid = PARISC_PDC_CPUID, + .pdc_caps = PARISC_PDC_CAPABILITIES, + .pdc_entry = PARISC_PDC_ENTRY_ORG, + .pdc_cache_info = { PARISC_PDC_CACHE_INFO }, + .device_list = { PARISC_DEVICE_LIST }, +}; + +#undef MACHINE +#undef PARISC_MODEL +#undef PARISC_PDC_MODEL +#undef PARISC_PDC_VERSION +#undef PARISC_PDC_CPUID +#undef PARISC_PDC_CAPABILITIES +#undef PARISC_PDC_ENTRY_ORG +#undef PARISC_PDC_CACHE_INFO +#undef PARISC_DEVICE_LIST diff --git a/src/parisc/malloc.c b/src/parisc/malloc.c index c4e46e6..b4f56d5 100644 --- a/src/parisc/malloc.c +++ b/src/parisc/malloc.c @@ -35,7 +35,7 @@ malloc_palloc(struct zone_s *zone, u32 size, u32 align) data = stackptr; stackptr += size; - dprintf(8, "size=%d align=%d ret=0x%lx\n" , size, align, data); + // dprintf(9, "malloc: size=%d align=%d ret=0x%lx\n" , size, align, data); return data; } diff --git a/src/parisc/parisc.c b/src/parisc/parisc.c index 3eaa218..33dcb3d 100644 --- a/src/parisc/parisc.c +++ b/src/parisc/parisc.c @@ -4,6 +4,10 @@ // Copyright (C) 2019 Sven Schnelle <svens@stackframe.org> // // This file may be distributed under the terms of the GNU LGPLv3 license. +// +// Example command line: +// ./qemu-system-hppa -drive file=../qemu-images/hdd.img -kernel vmlinux -append root=/dev/sda5 cryptomgr.notests console=ttyS0 earlycon=pdc -accel tcg,thread=multi,one-insn-per-tb=off -serial mon:stdio -smp cpus=1 -snapshot -nographic -machine B160L +// /qemu-system-hppa -drive file=../qemu-images/hdd.img -kernel vmlinux -append "root=/dev/sda5 cryptomgr.notests console=ttyS0 earlycon=pdc" -accel tcg,thread=multi,one-insn-per-tb=off -serial mon:stdio -smp cpus=1 -nographic -machine C3700 -device pci-serial-4x -device pci-ohci -device usb-tablet -device ES1370 -snapshot # -fw_cfg opt/pdc_debug,string=255 # -d trace:serial\* # ,mmu,trace:serial\*,trace:iosapic\*,trace:elroy\*,trace:astro\*,trace:pci\* #include "biosvar.h" // GET_BDA #include "bregs.h" // struct bregs @@ -19,13 +23,13 @@ #include "hw/pci_ids.h" // PCI IDs #include "hw/pci_regs.h" // PCI_BASE_ADDRESS_0 #include "hw/ata.h" +#include "hw/usb-ohci.h" #include "hw/blockcmd.h" // scsi_is_ready() #include "hw/rtc.h" #include "fw/paravirt.h" // PlatformRunningOn #include "vgahw.h" #include "parisc/hppa_hardware.h" // DINO_UART_BASE #include "parisc/pdc.h" -#include "parisc/b160l.h" #include "parisc/sticore.h" #include "parisc/lasips2.h" @@ -118,6 +122,12 @@ int pdc_console; int sti_font; char qemu_version[16] = "unknown version"; +char qemu_machine[16] = "B160L"; +char cpu_bit_width; +char has_astro; +unsigned long hppa_port_pci_cmd = (PCI_HPA + DINO_PCI_ADDR); +unsigned long hppa_port_pci_data = (PCI_HPA + DINO_CONFIG_DATA); + /* Want PDC boot menu? Enable via qemu "-boot menu=on" option. */ unsigned int show_boot_menu; @@ -173,6 +183,12 @@ static unsigned int chassis_code = 0; int powersw_nop; int *powersw_ptr; +/* + * Real time clock emulation + * Either LASI or Astro will provide access to an emulated RTC clock. + */ +int *rtc_ptr = (int *) (unsigned long) LASI_RTC_HPA; + void __VISIBLE __noreturn hlt(void) { if (pdc_debug) @@ -207,8 +223,10 @@ void __VISIBLE __noreturn reset(void) #undef BUG_ON #define BUG_ON(cond) \ - if (unlikely(cond)) \ -{ printf("ERROR in %s:%d\n", __FUNCTION__, __LINE__); hlt(); } + if (unlikely(cond)) { \ + printf("*ERROR* in SeaBIOS-hppa-v%d:\n%s:%d\n", SEABIOS_HPPA_VERSION, \ + __FUNCTION__, __LINE__); hlt(); \ + } void flush_data_cache(char *start, size_t length) { @@ -252,6 +270,8 @@ static struct pdc_module_path mod_path_emulated_drives = { * FIRMWARE IO Dependent Code (IODC) HANDLER ********************************************************/ +#define MAX_DEVICES HPPA_MAX_CPUS+16 + typedef struct { unsigned long hpa; struct pdc_iodc *iodc; @@ -259,21 +279,46 @@ typedef struct { struct pdc_module_path *mod_path; int num_addr; int add_addr[5]; + struct pci_device *pci; + unsigned long pci_addr; } hppa_device_t; -static hppa_device_t parisc_devices[HPPA_MAX_CPUS+16] = { PARISC_DEVICE_LIST }; +static hppa_device_t *find_hpa_device(unsigned long hpa); + +#define CONCAT2(a, b) a ## b +#define CONCAT(a, b) CONCAT2(a, b) + +struct machine_info { + char pdc_modelstr[16]; + struct pdc_model pdc_model; + int pdc_version; + int pdc_cpuid; + int pdc_caps; + int pdc_entry; + unsigned long pdc_cache_info[30]; + hppa_device_t device_list[MAX_DEVICES]; +}; + + +/* create machine definitions */ +#define MACHINE B160L +#include "parisc/b160l.h" +#include "parisc/machine-create.h" + +#define MACHINE C3700 +#include "parisc/c3700.h" +#include "parisc/machine-create.h" + +struct machine_info *current_machine = &machine_B160L; + +static hppa_device_t *parisc_devices = machine_B160L.device_list; #define PARISC_KEEP_LIST \ - GSC_HPA,\ - DINO_HPA,\ DINO_UART_HPA,\ /* DINO_SCSI_HPA, */ \ - LASI_HPA, \ LASI_UART_HPA, \ LASI_LAN_HPA, \ LASI_LPT_HPA, \ - CPU_HPA,\ - MEMORY_HPA,\ LASI_GFX_HPA,\ LASI_PS2KBD_HPA, \ LASI_PS2MOU_HPA, \ @@ -291,7 +336,6 @@ static const char *hpa_name(unsigned long hpa) DO(DINO_SCSI_HPA) DO(CPU_HPA) DO(MEMORY_HPA) - DO(IDE_HPA) DO(LASI_HPA) DO(LASI_UART_HPA) DO(LASI_SCSI_HPA) @@ -328,20 +372,109 @@ static const char *hpa_name(unsigned long hpa) return "UNKNOWN HPA"; } +int HPA_is_astro_ioport(unsigned long hpa) +{ + if (!has_astro) + return 0; + return ((hpa - IOS_DIST_BASE_ADDR) < IOS_DIST_BASE_SIZE); +} + +int HPA_is_astro_mmio(unsigned long hpa) +{ + if (!has_astro) + return 0; + return ((hpa - LMMIO_DIST_BASE_ADDR) < LMMIO_DIST_BASE_SIZE); +} + +struct pci_device *find_pci_from_HPA(unsigned long hpa) +{ + struct pci_device *pci = NULL; + int ioport; + + if (HPA_is_astro_ioport(hpa)) { + ioport = 1; + hpa -= IOS_DIST_BASE_ADDR; + } else if (HPA_is_astro_mmio(hpa)) + ioport = 0; + else + return NULL; + + foreachpci(pci) { + int i; + for (i = 0; i < 6; i++) { + unsigned long addr = PCI_BASE_ADDRESS_0 + 4*i; + unsigned long mem; + mem = pci_config_readl(pci->bdf, addr); + if ((mem & PCI_BASE_ADDRESS_SPACE_IO) && + ((mem & PCI_BASE_ADDRESS_IO_MASK) == hpa) && + (ioport == 1)) + return pci; /* found ioport */ + if (((mem & PCI_BASE_ADDRESS_SPACE_IO) == 0) && + ((mem & PCI_BASE_ADDRESS_MEM_MASK) == hpa) && + (ioport == 0)) + return pci; /* found memaddr */ + } + } + dprintf(1, "No PCI device found for HPA %lx\n", hpa); + return NULL; +} + +int DEV_is_storage_device(hppa_device_t *dev) +{ + BUG_ON(!dev); + if (dev->pci) + return (dev->pci->class == PCI_CLASS_STORAGE_SCSI); + return ((dev->iodc->type & 0xf) == 0x04); /* HPHW_A_DMA */ +} + +int DEV_is_serial_device(hppa_device_t *dev) +{ + BUG_ON(!dev); + if (dev->pci) + return (dev->pci->class == PCI_CLASS_COMMUNICATION_SERIAL); + return ((dev->iodc->type & 0xf) == 0x0a); /* HPHW_FIO */ +} + int HPA_is_serial_device(unsigned long hpa) { - return (hpa == DINO_UART_HPA) || (hpa == LASI_UART_HPA); + hppa_device_t *dev; + + dev = find_hpa_device(hpa); + if (!dev) + return 0; + return DEV_is_serial_device(dev); +} + +int DEV_is_network_device(hppa_device_t *dev) +{ + BUG_ON(!dev); + if (dev->pci) + return (dev->pci->class == PCI_CLASS_NETWORK_ETHERNET); + return ((dev->iodc->type & 0xf) == 0x0a); /* HPHW_FIO */ } -int HPA_is_storage_device(unsigned long hpa) +static int HPA_is_LASI_keyboard(unsigned long hpa) { - return (hpa == DINO_SCSI_HPA) || (hpa == IDE_HPA) || (hpa == LASI_SCSI_HPA); + return !has_astro && (hpa == LASI_PS2KBD_HPA); } -int HPA_is_keyboard_device(unsigned long hpa) +#if 0 +static int HPA_is_keyboard_device(unsigned long hpa) { - return (hpa == LASI_PS2KBD_HPA); + struct pci_device *pci; + int ret; + + if (HPA_is_LASI_keyboard(hpa)) + return 1; + pci = find_pci_from_HPA(hpa); + if (!pci) + return 0; + ret = pci->class == PCI_CLASS_COMMUNICATION_SERIAL || + pci->class == PCI_CLASS_INPUT_KEYBOARD; + dprintf(1, "PCI: is_keyboard? %pP -> %s\n", pci, ret?"Yes":"no"); + return ret; } +#endif #define GFX_NUM_PAGES 0x2000 int HPA_is_graphics_device(unsigned long hpa) @@ -353,12 +486,143 @@ int HPA_is_graphics_device(unsigned long hpa) static const char *hpa_device_name(unsigned long hpa, int output) { return HPA_is_graphics_device(hpa) ? "GRAPHICS(1)" : - HPA_is_keyboard_device(hpa) ? "PS2" : + HPA_is_LASI_keyboard(hpa) ? "PS2" : ((hpa + 0x800) == PORT_SERIAL1) ? "SERIAL_1.9600.8.none" : "SERIAL_2.9600.8.none"; } -static unsigned long keep_list[] = { PARISC_KEEP_LIST }; +void make_module_path_from_pcidev(struct pci_device *pci, + struct pdc_module_path *p) +{ + memset(p, 0, sizeof(*p)); + memset(&p->path.bc, 0xff, sizeof(p->path.bc)); + + switch (pci->class) { + case PCI_CLASS_COMMUNICATION_SERIAL: + case PCI_CLASS_NETWORK_ETHERNET: + case PCI_CLASS_STORAGE_SCSI: + case PCI_CLASS_SERIAL_USB: + default: +#if 0 +static struct pdc_module_path mod_path_hpa_fed3c000 = { // SCSI + .path = { .flags = 0x0, .bc = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xa }, .mod = 0x6 }, + .layers = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } +#endif + p->path.bc[3] = has_astro ? ASTRO_BUS_MODULE : 0x08; /* astro or dino */ + p->path.bc[4] = 0; // elroy index (0,1,4,6) == PCI Bus number (0,1,2,3) + p->path.bc[5] = pci->bdf >> 3; /* slot */ + p->path.mod = pci->bdf & 0x07; /* function */ + break; + } +} + +void make_iodc_from_pcidev(struct pci_device *pci, + struct pdc_iodc *p) +{ + memset(p, 0, sizeof(*p)); + p->hversion_model = 0x0058; + p->hversion = 0x0020; + p->sversion_model = 0; + p->sversion_opt = 0; + p->rev = 0x0099; + p->features = 0x0001; + p->length = 1; + + switch (pci->class) { + case PCI_CLASS_STORAGE_SCSI: + p->type = 0x0084; + break; + case PCI_CLASS_COMMUNICATION_SERIAL: + case PCI_CLASS_NETWORK_ETHERNET: + case PCI_CLASS_SERIAL_USB: + default: + p->type = 0x008a; + break; + } +}; + +void make_modinfo_from_pcidev(struct pci_device *pci, + struct pdc_system_map_mod_info *p, unsigned long pfa) +{ + memset(p, 0, sizeof(*p)); + p->mod_addr = pfa; + p->mod_pgs = 0; + p->add_addrs = HPA_is_graphics_device(pfa) ? GFX_NUM_PAGES : 0; +}; + +#define MAX_PCI_DEVICES 10 +static int curr_pci_devices; /* current number of PCI devices in list */ +static hppa_device_t hppa_pci_devices[MAX_PCI_DEVICES]; +static struct pdc_iodc hppa_pci_iodc[MAX_PCI_DEVICES]; +static struct pdc_system_map_mod_info hppa_pci_mod_info[MAX_PCI_DEVICES]; +static struct pdc_module_path hppa_pci_mod_path[MAX_PCI_DEVICES]; + + +/* create table of PFA (PCI Function address), similiar to HPA */ +static void hppa_pci_build_devices_list(void) +{ + struct pci_device *pci; + + memset(&hppa_pci_devices, 0, sizeof(hppa_pci_devices)); + + curr_pci_devices = 0; + + dprintf(1, "\n PCI DEVICE LIST PFA TABLE\n"); + foreachpci(pci) { + unsigned long pfa, offs; + hppa_device_t *pdev = &hppa_pci_devices[curr_pci_devices]; + + offs = elroy_offset(pci->bdf); + BUG_ON(offs == -1UL); + pfa = (unsigned long) elroy_port(0, offs); + pfa += pci->bdf << 8; + dprintf(1, "PCI device #%d %pP bdf 0x%x at pfa 0x%lx\n", curr_pci_devices, pci, pci->bdf, pfa); + + pdev->hpa = pfa; + pdev->iodc = &hppa_pci_iodc[curr_pci_devices]; + pdev->mod_info = &hppa_pci_mod_info[curr_pci_devices]; + pdev->mod_path = &hppa_pci_mod_path[curr_pci_devices]; + pdev->num_addr = 0; + pdev->pci = pci; + + make_iodc_from_pcidev(pci, pdev->iodc); + make_modinfo_from_pcidev(pci, pdev->mod_info, pfa); + make_module_path_from_pcidev(pci, pdev->mod_path); + + curr_pci_devices++; + BUG_ON(curr_pci_devices >= MAX_PCI_DEVICES); + } +} + +static hppa_device_t *find_hpa_device(unsigned long hpa) +{ + int i; + + /* search classical HPPA devices */ + if (hpa) + for (i = 0; i < (MAX_DEVICES-1); i++) { + if (hpa == parisc_devices[i].hpa) + return &parisc_devices[i]; + if (!parisc_devices[i].hpa) + break; + } + + /* search PCI devices */ + for (i = 0; i < curr_pci_devices; i++) { + if (hpa == hppa_pci_devices[i].hpa) + return &hppa_pci_devices[i]; + } + return NULL; +} + +static void print_mod_path(struct pdc_module_path *p) +{ + dprintf(1, "PATH %d:%d:%d:%d:%d:%d.%d$%d ", p->path.bc[0], p->path.bc[1], + p->path.bc[2],p->path.bc[3],p->path.bc[4],p->path.bc[5], + p->path.mod, p->layers[0]); +} + +static unsigned long keep_list[20] = { PARISC_KEEP_LIST }; static void remove_from_keep_list(unsigned long hpa) { @@ -384,6 +648,33 @@ static int keep_this_hpa(unsigned long hpa) return 0; } +/* walk all machine devices and add generic ones to the keep_list[] */ +static int keep_add_generic_devices(void) +{ + hppa_device_t *dev = current_machine->device_list; + int i = 0; + + /* search end of list */ + while (keep_list[i]) i++; + + while (dev->hpa) { + switch (dev->iodc->type) { + case 0x0007: /* GSC+ Port bridge */ + case 0x004d: /* Dino PCI bridge */ + case 0x004b: /* Core Bus adapter (LASI) */ + case 0x0040: /* CPU */ + case 0x0041: /* Memory */ + case 0x000d: /* Elroy PCI bridge */ + case 0x000c: /* Runway port */ + keep_list[i++] = dev->hpa; + } + dev++; + } + BUG_ON(i >= ARRAY_SIZE(keep_list)); + + return 0; +} + /* Rebuild hardware list and drop all devices which are not listed in * PARISC_KEEP_LIST. Generate num_cpus CPUs. */ static void remove_parisc_devices(unsigned int num_cpus) @@ -445,28 +736,14 @@ static void remove_parisc_devices(unsigned int num_cpus) t++; } - BUG_ON(t > ARRAY_SIZE(parisc_devices)); + BUG_ON(t > MAX_DEVICES); - while (t < ARRAY_SIZE(parisc_devices)) { - memset(&parisc_devices[t], 0, sizeof(parisc_devices[0])); + while (t < MAX_DEVICES) { + memset(&parisc_devices[t], 0, sizeof(*parisc_devices)); t++; } } -static int find_hpa_index(unsigned long hpa) -{ - int i; - if (!hpa) - return -1; - for (i = 0; i < (ARRAY_SIZE(parisc_devices)-1); i++) { - if (hpa == parisc_devices[i].hpa) - return i; - if (!parisc_devices[i].hpa) - return -1; - } - return -1; -} - static int compare_module_path(struct pdc_module_path *path, struct pdc_module_path *search, int check_layers) @@ -494,27 +771,71 @@ static hppa_device_t *find_hppa_device_by_path(struct pdc_module_path *search, unsigned long *index, int check_layers) { hppa_device_t *dev; - int i; + int i, nr = 0; - for (i = 0; i < (ARRAY_SIZE(parisc_devices)-1); i++) { + for (i = 0; i < (MAX_DEVICES-1); i++) { dev = parisc_devices + i; if (!dev->hpa) continue; if (!compare_module_path(dev->mod_path, search, check_layers)) { - *index = i; + *index = nr; + return dev; + } + nr++; + } + + /* search PCI devices */ + for (i = 0; i < curr_pci_devices; i++) { + dev = hppa_pci_devices + i; + if (!compare_module_path(dev->mod_path, search, check_layers)) { + *index = nr; + return dev; + } + nr++; + } + + return NULL; +} + +static hppa_device_t *find_hppa_device_by_index(unsigned int index, int search_pci) +{ + hppa_device_t *dev; + int i; + + for (i = 0; i < (MAX_DEVICES-1); i++) { + dev = parisc_devices + i; + if (!dev->hpa) + continue; + if (index-- == 0) return dev; + } + + /* search PCI devices */ + if (search_pci) { + for (i = 0; i < curr_pci_devices; i++) { + dev = hppa_pci_devices + i; + if (index-- == 0) + return dev; } } + return NULL; } #define SERIAL_TIMEOUT 20 static unsigned long parisc_serial_in(char *c, unsigned long maxchars) { - portaddr_t addr = PAGE0->mem_kbd.hpa + 0x800; /* PARISC_SERIAL_CONSOLE */ + portaddr_t addr = PAGE0->mem_kbd.hpa; unsigned long end = timer_calc(SERIAL_TIMEOUT); unsigned long count = 0; + + if (has_astro) { + hppa_device_t *dev = find_hpa_device(addr); + BUG_ON(!dev); + addr = dev->pci_addr; + } else + addr += 0x800; while (count < maxchars) { u8 lsr = inb(addr+SEROFF_LSR); if (lsr & 0x01) { @@ -533,10 +854,18 @@ static void parisc_serial_out(char c) portaddr_t addr = PAGE0->mem_cons.hpa; /* might not be initialized if problems happen during early bootup */ - if (!addr) - addr = PARISC_SERIAL_CONSOLE; - else + if (!addr) { + /* use debugoutput instead */ + dprintf(0, "%c", c); + return; + } + if (has_astro) { + hppa_device_t *dev = find_hpa_device(addr); + BUG_ON(!dev); + addr = dev->pci_addr; + } else addr += 0x800; +// dprintf(1,"parisc_serial_out addr %x\n", addr); if (c == '\n') parisc_serial_out('\r'); @@ -573,10 +902,12 @@ static char parisc_getchar(void) int count; char c; - if (HPA_is_serial_device(PAGE0->mem_kbd.hpa)) + if (HPA_is_LASI_keyboard(PAGE0->mem_kbd.hpa)) + count = lasips2_kbd_in(&c, sizeof(c)); + else if (HPA_is_serial_device(PAGE0->mem_kbd.hpa)) count = parisc_serial_in(&c, sizeof(c)); else - count = lasips2_kbd_in(&c, sizeof(c)); + BUG_ON(1); if (count == 0) c = 0; return c; @@ -600,14 +931,19 @@ int __VISIBLE parisc_iodc_ENTRY_IO(unsigned int *arg FUNC_MANY_ARGS) unsigned long hpa = ARG0; unsigned long option = ARG1; unsigned long *result = (unsigned long *)ARG4; + hppa_device_t *dev; int ret, len; char *c; struct disk_op_s disk_op; + dev = find_hpa_device(hpa); + if (!dev) + return PDC_INVALID_ARG; + if (1 && - (((HPA_is_serial_device(hpa) || HPA_is_graphics_device(hpa)) && option == ENTRY_IO_COUT) || - ((HPA_is_serial_device(hpa) || HPA_is_graphics_device(hpa)) && option == ENTRY_IO_CIN) || - ((HPA_is_storage_device(hpa) && option == ENTRY_IO_BOOTIN && !(pdc_debug & DEBUG_BOOT_IO)))) ) { + (((DEV_is_serial_device(dev) || HPA_is_graphics_device(hpa)) && option == ENTRY_IO_COUT) || + ((DEV_is_serial_device(dev) || HPA_is_graphics_device(hpa)) && option == ENTRY_IO_CIN) || + ((DEV_is_storage_device(dev) && option == ENTRY_IO_BOOTIN && !(pdc_debug & DEBUG_BOOT_IO)))) ) { /* avoid debug messages */ } else { iodc_log_call(arg, __FUNCTION__); @@ -618,7 +954,7 @@ int __VISIBLE parisc_iodc_ENTRY_IO(unsigned int *arg FUNC_MANY_ARGS) case ENTRY_IO_COUT: /* console output */ c = (char*)ARG6; result[0] = len = ARG7; - if (HPA_is_serial_device(hpa) || HPA_is_graphics_device(hpa)) { + if (DEV_is_serial_device(dev) || HPA_is_graphics_device(hpa)) { while (len--) printf("%c", *c++); } @@ -626,15 +962,15 @@ int __VISIBLE parisc_iodc_ENTRY_IO(unsigned int *arg FUNC_MANY_ARGS) case ENTRY_IO_CIN: /* console input, with 5 seconds timeout */ c = (char*)ARG6; /* FIXME: Add loop to wait for up to 5 seconds for input */ - if (HPA_is_serial_device(hpa)) - result[0] = parisc_serial_in(c, ARG7); - else if (HPA_is_keyboard_device(hpa)) + if (HPA_is_LASI_keyboard(hpa)) result[0] = lasips2_kbd_in(c, ARG7); + else if (DEV_is_serial_device(dev)) + result[0] = parisc_serial_in(c, ARG7); return PDC_OK; } /* boot medium I/O */ - if (HPA_is_storage_device(hpa)) + if (DEV_is_storage_device(dev)) switch (option) { case ENTRY_IO_BOOTIN: /* boot medium IN */ case ENTRY_IO_BBLOCK_IN: /* boot block medium IN */ @@ -692,21 +1028,25 @@ int __VISIBLE parisc_iodc_ENTRY_INIT(unsigned int *arg FUNC_MANY_ARGS) unsigned long hpa = ARG0; unsigned long option = ARG1; unsigned long *result = (unsigned long *)ARG4; - int hpa_index; + hppa_device_t *dev; iodc_log_call(arg, __FUNCTION__); - hpa_index = find_hpa_index(hpa); - if (hpa_index < 0 && hpa != IDE_HPA) + dev = find_hpa_device(hpa); + // dprintf(1, "HPA1 %lx DEV %p pci %p\n", hpa, dev, dev->pci); + + if (!dev || !(DEV_is_storage_device(dev) || DEV_is_serial_device(dev) || DEV_is_network_device(dev))) return PDC_INVALID_ARG; + // dprintf(1, "HPA2 %lx DEV %p\n", hpa, dev); switch (option) { case ENTRY_INIT_SRCH_FRST: /* 2: Search first */ + if (DEV_is_network_device(dev)) + return PDC_NE_BOOTDEV; /* No further boot devices */ memcpy((void *)ARG3, &mod_path_emulated_drives.layers, sizeof(mod_path_emulated_drives.layers)); /* fill ID_addr */ result[0] = 0; - result[1] = HPA_is_serial_device(hpa) ? CL_DUPLEX: - HPA_is_storage_device(hpa) ? CL_RANDOM : 0; + result[1] = DEV_is_serial_device(dev) ? CL_DUPLEX : CL_RANDOM; result[2] = result[3] = 0; /* No network card, so no MAC. */ return PDC_OK; case ENTRY_INIT_SRCH_NEXT: /* 3: Search next */ @@ -714,9 +1054,11 @@ int __VISIBLE parisc_iodc_ENTRY_INIT(unsigned int *arg FUNC_MANY_ARGS) case ENTRY_INIT_MOD_DEV: /* 4: Init & test mod & dev */ case ENTRY_INIT_DEV: /* 5: Init & test dev */ result[0] = 0; /* module IO_STATUS */ - result[1] = HPA_is_serial_device(hpa) ? CL_DUPLEX: - HPA_is_storage_device(hpa) ? CL_RANDOM : 0; - result[2] = result[3] = 0; /* TODO?: MAC of network card. */ + result[1] = DEV_is_serial_device(dev) ? CL_DUPLEX: CL_RANDOM; + if (DEV_is_network_device(dev)) + result[2] = result[3] = 0x11221133; /* TODO?: MAC of network card. */ + else + result[2] = result[3] = 0; return PDC_OK; case ENTRY_INIT_MOD: /* 6: INIT */ result[0] = 0; /* module IO_STATUS */ @@ -742,12 +1084,12 @@ int __VISIBLE parisc_iodc_ENTRY_TEST(unsigned int *arg FUNC_MANY_ARGS) unsigned long hpa = ARG0; unsigned long option = ARG1; unsigned long *result = (unsigned long *)ARG4; - int hpa_index; + hppa_device_t *dev; iodc_log_call(arg, __FUNCTION__); - hpa_index = find_hpa_index(hpa); - if (hpa_index < 0 && hpa != IDE_HPA) + dev = find_hpa_device(hpa); + if (!dev || !(DEV_is_storage_device(dev) || DEV_is_serial_device(dev))) return PDC_INVALID_ARG; /* The options ARG1=0 and ARG1=1 are required. Others are optional. */ @@ -805,16 +1147,6 @@ static void init_stable_storage(void) stable_storage[0x5f] = 0x0f; } -static unsigned long lasi_rtc_read(void) -{ - return *(u32 *)LASI_RTC_HPA; -} - -static void lasi_rtc_write(u32 val) -{ - *(u32 *)LASI_RTC_HPA = val; -} - /* values in PDC_CHASSIS */ const char * const systat[] = { "Off", "Fault", "Test", "Initialize", @@ -926,7 +1258,7 @@ static int pdc_pim(unsigned int *arg) case PDC_PIM_TOC: hpa = mfctl(CPU_HPA_CR_REG); /* get CPU HPA from cr7 */ i = index_of_CPU_HPA(hpa); - if (i < 0 || i >= HPPA_MAX_CPUS) { + if (i < 0 || i >= smp_cpus) { *result = PDC_INVALID_ARG; return PDC_OK; } @@ -949,17 +1281,29 @@ static int pdc_pim(unsigned int *arg) return PDC_BAD_OPTION; } -static struct pdc_model model = { PARISC_PDC_MODEL }; - static int pdc_model(unsigned int *arg) { - static const char model_str[] = PARISC_MODEL; + const char *model_str = current_machine->pdc_modelstr; unsigned long option = ARG1; unsigned long *result = (unsigned long *)ARG2; switch (option) { case PDC_MODEL_INFO: - memcpy(result, &model, sizeof(model)); + /* + * In case we run on a 32-bit only emulation, avoid a kernel crash + * with old qemu versions which will try to run 64-bit instructions + * kernel sr_disable_hash() function + */ +#if 1 + memcpy(result, (cpu_bit_width == 64) ? + ¤t_machine->pdc_model : &machine_B160L.pdc_model, + sizeof(current_machine->pdc_model)); +#else + memcpy(result, ¤t_machine->pdc_model, sizeof(current_machine->pdc_model)); + struct pdc_model *p = (struct pdc_model *) result; + /* HACK */ + p->arch_rev = 0x04; /* 32-bit CPU, 64-bit has value 0x08 */ +#endif return PDC_OK; case PDC_MODEL_VERSIONS: switch (ARG3) { @@ -967,30 +1311,43 @@ static int pdc_model(unsigned int *arg) result[0] = 35; // TODO! ??? return PDC_OK; case 1: /* return PDC version */ - result[0] = PARISC_PDC_VERSION; + result[0] = current_machine->pdc_version; return PDC_OK; } return -4; // invalid c_index case PDC_MODEL_SYSMODEL: - result[0] = sizeof(model_str) - 1; - strtcpy((char *)ARG4, model_str, sizeof(model_str)); + result[0] = strlen(model_str); + strtcpy((char *)ARG4, model_str, result[0] + 1); return PDC_OK; case PDC_MODEL_ENSPEC: case PDC_MODEL_DISPEC: - if (ARG3 != model.pot_key) + if (ARG3 != current_machine->pdc_model.pot_key) return -20; return PDC_OK; case PDC_MODEL_CPU_ID: - result[0] = PARISC_PDC_CPUID; + result[0] = current_machine->pdc_cpuid; + /* if CPU does not support 64bits, use the B160L CPUID */ + if (cpu_bit_width != 64) + result[0] = machine_B160L.pdc_cpuid; return PDC_OK; case PDC_MODEL_CAPABILITIES: - result[0] = PARISC_PDC_CAPABILITIES; + result[0] = current_machine->pdc_caps; result[0] |= PDC_MODEL_OS32; /* we do support 32-bit */ - result[0] &= ~PDC_MODEL_OS64; /* but not 64-bit (yet) */ + if (cpu_bit_width == 64) /* and maybe 64-bit */ + result[0] |= PDC_MODEL_OS64; + else + result[0] &= ~PDC_MODEL_OS64; return PDC_OK; case PDC_MODEL_GET_INSTALL_KERNEL: // No need to provide a special install kernel during installation of HP-UX return PDC_BAD_OPTION; + case PDC_MODEL_GET_PLATFORM_INFO: + model_str = has_astro ? "A6057A" : "9000/778"; + strtcpy((char *)ARG2, model_str, 16); + strtcpy((char *)ARG3, model_str, 16); + /* use: current_machine->pdc_model.sw_id ? */ + strtcpy((char *)ARG4, "001122334455", 16); + return PDC_OK; } dprintf(0, "\n\nSeaBIOS: Unimplemented PDC_MODEL function %d %x %x %x %x\n", ARG1, ARG2, ARG3, ARG4, ARG5); return PDC_BAD_OPTION; @@ -1000,15 +1357,15 @@ static int pdc_cache(unsigned int *arg) { unsigned long option = ARG1; unsigned long *result = (unsigned long *)ARG2; - static unsigned long cache_info[] = { PARISC_PDC_CACHE_INFO }; - static struct pdc_cache_info *machine_cache_info - = (struct pdc_cache_info *) &cache_info; + struct pdc_cache_info *machine_cache_info + = (struct pdc_cache_info *) current_machine->pdc_cache_info; switch (option) { case PDC_CACHE_INFO: - BUG_ON(sizeof(cache_info) != sizeof(*machine_cache_info)); machine_cache_info->it_size = tlb_entries; machine_cache_info->dt_size = tlb_entries; + machine_cache_info->it_conf = (struct pdc_tlb_cf) { .tc_sh = 3, .tc_page = 1, .tc_cst = 1, .tc_sr = 0, }; + machine_cache_info->dt_conf = (struct pdc_tlb_cf) { .tc_sh = 3, .tc_page = 1, .tc_cst = 1, .tc_sr = 0, }; machine_cache_info->it_loop = 1; machine_cache_info->dt_loop = 1; @@ -1017,21 +1374,23 @@ static int pdc_cache(unsigned int *arg) machine_cache_info->ic_count, machine_cache_info->ic_loop, machine_cache_info->ic_stride, machine_cache_info->dc_count, machine_cache_info->dc_loop, machine_cache_info->dc_stride); #endif -#if 1 - /* Increase cc_block from 1 to 11. This increases icache_stride - * and dcache_stride to 32768 bytes. Revisit for HP-UX. */ - machine_cache_info->dc_conf.cc_block = 11; - machine_cache_info->ic_conf.cc_block = 11; +#if 0 + machine_cache_info->dc_conf = (struct pdc_cache_cf) { 0 }; // .alias=1, .sh=3, }; + machine_cache_info->ic_conf = (struct pdc_cache_cf) { 0 }; // .alias=1, .sh=3, }; machine_cache_info->ic_size = 0; /* no instruction cache */ machine_cache_info->ic_count = 0; machine_cache_info->ic_loop = 0; + machine_cache_info->ic_base = 0; + machine_cache_info->ic_stride = 0; machine_cache_info->dc_size = 0; /* no data cache */ machine_cache_info->dc_count = 0; machine_cache_info->dc_loop = 0; + machine_cache_info->dc_base = 0; + machine_cache_info->dc_stride = 0; #endif - memcpy(result, cache_info, sizeof(cache_info)); + memcpy(result, machine_cache_info, sizeof(*machine_cache_info)); return PDC_OK; case PDC_CACHE_RET_SPID: /* returns space-ID bits */ memset(result, 0, 32 * sizeof(unsigned long)); @@ -1054,7 +1413,7 @@ static int pdc_hpa(unsigned int *arg) case PDC_HPA_PROCESSOR: hpa = mfctl(CPU_HPA_CR_REG); /* get CPU HPA from cr7 */ i = index_of_CPU_HPA(hpa); - BUG_ON(i < 0); /* ARGH, someone modified cr7! */ + BUG_ON(i < 0 || i >= smp_cpus); /* ARGH, someone modified cr7! */ result[0] = hpa; /* CPU_HPA */ result[1] = i; /* for SMP: 0,1,2,3,4...(num of this cpu) */ return PDC_OK; @@ -1075,12 +1434,12 @@ static int pdc_coproc(unsigned int *arg) /* Set one bit per cpu in ccr_functional and ccr_present. Ignore that specification only mentions 8 bits for cr10 and set all FPUs functional */ - mask = -1UL; + mask = 1UL; mtctl(mask, 10); /* initialize cr10 */ - result[0] = mask; - result[1] = mask; + result[0] = 1; // mask + result[1] = 1; // mask result[17] = 1; // Revision - result[18] = 19; // Model + result[18] = has_astro ? 0x0f : 0x13; // Model return PDC_OK; } return PDC_BAD_OPTION; @@ -1091,22 +1450,20 @@ static int pdc_iodc(unsigned int *arg) unsigned long option = ARG1; unsigned long *result = (unsigned long *)ARG2; unsigned long hpa; + hppa_device_t *dev; struct pdc_iodc *iodc_p; - int hpa_index; unsigned char *c; - // dprintf(0, "\n\nSeaBIOS: Info PDC_IODC function %ld ARG3=%x ARG4=%x ARG5=%x ARG6=%x\n", option, ARG3, ARG4, ARG5, ARG6); + // dprintf(1, "\n\nSeaBIOS: Info PDC_IODC function %ld ARG3=%x ARG4=%x ARG5=%x ARG6=%x\n", option, ARG3, ARG4, ARG5, ARG6); switch (option) { case PDC_IODC_READ: hpa = ARG3; - if (hpa == IDE_HPA) { // do NOT check for DINO_SCSI_HPA, breaks Linux which scans IO areas for unlisted io modules - iodc_p = &iodc_data_hpa_fff8c000; // workaround for PCI ATA - } else { - hpa_index = find_hpa_index(hpa); - if (hpa_index < 0) - return -4; // not found - iodc_p = parisc_devices[hpa_index].iodc; - } + dev = find_hpa_device(hpa); +// dprintf(1, "pdc_iodc found dev %p\n", dev); + if (!dev) + return -4; // not found + + iodc_p = dev->iodc; if (ARG4 == PDC_IODC_INDEX_DATA) { // if (hpa == MEMORY_HPA) @@ -1136,9 +1493,13 @@ static int pdc_iodc(unsigned int *arg) flush_data_cache((char*)ARG5, *result); return PDC_OK; break; - case PDC_IODC_NINIT: /* non-destructive init */ + case PDC_IODC_NINIT: /* non-destructive init - for memory */ case PDC_IODC_DINIT: /* destructive init */ - break; + result[0] = 0; /* IO_STATUS */ + result[1] = 0; /* max_spa */ + result[2] = ram_size; /* max memory */ + result[3] = 0; + return PDC_OK; case PDC_IODC_MEMERR: result[0] = 0; /* IO_STATUS */ result[1] = 0; @@ -1157,11 +1518,11 @@ static int pdc_tod(unsigned int *arg) switch (option) { case PDC_TOD_READ: - result[0] = lasi_rtc_read(); + result[0] = *rtc_ptr; result[1] = result[2] = result[3] = 0; return PDC_OK; case PDC_TOD_WRITE: - lasi_rtc_write(ARG2); + *rtc_ptr = ARG2; return PDC_OK; case 2: /* PDC_TOD_CALIBRATE_TIMERS */ /* double-precision floating-point with frequency of Interval Timer in megahertz: */ @@ -1280,6 +1641,10 @@ static int pdc_block_tlb(unsigned int *arg) { int ret; + /* Block TLB is only supported on 32-bit CPUs */ + if (cpu_bit_width != 32) + return PDC_BAD_PROC; + asm( "ldw (7-0)*%2(%1),%%r26 ! ldw (7-1)*%2(%1),%%r25 ! ldw (7-2)*%2(%1),%%r24 ! ldw (7-3)*%2(%1),%%r23\n" "ldw (7-4)*%2(%1),%%r22 ! ldw (7-5)*%2(%1),%%r21 ! ldw (7-6)*%2(%1),%%r20 ! ldw (7-7)*%2(%1),%%r19\n" @@ -1363,55 +1728,77 @@ static int pdc_system_map(unsigned int *arg) unsigned long option = ARG1; unsigned long *result = (unsigned long *)ARG2; struct pdc_module_path *mod_path; + hppa_device_t *dev; unsigned long hpa; - int hpa_index; + unsigned long hpa_index; // dprintf(0, "\n\nSeaBIOS: Info: PDC_SYSTEM_MAP function %ld ARG3=%x ARG4=%x ARG5=%x\n", option, ARG3, ARG4, ARG5); switch (option) { case PDC_FIND_MODULE: hpa_index = ARG4; - if (hpa_index >= ARRAY_SIZE(parisc_devices)) - return PDC_NE_MOD; // Module not found - hpa = parisc_devices[hpa_index].hpa; - if (!hpa) + dev = find_hppa_device_by_index(hpa_index, 0); + if (!dev) return PDC_NE_MOD; // Module not found + hpa = dev->hpa; + + if (0) { + dprintf(1, "PDC_FIND_MODULE dev=%p hpa=%lx ", dev, dev ? dev->hpa:0UL); + print_mod_path(dev->mod_path); + if (dev->pci) + dprintf(1, "PCI %pP ", dev->pci); + dprintf(1, "\n"); + } + + memset(result, 0, 32*sizeof(long)); mod_path = (struct pdc_module_path *)ARG3; if (mod_path) - *mod_path = *parisc_devices[hpa_index].mod_path; + *mod_path = *dev->mod_path; +#if 1 // *pdc_mod_info = *parisc_devices[hpa_index].mod_info; -> can be dropped. - memset(result, 0, 32*sizeof(long)); + result[0] = dev->mod_info->mod_addr; // for PDC_IODC + result[1] = dev->mod_info->mod_pgs; + result[2] = dev->num_addr; // dev->mod_info->add_addr; +#else result[0] = hpa; // .mod_addr for PDC_IODC - result[1] = HPA_is_graphics_device(hpa) ? GFX_NUM_PAGES : 1; - result[2] = parisc_devices[hpa_index].num_addr; // additional addresses + result[1] = HPA_is_graphics_device(hpa) ? GFX_NUM_PAGES : dev->pci ? 1 : 1; + result[2] = dev->num_addr; // additional addresses +#endif return PDC_OK; case PDC_FIND_ADDRESS: hpa_index = ARG3; - if (hpa_index >= ARRAY_SIZE(parisc_devices)) - return PDC_NE_MOD; // Module not found - hpa = parisc_devices[hpa_index].hpa; - if (!hpa) + dev = find_hppa_device_by_index(hpa_index, 1); + if (!dev) return PDC_NE_MOD; // Module not found + hpa = dev->hpa; memset(result, 0, 32*sizeof(long)); ARG4 -= 1; - if (ARG4 >= parisc_devices[hpa_index].num_addr) + if (ARG4 >= dev->num_addr) return PDC_INVALID_ARG; - result[0] = parisc_devices[hpa_index].add_addr[ARG4]; + result[0] = dev->add_addr[ARG4]; result[1] = HPA_is_graphics_device(hpa) ? GFX_NUM_PAGES : 1; return PDC_OK; case PDC_TRANSLATE_PATH: mod_path = (struct pdc_module_path *)ARG3; - hppa_device_t *dev = find_hppa_device_by_path(mod_path, result+3, 1); + hppa_device_t *dev = find_hppa_device_by_path(mod_path, &hpa_index, 1); + if (1) { + dprintf(1, "PDC_TRANSLATE_PATH dev=%p hpa=%lx ", dev, dev ? dev->hpa:0UL); + print_mod_path(mod_path); + if (dev && dev->pci) + dprintf(1, "PCI %pP ", dev->pci); + dprintf(1, "\n"); + } if (!dev) return PDC_NE_MOD; - result[0] = dev->hpa; - result[1] = 1; - result[2] = 0; + result[0] = dev->mod_info->mod_addr; // for PDC_IODC + result[1] = dev->mod_info->mod_pgs; + result[2] = dev->num_addr; // dev->mod_info->add_addr; + result[3] = hpa_index; return PDC_OK; } return PDC_BAD_OPTION; @@ -1447,7 +1834,8 @@ static int pdc_mem_map(unsigned int *arg) switch (option) { case PDC_MEM_MAP_HPA: - // dprintf(0, "\nSeaBIOS: PDC_MEM_MAP_HPA bus = %d, mod = %d\n", dp->bc[4], dp->mod); +// NEEDS FIXING !! + dprintf(0, "\nSeaBIOS: PDC_MEM_MAP_HPA bus = %d, mod = %d\n", dp->bc[4], dp->mod); dev = find_hppa_device_by_path((struct pdc_module_path *) dp, &index, 0); if (!dev) return PDC_NE_MOD; @@ -1489,31 +1877,90 @@ static int pdc_lan_station_id(unsigned int *arg) return PDC_BAD_OPTION; } + +#if 0 +[ 3.212566] iosapic Interrupt Routing Table (cell 0) +[ 3.282568] iosapic start = 0x1302f980 num_entries 5 entry_size 16 +[ 3.362568] iosapic 8b10000f30000002 fffffffffed30800 - 8b 10 00 0f 30 00 00 02 fffffffffed30800 +[ 3.482568] iosapic 8b10000f34000003 fffffffffed30800 - 8b 10 00 0f 34 00 00 03 fffffffffed30800 +[ 3.592568] iosapic 8b10000d3b000000 fffffffffed30800 - 8b 10 00 0d 3b 00 00 00 fffffffffed30800 +[ 3.712568] iosapic 8b10000f3c000001 fffffffffed30800 - 8b 10 00 0f 3c 00 00 01 fffffffffed30800 +[ 3.832568] iosapic 8b10000f3c000001 fffffffffed30800 - 8b 10 00 0f 3c 00 00 01 fffffffffed30800 + printk(MODULE_NAME " %016llx %016llx - %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n", + p1[0], p1[1], + p->entry_type, p->entry_length, p->interrupt_type, p->polarity_trigger, + p->src_bus_irq_devno, p->src_bus_id, p->src_seg_id, p->dest_iosapic_intin, + ((u32 *) p)[2], + ((u32 *) p)[3] +#endif +#define IRT_TABLE_ENTRIES 24 +#define IOSAPIC_HPA 0xfffffffffed30800ULL +#define ELROY_IRQS 8 /* IOSAPIC IRQs */ +static int irt_table_entries; +static u32 irt_table[IRT_TABLE_ENTRIES * 16/sizeof(u32)]; + +static void iosapic_table_setup(void) +{ + struct pci_device *pci; + u32 *p; + u8 slot = 0, iosapic_intin = 0, irq_devno, bus_id; + + irt_table_entries = 0; + memset(irt_table, 0, sizeof(irt_table)); + p = irt_table; + + foreachpci(pci) { + // if (!pci->irq) continue; + BUG_ON(irt_table_entries >= IRT_TABLE_ENTRIES); + irt_table_entries++; + dprintf(5, "IRT ENTRY #%d: bdf %02x\n", irt_table_entries, pci->bdf); + /* write the 16 bytes */ + /* 1: entry_type, entry_length, interrupt_type, polarity_trigger */ + *p++ = 0x8b10000f; // oder 0x8b10000d + /* 2: src_bus_irq_devno, src_bus_id, src_seg_id, dest_iosapic_intin */ + /* irq_devno = (slot << 2) | (intr_pin-1); */ + irq_devno = (slot++ << 2) | (pci->irq - 1); + bus_id = 0; + *p++ = (irq_devno << 24) | (bus_id << 16) | (0 << 8) | (iosapic_intin << 0); + *p++ = IOSAPIC_HPA >> 32; + *p++ = (u32) IOSAPIC_HPA; + iosapic_intin++; + iosapic_intin &= (ELROY_IRQS - 1 ); + } +} + static int pdc_pci_index(unsigned int *arg) { unsigned long option = ARG1; unsigned long *result = (unsigned long *)ARG2; + /* machines with Dino don't provide this info */ // dprintf(0, "\n\nSeaBIOS: PDC_PCI_INDEX(%lu) called with ARG2=%x ARG3=%x ARG4=%x\n", option, ARG2, ARG3, ARG4); switch (option) { case PDC_PCI_INTERFACE_INFO: memset(result, 0, 32 * sizeof(unsigned long)); + // BUG_ON(1); result[0] = 2; /* XXX physical hardware returns those ?!? */ - result[16] = 0x60; - result[17] = 0x90; return PDC_OK; case PDC_PCI_GET_INT_TBL_SIZE: + if (!has_astro) + return PDC_BAD_OPTION; + result[0] = irt_table_entries; + return PDC_OK; case PDC_PCI_GET_INT_TBL: - memset(result, 0, 32 * sizeof(unsigned long)); - result[0] = 2; /* Hardware fills in, even though we return PDC_BAD_OPTION below. */ - result[16] = 0x60; - result[17] = 0x90; - return PDC_BAD_OPTION; - case PDC_PCI_PCI_PATH_TO_PCI_HPA: - result[0] = PCI_HPA; + if (!has_astro) + return PDC_BAD_OPTION; + result[0] = irt_table_entries; + /* ARG4 is ptr to irt table */ + memcpy((void *)ARG4, irt_table, irt_table_entries * 16); return PDC_OK; + case PDC_PCI_PCI_PATH_TO_PCI_HPA: + // BUG_ON(1); + result[0] = has_astro ? 0xfed00000 : PCI_HPA; + return has_astro ? PDC_OK : PDC_BAD_OPTION; case PDC_PCI_PCI_HPA_TO_PCI_PATH: - BUG_ON(1); + // BUG_ON(1); + break; } return PDC_BAD_OPTION; } @@ -1525,6 +1972,8 @@ static int pdc_initiator(unsigned int *arg) switch (option) { case PDC_GET_INITIATOR: + /* SCSI controller is on normal PCI bus on machines with Astro */ + if (has_astro) return PDC_BAD_OPTION; // ARG3 points to the hwpath of device for which initiator is asked for. result[0] = 7; // initiator_id/host_id: 7 to 15. result[1] = 10; // scsi_rate: 1, 2, 5 or 10 for 5, 10, 20 or 40 MT/s @@ -2047,45 +2496,99 @@ static struct pz_device mem_kbd_boot = { .cl_class = CL_KEYBD, }; -static const struct pz_device mem_boot_boot = { +static struct pz_device mem_boot_boot = { .dp.flags = PF_AUTOBOOT, - .hpa = IDE_HPA, // DINO_SCSI_HPA, // IDE_HPA + .hpa = DINO_SCSI_HPA, // will be overwritten .iodc_io = (unsigned long) &iodc_entry, .cl_class = CL_RANDOM, }; -static void find_pci_slot_for_dev(unsigned int pciid, char *pci_slot) +#if 0 +static void find_pci_slot_for_dev(unsigned int vendor, char *pci_slot) { struct pci_device *pci; foreachpci(pci) - if (pci->vendor == pciid) { + if (pci->vendor == vendor) { *pci_slot = (pci->bdf >> 3) & 0x0f; return; } } +#endif + +/* find serial PCI card (to be used as console) */ +static void find_serial_pci_card(void) +{ + struct pci_device *pci; + hppa_device_t *pdev; + u32 pmem; + + if (!has_astro) + return; + pci = pci_find_class(PCI_CLASS_COMMUNICATION_SERIAL); + if (!pci) + return; + + dprintf(1, "PCI: Enabling %pP for primary SERIAL PORT\n", pci); + pci_config_maskw(pci->bdf, PCI_COMMAND, 0, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + pmem = pci_enable_iobar(pci, PCI_BASE_ADDRESS_0); + dprintf(1, "PCI: Enabling %pP for primary SERIAL PORT mem %x\n", pci, pmem); + pmem += IOS_DIST_BASE_ADDR; + + /* set serial port for console output and keyboard input */ + pdev = &hppa_pci_devices[0]; + while (pdev->pci != pci) + pdev++; + pdev->pci_addr = pmem; + mem_cons_boot.hpa = pdev->hpa; + mem_kbd_boot.hpa = pdev->hpa; +} + +/* find SCSI PCI card (to be used as boot device) */ +static void find_scsi_pci_card(void) +{ + struct pci_device *pci; + hppa_device_t *pdev; + u32 pmem; + + // if (!has_astro) return; + pci = pci_find_class(PCI_CLASS_STORAGE_SCSI); + if (!pci) + return; + dprintf(1, "PCI: Enabling %pP for primary SCSI PORT\n", pci); + pmem = pci_enable_iobar(pci, PCI_BASE_ADDRESS_0); + dprintf(1, "PCI: Enabling %pP for primary SCSI PORT mem %x\n", pci, pmem); + pmem += IOS_DIST_BASE_ADDR; + + /* set SCSI HPA */ + pdev = &hppa_pci_devices[0]; + while (pdev->pci != pci) + pdev++; + pdev->pci_addr = pmem; + mem_boot_boot.hpa = pdev->hpa; +} + /* Prepare boot paths in PAGE0 and stable memory */ static void prepare_boot_path(volatile struct pz_device *dest, const struct pz_device *source, unsigned int stable_offset) { - int hpa_index; + hppa_device_t *dev; unsigned long hpa; struct pdc_module_path *mod_path; hpa = source->hpa; - hpa_index = find_hpa_index(hpa); + dev = find_hpa_device(hpa); + BUG_ON(!dev); - if (HPA_is_storage_device(hpa)) + if (DEV_is_storage_device(dev)) mod_path = &mod_path_emulated_drives; - else if (hpa == LASI_UART_HPA) // HPA_is_serial_device(hpa)) - mod_path = &mod_path_hpa_ffd05000; - else if (hpa == DINO_UART_HPA) // HPA_is_serial_device(hpa)) - mod_path = &mod_path_hpa_fff83000; + else if (dev) + mod_path = dev->mod_path; else { - BUG_ON(hpa_index < 0); - mod_path = parisc_devices[hpa_index].mod_path; + BUG_ON(1); } /* copy device path to entry in PAGE0 */ @@ -2132,6 +2635,14 @@ void __VISIBLE start_parisc_firmware(void) char bootdrive = (char)cmdline; // c = hdd, d = CD/DVD show_boot_menu = (linux_kernel_entry == 1); + // detect if we emulate a 32- or 64-bit CPU. + // set all bits in cr11, read back, and if the return + // value is 63 this is a 64-bit capable CPU. + // A 32-bit only CPU returns 31. + mtctl(-1UL, 11); + cpu_bit_width = (mfctl(11) == 63) ? 64 : 32; + // cpu_bit_width = 64; /* XXX HACK */ + if (smp_cpus > HPPA_MAX_CPUS) smp_cpus = HPPA_MAX_CPUS; num_online_cpus = smp_cpus; @@ -2142,6 +2653,8 @@ void __VISIBLE start_parisc_firmware(void) /* Initialize malloc stack */ malloc_preinit(); + // PlatformRunningOn = PF_QEMU; // emulate runningOnQEMU() + /* Initialize qemu fw_cfg interface */ PORT_QEMU_CFG_CTL = fw_cfg_port; qemu_cfg_init(); @@ -2149,27 +2662,42 @@ void __VISIBLE start_parisc_firmware(void) /* Initialize boot structures. Needs working fw_cfg for bootprio option. */ boot_init(); + DebugOutputPort = romfile_loadint("/etc/hppa/DebugOutputPort", CPU_HPA + 24); + i = romfile_loadint("/etc/firmware-min-version", 0); if (i && i > SEABIOS_HPPA_VERSION) { printf("\nSeaBIOS firmware is version %d, but version %d is required. " "Please update.\n", (int)SEABIOS_HPPA_VERSION, i); hlt(); } - /* Qemu versions which request a SEABIOS_HPPA_VERSION < 6 have the bug that - * they use the DINO UART instead of the LASI UART as serial port #0. - * Fix it up here and switch the serial console code to use PORT_SERIAL2 - * for such Qemu versions, so that we can still use this higher SeaBIOS - * version with older Qemus. */ - if (i < 6) { - mem_cons_boot.hpa = PORT_SERIAL2 - 0x800; - mem_kbd_boot.hpa = PORT_SERIAL2 - 0x800; + + /* which machine shall we emulate? */ + str = romfile_loadfile("/etc/hppa/machine", NULL); + if (!str) + str = "B160L"; + if (strcmp(str, "C3700") == 0) { + current_machine = &machine_C3700; + has_astro = 1; + hppa_port_pci_cmd = 0xfed30000 + 0x040; + hppa_port_pci_data = 0xfed30000 + 0x048; + /* no serial port for now, will find later */ + mem_cons_boot.hpa = 0; + mem_kbd_boot.hpa = 0; } + parisc_devices = current_machine->device_list; + strtcpy(qemu_machine, str, sizeof(qemu_machine)); tlb_entries = romfile_loadint("/etc/cpu/tlb_entries", 256); dprintf(0, "fw_cfg: TLB entries %d\n", tlb_entries); +// hlt(); powersw_ptr = (int *) (unsigned long) - romfile_loadint("/etc/power-button-addr", (unsigned long)&powersw_nop); + romfile_loadint("/etc/hppa/power-button-addr", (unsigned long)&powersw_nop); + + /* real-time-clock addr */ + rtc_ptr = (int *) (unsigned long) + romfile_loadint("/etc/hppa/rtc-addr", (unsigned long) LASI_RTC_HPA); + dprintf(0, "RTC PTR 0x%x\n", (int)rtc_ptr); /* use -fw_cfg opt/pdc_debug,string=255 to enable all firmware debug infos */ pdc_debug = romfile_loadstring_to_int("opt/pdc_debug", 0); @@ -2186,8 +2714,9 @@ void __VISIBLE start_parisc_firmware(void) /* 0,1 = default 8x16 font, 2 = 16x32 font */ sti_font = romfile_loadstring_to_int("opt/font", 0); - model.sw_id = romfile_loadstring_to_int("opt/hostid", model.sw_id); - dprintf(0, "fw_cfg: machine hostid %lu\n", model.sw_id); + current_machine->pdc_model.sw_id = romfile_loadstring_to_int("opt/hostid", + current_machine->pdc_model.sw_id); + dprintf(0, "fw_cfg: machine hostid %lu\n", current_machine->pdc_model.sw_id); str = romfile_loadfile("/etc/qemu-version", NULL); if (str) @@ -2229,29 +2758,18 @@ void __VISIBLE start_parisc_firmware(void) sti_rom_init(); sti_console_init(&sti_proc_rom); PAGE0->proc_sti = (u32)&sti_proc_rom; - ps2port_setup(); + if (has_astro) + kbd_init(); + else + ps2port_setup(); } else { remove_from_keep_list(LASI_GFX_HPA); remove_from_keep_list(LASI_PS2KBD_HPA); remove_from_keep_list(LASI_PS2MOU_HPA); } - // Initialize boot paths (graphics & keyboard) - if (pdc_console == CONSOLE_DEFAULT) { - if (artist_present()) - pdc_console = CONSOLE_GRAPHICS; - else - pdc_console = CONSOLE_SERIAL; - } - if (pdc_console == CONSOLE_GRAPHICS) { - prepare_boot_path(&(PAGE0->mem_cons), &mem_cons_sti_boot, 0x60); - prepare_boot_path(&(PAGE0->mem_kbd), &mem_kbd_sti_boot, 0xa0); - } else { - prepare_boot_path(&(PAGE0->mem_cons), &mem_cons_boot, 0x60); - prepare_boot_path(&(PAGE0->mem_kbd), &mem_kbd_boot, 0xa0); - } - /* Initialize device list */ + keep_add_generic_devices(); remove_parisc_devices(smp_cpus); /* Show list of HPA devices which are still returned by firmware. */ @@ -2264,13 +2782,9 @@ void __VISIBLE start_parisc_firmware(void) chassis_code = 0; - // set Qemu serial debug port - DebugOutputPort = PARISC_SERIAL_CONSOLE; - // PlatformRunningOn = PF_QEMU; // emulate runningOnQEMU() - cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */ - dprintf(1, "\nPARISC SeaBIOS Firmware, %d x PA7300LC (PCX-L2) at %d.%06d MHz, %d MB RAM.\n", - smp_cpus, cpu_hz / 1000000, cpu_hz % 1000000, + dprintf(1, "\nPARISC SeaBIOS Firmware, %d x %d-bit PA-RISC CPU at %d.%06d MHz, %d MB RAM.\n", + smp_cpus, cpu_bit_width, cpu_hz / 1000000, cpu_hz % 1000000, ram_size/1024/1024); if (ram_size < MIN_RAM_SIZE) { @@ -2289,10 +2803,36 @@ void __VISIBLE start_parisc_firmware(void) // coreboot_preinit(); pci_setup(); + if (has_astro) { + iosapic_table_setup(); + } + hppa_pci_build_devices_list(); + + /* find serial PCI card when running on Astro */ + find_serial_pci_card(); serial_setup(); + // ohci_setup(); block_setup(); + /* find SCSI PCI card when running on Astro or Dino */ + find_scsi_pci_card(); + + // Initialize boot paths (graphics & keyboard) + if (pdc_console == CONSOLE_DEFAULT) { + if (artist_present()) + pdc_console = CONSOLE_GRAPHICS; + else + pdc_console = CONSOLE_SERIAL; + } + if (pdc_console == CONSOLE_GRAPHICS) { + prepare_boot_path(&(PAGE0->mem_cons), &mem_cons_sti_boot, 0x60); + prepare_boot_path(&(PAGE0->mem_kbd), &mem_kbd_sti_boot, 0xa0); + } else { + prepare_boot_path(&(PAGE0->mem_cons), &mem_cons_boot, 0x60); + prepare_boot_path(&(PAGE0->mem_kbd), &mem_kbd_boot, 0xa0); + } + PAGE0->vec_rendz = 0; /* No rendezvous yet. Add MEM_RENDEZ_HI later */ printf("\n"); @@ -2310,8 +2850,10 @@ void __VISIBLE start_parisc_firmware(void) " MHz %s Functional 0 KB\n", i < 10 ? " ":"", i, i?"Idle ":"Active"); printf("\n\n"); - printf(" Available memory: %u MB\n" + printf(" Emulated machine: HP %s (%d-bit %s)\n" + " Available memory: %u MB\n" " Good memory required: %d MB\n\n", + qemu_machine, cpu_bit_width, (cpu_bit_width == 64) ? "PA2.0" : "PA1.1", ram_size/1024/1024, MIN_RAM_SIZE/1024/1024); // search boot devices @@ -2332,8 +2874,7 @@ void __VISIBLE start_parisc_firmware(void) boot_drive = parisc_boot_cdrom; // Find PCI bus id of LSI SCSI card - find_pci_slot_for_dev(PCI_VENDOR_ID_LSI_LOGIC, - &mod_path_emulated_drives.path.bc[5]); + // find_pci_slot_for_dev(PCI_VENDOR_ID_LSI_LOGIC, &mod_path_emulated_drives.path.bc[5]); // Store initial emulated drives path master data if (parisc_boot_harddisc) { diff --git a/src/parisc/pdc.h b/src/parisc/pdc.h index bf6dd64..9c0b8f7 100644 --- a/src/parisc/pdc.h +++ b/src/parisc/pdc.h @@ -186,6 +186,9 @@ #define PDC_SCSI_GET_PARMS 0 /* Get SCSI parameters for I/O device */ #define PDC_SCSI_SET_PARMS 1 /* Set SCSI parameters for I/O device */ +#define PDC_PAT_CELL 64 +#define PDC_PAT_CHASSIS_LOG 65 + /* HVERSION dependent */ /* The PDC_MEM_MAP calls */ diff --git a/src/parisc/stirom.c b/src/parisc/stirom.c index 4c41d7c..ddc6285 100644 --- a/src/parisc/stirom.c +++ b/src/parisc/stirom.c @@ -3281,7 +3281,7 @@ struct sti_rom __stiheader sti_proc_rom = { static void __stitext write_artist(struct sti_glob_cfg *cfg, int reg, u32 val) { - writel((void *)cfg->region_ptrs[2] + reg, val); + gsc_writel((void *)cfg->region_ptrs[2] + reg, val); } static int __stifunc("state_mgmt") sti_state_mgmt(struct sti_state_flags *flags, |