aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2023-09-21 23:37:50 +0200
committerHelge Deller <deller@gmx.de>2023-10-11 03:24:39 +0200
commitae2b0d735fba482f9e29945c2af0cfe033887756 (patch)
treea639e25e399e30e41cd275560274cd52fcd56b7e
parent40c5a5a8ab1391b9d50e57ee349c04f0009d7714 (diff)
downloadseabios-hppa-ae2b0d735fba482f9e29945c2af0cfe033887756.zip
seabios-hppa-ae2b0d735fba482f9e29945c2af0cfe033887756.tar.gz
seabios-hppa-ae2b0d735fba482f9e29945c2af0cfe033887756.tar.bz2
Add support for HP C3700 worksation emulation
-rw-r--r--.vimrc4
-rw-r--r--src/Kconfig2
-rw-r--r--src/block.c2
-rw-r--r--src/boot.c6
-rw-r--r--src/fw/pciinit.c34
-rw-r--r--src/hw/ata.h8
-rw-r--r--src/hw/pci.c67
-rw-r--r--src/hw/pcidevice.c5
-rw-r--r--src/hw/pcidevice.h1
-rw-r--r--src/hw/rtc.h7
-rw-r--r--src/hw/serialio.c3
-rw-r--r--src/hw/usb-ohci.c91
-rw-r--r--src/hw/usb.c14
-rw-r--r--src/kbd.c2
-rw-r--r--src/parisc/c3700.h284
-rw-r--r--src/parisc/hppa.h69
-rw-r--r--src/parisc/hppa_hardware.h18
-rw-r--r--src/parisc/lasips2.c11
-rw-r--r--src/parisc/machine-create.h20
-rw-r--r--src/parisc/malloc.c2
-rw-r--r--src/parisc/parisc.c925
-rw-r--r--src/parisc/pdc.h3
-rw-r--r--src/parisc/stirom.c2
23 files changed, 1292 insertions, 288 deletions
diff --git a/.vimrc b/.vimrc
new file mode 100644
index 0000000..5126a5d
--- /dev/null
+++ b/.vimrc
@@ -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);
diff --git a/src/boot.c b/src/boot.c
index 3d7f092..cf1b2fe 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -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(&regs->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);
diff --git a/src/kbd.c b/src/kbd.c
index 15e5ae7..2451ac1 100644
--- a/src/kbd.c
+++ b/src/kbd.c
@@ -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) ?
+ &current_machine->pdc_model : &machine_B160L.pdc_model,
+ sizeof(current_machine->pdc_model));
+#else
+ memcpy(result, &current_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,