diff options
Diffstat (limited to 'qemu/roms/openbios/drivers/sbus.c')
-rw-r--r-- | qemu/roms/openbios/drivers/sbus.c | 498 |
1 files changed, 0 insertions, 498 deletions
diff --git a/qemu/roms/openbios/drivers/sbus.c b/qemu/roms/openbios/drivers/sbus.c deleted file mode 100644 index 4caa59aaf..000000000 --- a/qemu/roms/openbios/drivers/sbus.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * OpenBIOS SBus driver - * - * (C) 2004 Stefan Reinauer <stepan@openbios.org> - * (C) 2005 Ed Schouten <ed@fxq.nl> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 - * - */ - -#include "config.h" -#include "libopenbios/bindings.h" -#include "kernel/kernel.h" -#include "libc/byteorder.h" -#include "libc/vsprintf.h" -#include "drivers/drivers.h" -#include "libopenbios/ofmem.h" -#include "libopenbios/video.h" - -#define SBUS_REGS 0x28 -#define SBUS_SLOTS 16 -#define APC_REGS 0x10 -#define APC_OFFSET 0x0a000000ULL -#define CS4231_REGS 0x40 -#define CS4231_OFFSET 0x0c000000ULL -#define MACIO_ESPDMA 0x00400000ULL /* ESP DMA controller */ -#define MACIO_ESP 0x00800000ULL /* ESP SCSI */ -#define SS600MP_ESPDMA 0x00081000ULL -#define SS600MP_ESP 0x00080000ULL -#define SS600MP_LEBUFFER (SS600MP_ESPDMA + 0x10) // XXX should be 0x40000 -#define LEDMA_REGS 0x4 -#define LE_REGS 0x20 - -#ifdef CONFIG_DEBUG_SBUS -#define DPRINTF(fmt, args...) \ - do { printk(fmt , ##args); } while (0) -#else -#define DPRINTF(fmt, args...) -#endif - -typedef struct le_private { - uint32_t *dmaregs; - uint32_t *regs; -} le_private_t; - -static void -ob_sbus_node_init(uint64_t base) -{ - void *regs; - - push_str("/iommu/sbus"); - fword("find-device"); - - PUSH(base >> 32); - fword("encode-int"); - PUSH(base & 0xffffffff); - fword("encode-int"); - fword("encode+"); - PUSH(SBUS_REGS); - fword("encode-int"); - fword("encode+"); - push_str("reg"); - fword("property"); - - regs = (void *)ofmem_map_io(base, SBUS_REGS); - PUSH((unsigned long)regs); - fword("encode-int"); - push_str("address"); - fword("property"); -} - -static void -ob_le_init(unsigned int slot, uint64_t base, unsigned long leoffset, unsigned long dmaoffset) -{ - le_private_t *le; - - le = malloc(sizeof(le_private_t)); - if (!le) { - DPRINTF("Can't allocate LANCE private structure\n"); - return; - } - - /* Get the IO region for DMA registers */ - le->dmaregs = (void *)ofmem_map_io(base + (uint64_t)dmaoffset, LEDMA_REGS); - if (le->dmaregs == NULL) { - DPRINTF("Can't map LANCE DMA registers\n"); - return; - } - - /* Now it appears that the Solaris kernel forgets to set up the LANCE DMA mapping - and so it must inherit the one from OpenBIOS. The symptom of this is that the - LANCE DMA base addr register is still zero, and so we start sending network - packets containing random areas of memory. - - The correct fix for this should be to use dvma_alloc() to grab a section of - memory and point the LANCE DMA buffers to use that instead; this gets - slightly further but still crashes. Time-consuming investigation on various - hacked versions of QEMU seems to indicate that Solaris always assumes the LANCE - DMA base address is fixed 0xff000000 when setting up the IOMMU for the LANCE - card. Hence we imitate this behaviour here. */ - le->dmaregs[3] = 0xff000000; - - push_str("/iommu/sbus/ledma"); - fword("find-device"); - PUSH(slot); - fword("encode-int"); - PUSH(dmaoffset); - fword("encode-int"); - fword("encode+"); - PUSH(0x00000020); - fword("encode-int"); - fword("encode+"); - push_str("reg"); - fword("property"); - - /* Get the IO region for Lance registers */ - le->regs = (void *)ofmem_map_io(base + (uint64_t)leoffset, LE_REGS); - if (le->regs == NULL) { - DPRINTF("Can't map LANCE registers\n"); - return; - } - - push_str("/iommu/sbus/ledma/le"); - fword("find-device"); - PUSH(slot); - fword("encode-int"); - PUSH(leoffset); - fword("encode-int"); - fword("encode+"); - PUSH(0x00000004); - fword("encode-int"); - fword("encode+"); - push_str("reg"); - fword("property"); -} - -uint16_t graphic_depth; - -static void -ob_tcx_init(unsigned int slot, const char *path) -{ - char buf[6]; - - printk("No display device located during SBus probe - falling back to internal TCX driver\n"); - - /* Make the sbus node the current instance and active package for probing */ - feval("active-package my-self"); - push_str("/iommu/sbus"); - feval("2dup find-device open-dev to my-self"); - - fword("new-device"); - PUSH(0); - PUSH(0); - snprintf(buf, 6, "%x,0", slot); - push_str(buf); - fword("set-args"); - feval("['] tcx-driver-fcode 2 cells + 1 byte-load"); - fword("finish-device"); - - /* Restore */ - feval("to my-self active-package!"); -} - -static void -ob_apc_init(unsigned int slot, unsigned long base) -{ - push_str("/iommu/sbus"); - fword("find-device"); - fword("new-device"); - - push_str("power-management"); - fword("device-name"); - - PUSH(slot); - fword("encode-int"); - PUSH(base); - fword("encode-int"); - fword("encode+"); - PUSH(APC_REGS); - fword("encode-int"); - fword("encode+"); - push_str("reg"); - fword("property"); - - fword("finish-device"); -} - -static void -ob_cs4231_init(unsigned int slot) -{ - push_str("/iommu/sbus"); - fword("find-device"); - fword("new-device"); - - push_str("SUNW,CS4231"); - fword("device-name"); - - push_str("serial"); - fword("device-type"); - - PUSH(slot); - fword("encode-int"); - PUSH(CS4231_OFFSET); - fword("encode-int"); - fword("encode+"); - PUSH(CS4231_REGS); - fword("encode-int"); - fword("encode+"); - push_str("reg"); - fword("property"); - - PUSH(5); - fword("encode-int"); - PUSH(0); - fword("encode-int"); - fword("encode+"); - push_str("intr"); - fword("property"); - - PUSH(5); - fword("encode-int"); - push_str("interrupts"); - fword("property"); - - push_str("audio"); - fword("encode-string"); - push_str("alias"); - fword("property"); - - fword("finish-device"); -} - -static void -ob_macio_init(unsigned int slot, uint64_t base, unsigned long offset) -{ - // All devices were integrated to NCR89C100, see - // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt - - // NCR 53c9x, aka ESP. See - // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt -#ifdef CONFIG_DRIVER_ESP - ob_esp_init(slot, base, offset + MACIO_ESP, offset + MACIO_ESPDMA); -#endif - - // NCR 92C990, Am7990, Lance. See http://www.amd.com - ob_le_init(slot, base, offset + 0x00c00000, offset + 0x00400010); - - // Parallel port - //ob_bpp_init(base); -} - -static void -sbus_probe_self(unsigned int slot, unsigned long offset) -{ - /* Wrapper for calling probe-self in Forth. This is mainly because some - drivers don't handle properties correctly when the sbus node is set - as the current instance during probe. */ - char buf[6]; - - printk("Probing SBus slot %d offset %ld\n", slot, offset); - - /* Make the sbus node the current instance and active package for probing */ - feval("active-package my-self"); - push_str("/iommu/sbus"); - feval("open-dev to my-self"); - - PUSH(0); - PUSH(0); - snprintf(buf, 6, "%x,%lx", slot, offset); - push_str(buf); - fword("2dup"); - fword("probe-self-sbus"); - - /* Restore */ - feval("to my-self active-package!"); -} - -static int -sbus_probe_sucess(void) -{ - /* Return true if the last sbus_probe_self() resulted in - the successful detection and execution of FCode */ - fword("probe-fcode?"); - return POP(); -} - -static void -sbus_probe_slot_ss5(unsigned int slot, uint64_t base) -{ - /* Probe the slot */ - sbus_probe_self(slot, 0); - - /* If the device was successfully created by FCode then do nothing */ - if (sbus_probe_sucess()) { - return; - } - - switch(slot) { - case 3: // SUNW,tcx - ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx"); - break; - case 4: - // SUNW,CS4231 - ob_cs4231_init(slot); - // Power management (APC) - ob_apc_init(slot, APC_OFFSET); - break; - case 5: // MACIO: le, esp, bpp - ob_macio_init(slot, base, 0x08000000); - break; - default: - break; - } -} - -static void -sbus_probe_slot_ss10(unsigned int slot, uint64_t base) -{ - /* Probe the slot */ - sbus_probe_self(slot, 0); - - /* If the device was successfully created by FCode then do nothing */ - if (sbus_probe_sucess()) { - return; - } - - switch(slot) { - case 2: // SUNW,tcx - ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx"); - break; - case 0xf: // le, esp, bpp, power-management - ob_macio_init(slot, base, 0); - // Power management (APC) XXX should not exist - ob_apc_init(slot, APC_OFFSET); - break; - default: - break; - } -} - -static void -sbus_probe_slot_ss600mp(unsigned int slot, uint64_t base) -{ - /* Probe the slot */ - sbus_probe_self(slot, 0); - - /* If the device was successfully created by FCode then do nothing */ - if (sbus_probe_sucess()) { - return; - } - - switch(slot) { - case 2: // SUNW,tcx - ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx"); - break; - case 0xf: // le, esp, bpp, power-management -#ifdef CONFIG_DRIVER_ESP - ob_esp_init(slot, base, SS600MP_ESP, SS600MP_ESPDMA); -#endif - // NCR 92C990, Am7990, Lance. See http://www.amd.com - ob_le_init(slot, base, 0x00060000, SS600MP_LEBUFFER); - // Power management (APC) XXX should not exist - ob_apc_init(slot, APC_OFFSET); - break; - default: - break; - } -} - -struct sbus_offset { - int slot, type; - uint64_t base; - unsigned long size; -}; - -static const struct sbus_offset sbus_offsets_ss5[SBUS_SLOTS] = { - { 0, 0, 0x20000000, 0x10000000,}, - { 1, 0, 0x30000000, 0x10000000,}, - { 2, 0, 0x40000000, 0x10000000,}, - { 3, 0, 0x50000000, 0x10000000,}, - { 4, 0, 0x60000000, 0x10000000,}, - { 5, 0, 0x70000000, 0x10000000,}, -}; - -/* Shared with ss600mp */ -static const struct sbus_offset sbus_offsets_ss10[SBUS_SLOTS] = { - { 0, 0, 0xe00000000ULL, 0x10000000,}, - { 1, 0, 0xe10000000ULL, 0x10000000,}, - { 2, 0, 0xe20000000ULL, 0x10000000,}, - { 3, 0, 0xe30000000ULL, 0x10000000,}, - [0xf] = { 0xf, 0, 0xef0000000ULL, 0x10000000,}, -}; - -static void -ob_add_sbus_range(const struct sbus_offset *range, int notfirst) -{ - if (!notfirst) { - push_str("/iommu/sbus"); - fword("find-device"); - } - PUSH(range->slot); - fword("encode-int"); - if (notfirst) - fword("encode+"); - PUSH(range->type); - fword("encode-int"); - fword("encode+"); - PUSH(range->base >> 32); - fword("encode-int"); - fword("encode+"); - PUSH(range->base & 0xffffffff); - fword("encode-int"); - fword("encode+"); - PUSH(range->size); - fword("encode-int"); - fword("encode+"); -} - -static int -ob_sbus_init_ss5(void) -{ - unsigned int slot; - int notfirst = 0; - - for (slot = 0; slot < SBUS_SLOTS; slot++) { - if (sbus_offsets_ss5[slot].size > 0) - ob_add_sbus_range(&sbus_offsets_ss5[slot], notfirst++); - } - push_str("ranges"); - fword("property"); - - for (slot = 0; slot < SBUS_SLOTS; slot++) { - if (sbus_offsets_ss5[slot].size > 0) - sbus_probe_slot_ss5(slot, sbus_offsets_ss5[slot].base); - } - - return 0; -} - -static int -ob_sbus_init_ss10(void) -{ - unsigned int slot; - int notfirst = 0; - - for (slot = 0; slot < SBUS_SLOTS; slot++) { - if (sbus_offsets_ss10[slot].size > 0) - ob_add_sbus_range(&sbus_offsets_ss10[slot], notfirst++); - } - push_str("ranges"); - fword("property"); - - for (slot = 0; slot < SBUS_SLOTS; slot++) { - if (sbus_offsets_ss10[slot].size > 0) - sbus_probe_slot_ss10(slot, sbus_offsets_ss10[slot].base); - } - - return 0; -} - -static int -ob_sbus_init_ss600mp(void) -{ - unsigned int slot; - int notfirst = 0; - - for (slot = 0; slot < SBUS_SLOTS; slot++) { - if (sbus_offsets_ss10[slot].size > 0) - ob_add_sbus_range(&sbus_offsets_ss10[slot], notfirst++); - } - push_str("ranges"); - fword("property"); - - for (slot = 0; slot < SBUS_SLOTS; slot++) { - if (sbus_offsets_ss10[slot].size > 0) - sbus_probe_slot_ss600mp(slot, sbus_offsets_ss10[slot].base); - } - - return 0; -} - -int ob_sbus_init(uint64_t base, int machine_id) -{ - ob_sbus_node_init(base); - - switch (machine_id) { - case 66: - return ob_sbus_init_ss600mp(); - case 64 ... 65: - return ob_sbus_init_ss10(); - case 32 ... 63: - return ob_sbus_init_ss5(); - default: - return -1; - } -} |