diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2012-04-16 22:28:16 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2012-04-16 22:28:16 +0000 |
commit | f09813013655ad3b727993a1b3629a0dd4d92a62 (patch) | |
tree | b6ec058ed9f2d963eef17fbb0b0b96ad618d768e | |
parent | 273f81db66867242ea47adbe30fb879f282fc185 (diff) |
Improve the way frame buffers are probed to reduce (and hopefully avoid)
false positives.
Do not look for framebuffers past GIO EXP1, there shouldn't be anything there.
Add the console code machinery to attach a glass console on IP22, when the
appropriate drivers will exist.
On multihead systems, get console framebuffer address (well, sort of) from a
completely undocumented interface (knowledge taken from Linux, confirmed to
work on a dual-head Indigo 2 here).
While there, get frame buffer names from ARCBios whenever possible, to be used
in dmesg eventually.
-rw-r--r-- | sys/arch/sgi/gio/gio.c | 311 | ||||
-rw-r--r-- | sys/arch/sgi/gio/gioreg.h | 7 | ||||
-rw-r--r-- | sys/arch/sgi/gio/giovar.h | 28 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip22_machdep.c | 171 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/wscons_machdep.c | 71 |
5 files changed, 465 insertions, 123 deletions
diff --git a/sys/arch/sgi/gio/gio.c b/sys/arch/sgi/gio/gio.c index b8b31b6be2b..8501f5a4a68 100644 --- a/sys/arch/sgi/gio/gio.c +++ b/sys/arch/sgi/gio/gio.c @@ -1,7 +1,22 @@ -/* $OpenBSD: gio.c,v 1.2 2012/04/15 20:44:51 miod Exp $ */ +/* $OpenBSD: gio.c,v 1.3 2012/04/16 22:28:12 miod Exp $ */ /* $NetBSD: gio.c,v 1.32 2011/07/01 18:53:46 dyoung Exp $ */ /* + * Copyright (c) 2012 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* * Copyright (c) 2000 Soren S. Jorvang * All rights reserved. * @@ -51,13 +66,27 @@ #include <sgi/localbus/intvar.h> #include <sgi/sgi/ip22.h> +#include "grtwo.h" +#include "light.h" +#include "newport.h" + +#if NGRTWO > 0 +#include <sgi/gio/grtwovar.h> +#endif +#if NLIGHT > 0 +#include <sgi/gio/lightvar.h> +#endif +#if NNEWPORT > 0 +#include <sgi/gio/newportvar.h> +#endif + int gio_match(struct device *, void *, void *); void gio_attach(struct device *, struct device *, void *); int gio_print(void *, const char *); int gio_print_fb(void *, const char *); int gio_search(struct device *, void *, void *); int gio_submatch(struct device *, void *, void *); -uint32_t gio_id(paddr_t, int); +uint32_t gio_id(vaddr_t, paddr_t, int); struct gio_softc { struct device sc_dev; @@ -74,6 +103,11 @@ struct cfdriver gio_cd = { NULL, "gio", DV_DULL }; +/* Address of the console frame buffer registers, if applicable */ +paddr_t giofb_consaddr; +/* Names of the frame buffers, as obtained by ARCBios */ +const char *giofb_names[GIO_MAX_FB]; + struct gio_probe { uint32_t slot; uint64_t base; @@ -81,10 +115,13 @@ struct gio_probe { uint32_t mach_subtype; }; +/* an invalid GIO ID value used to report the device might be a frame buffer */ +#define GIO_FAKE_FB_ID (0xffffff7f) + /* * Expansion Slot Base Addresses * - * IP12, IP20 and IP24 have two GIO connectors: GIO_SLOT_EXP0 and + * IP20 and IP24 have two GIO connectors: GIO_SLOT_EXP0 and * GIO_SLOT_EXP1. * * On IP24 these slots exist on the graphics board or the IOPLUS @@ -98,13 +135,17 @@ struct gio_probe { * GIO_SLOT_EXP1. See gio(4) for the story. */ static const struct gio_probe slot_bases[] = { - { GIO_SLOT_GFX, 0x1f000000, SGI_IP22, IP22_INDIGO2 }, + /* GFX is only a slot on Indigo 2 */ + { GIO_SLOT_GFX, GIO_ADDR_GFX, SGI_IP22, IP22_INDIGO2 }, - { GIO_SLOT_EXP0, 0x1f400000, SGI_IP20, -1 }, - { GIO_SLOT_EXP0, 0x1f400000, SGI_IP22, -1 }, + /* EXP0 is available on all systems */ + { GIO_SLOT_EXP0, GIO_ADDR_EXP0, SGI_IP20, -1 }, + { GIO_SLOT_EXP0, GIO_ADDR_EXP0, SGI_IP22, -1 }, - { GIO_SLOT_EXP1, 0x1f600000, SGI_IP20, -1 }, - { GIO_SLOT_EXP1, 0x1f600000, SGI_IP22, IP22_INDY }, + /* EXP1 does not exist on Indigo 2 */ + { GIO_SLOT_EXP1, GIO_ADDR_EXP1, SGI_IP20, -1 }, + { GIO_SLOT_EXP1, GIO_ADDR_EXP1, SGI_IP22, IP22_INDY }, + { GIO_SLOT_EXP1, GIO_ADDR_EXP1, SGI_IP22, IP22_CHALLS }, { 0, 0, 0, 0 } }; @@ -114,39 +155,25 @@ static const struct gio_probe slot_bases[] = { * * Graphics boards are not treated like expansion slot cards. Their base * addresses do not necessarily correspond to GIO slot addresses and they - * do not contain product identification words. + * do not contain product identification words. + * + * This list needs to be sorted in address order, to match the descriptions + * obtained from ARCBios. */ static const struct gio_probe gfx_bases[] = { - /* grtwo, and newport on IP22 */ - { -1, 0x1f000000, SGI_IP20, -1 }, - { -1, 0x1f000000, SGI_IP22, -1 }, - - /* light */ - { -1, 0x1f3f0000, SGI_IP20, -1 }, - - /* light (dual headed) */ - { -1, 0x1f3f8000, SGI_IP20, -1 }, - - /* grtwo, and newport on IP22 */ - { -1, 0x1f400000, SGI_IP20, -1 }, - { -1, 0x1f400000, SGI_IP22, -1 }, + { -1, GIO_ADDR_GFX, SGI_IP20, -1 }, + { -1, GIO_ADDR_GFX, SGI_IP22, -1 }, - /* grtwo */ - { -1, 0x1f600000, SGI_IP20, -1 }, - { -1, 0x1f600000, SGI_IP22, -1 }, + /* IP20 LG1/LG2 */ + { -1, GIO_ADDR_GFX + 0x003f0000, SGI_IP20, -1 }, + { -1, GIO_ADDR_GFX + 0x003f8000, SGI_IP20, -1 }, /* second head */ - /* newport */ - { -1, 0x1f800000, SGI_IP22, IP22_INDIGO2 }, - - /* newport */ - { -1, 0x1fc00000, SGI_IP22, IP22_INDIGO2 }, + { -1, GIO_ADDR_EXP0, SGI_IP22, -1 }, + { -1, GIO_ADDR_EXP1, SGI_IP22, -1 }, { 0, 0, 0, 0 } }; -/* maximum number of graphics boards possible (arbitrarily large estimate) */ -#define MAXGFX (nitems(gfx_bases) - 1) - int gio_match(struct device *parent, void *match, void *aux) { @@ -164,7 +191,7 @@ gio_attach(struct device *parent, struct device *self, void *aux) struct gio_softc *sc = (struct gio_softc *)self; struct imc_attach_args *iaa = (struct imc_attach_args *)aux; struct gio_attach_args ga; - uint32_t gfx[MAXGFX]; + uint32_t gfx[GIO_MAX_FB]; uint i, j, ngfx; printf("\n"); @@ -191,27 +218,38 @@ gio_attach(struct device *parent, struct device *self, void *aux) * If only the ARCBios component tree would be so kind as to give * us the address of the frame buffer components... */ - for (i = 0; gfx_bases[i].base != 0; i++) { - /* skip slots that don't apply to us */ - if (gfx_bases[i].mach_type != sys_config.system_type) - continue; - - if (gfx_bases[i].mach_subtype != -1 && - gfx_bases[i].mach_subtype != sys_config.system_subtype) - continue; - - ga.ga_slot = -1; - ga.ga_addr = gfx_bases[i].base; - ga.ga_iot = sc->sc_iot; - ga.ga_ioh = PHYS_TO_XKPHYS(ga.ga_addr, CCA_NC); - ga.ga_dmat = sc->sc_dmat; - ga.ga_product = -1; - - if (gio_id(ga.ga_ioh, 1) == 0) - continue; - - if (config_found_sm(self, &ga, gio_print_fb, gio_submatch)) { - gfx[ngfx++] = gfx_bases[i].base; + if (sys_config.system_type != SGI_IP22 || + sys_config.system_subtype != IP22_CHALLS) { + for (i = 0; gfx_bases[i].base != 0; i++) { + /* skip slots that don't apply to us */ + if (gfx_bases[i].mach_type != sys_config.system_type) + continue; + + if (gfx_bases[i].mach_subtype != -1 && + gfx_bases[i].mach_subtype != + sys_config.system_subtype) + continue; + + ga.ga_addr = gfx_bases[i].base; + ga.ga_ioh = PHYS_TO_XKPHYS(ga.ga_addr, CCA_NC); + + if (gio_id(ga.ga_ioh, ga.ga_addr, 1) != GIO_FAKE_FB_ID) + continue; + + ga.ga_iot = sc->sc_iot; + ga.ga_dmat = sc->sc_dmat; + ga.ga_slot = -1; + ga.ga_product = -1; + if (ngfx < GIO_MAX_FB) + ga.ga_descr = giofb_names[ngfx]; + else + ga.ga_descr = NULL; /* shouldn't happen */ + + if (config_found_sm(self, &ga, gio_print_fb, + gio_submatch)) + gfx[ngfx] = gfx_bases[i].base; + + ngfx++; } } @@ -241,16 +279,17 @@ gio_attach(struct device *parent, struct device *self, void *aux) if (skip) continue; - ga.ga_slot = slot_bases[i].slot; ga.ga_addr = slot_bases[i].base; ga.ga_iot = sc->sc_iot; ga.ga_ioh = PHYS_TO_XKPHYS(ga.ga_addr, CCA_NC); - ga.ga_dmat = sc->sc_dmat; - if (gio_id(ga.ga_ioh, 0) == 0) + if (gio_id(ga.ga_ioh, ga.ga_addr, 0) == 0) continue; + ga.ga_dmat = sc->sc_dmat; + ga.ga_slot = slot_bases[i].slot; ga.ga_product = bus_space_read_4(ga.ga_iot, ga.ga_ioh, 0); + ga.ga_descr = NULL; config_found_sm(self, &ga, gio_print, gio_submatch); } @@ -262,25 +301,41 @@ gio_attach(struct device *parent, struct device *self, void *aux) * Try and figure out whether there is a device at the given slot address. */ uint32_t -gio_id(paddr_t pa, int maybe_gfx) +gio_id(vaddr_t va, paddr_t pa, int maybe_gfx) { uint32_t id32; uint16_t id16 = 0; uint8_t id8 = 0; - if (guarded_read_4(pa, &id32) != 0) + /* + * First, attempt to read the address with various sizes. + * If the slot is pipelined, and the address does not hit a + * device register, we will not fault but read the transfer + * width back. + */ + + if (guarded_read_4(va, &id32) != 0) + return 0; + if (guarded_read_2(va | 2, &id16) != 0) + return 0; + if (guarded_read_1(va | 3, &id8) != 0) return 0; - id16 = id32 ^ 0xffff; - (void)guarded_read_2(pa | 2, &id16); - id8 = id16 ^ 0xff; - (void)guarded_read_1(pa | 3, &id8); + /* + * If the address doesn't match a base slot address, then we are + * only probing for a frame buffer. + */ + + if (pa != GIO_ADDR_GFX && pa != GIO_ADDR_EXP0 && pa != GIO_ADDR_EXP1 && + maybe_gfx == 0) + return 0; /* * If there is a real GIO device at this address (as opposed to * a graphics card), then the low-order 8 bits of each read need * to be consistent... */ + if (id8 == (id16 & 0xff) && id8 == (id32 & 0xff)) { if (GIO_PRODUCT_32BIT_ID(id8)) { if (id16 == (id32 & 0xffff)) @@ -291,8 +346,38 @@ gio_id(paddr_t pa, int maybe_gfx) } } - if (maybe_gfx) - return 1; + /* + * If there is a frame buffer device, then either we have hit a + * device register (light, grtwo), or we did not fault because + * the slot is pipelined (impact, newport). + * In the latter case, we attempt to probe a known register + * offset. + */ + + if (maybe_gfx) { + if (id32 != 4 || id16 != 2 || id8 != 1) + return GIO_FAKE_FB_ID; + + /* could be impact(4) */ + va += 0x70000; + if (guarded_read_4(va, &id32) == 0 && + guarded_read_2(va | 2, &id16) == 0 && + guarded_read_1(va | 3, &id8) == 0) { + if (id32 != 4 || id16 != 2 || id8 != 1) + return GIO_FAKE_FB_ID; + } + + /* could be newport(4) */ + va += 0x80000; + if (guarded_read_4(va, &id32) == 0 && + guarded_read_2(va | 2, &id16) == 0 && + guarded_read_1(va | 3, &id8) == 0) { + if (id32 != 4 || id16 != 2 || id8 != 1) + return GIO_FAKE_FB_ID; + } + + return 0; + } return 0; } @@ -337,7 +422,8 @@ gio_print(void *aux, const char *pnp) int gio_print_fb(void *aux, const char *pnp) { -#if 0 /* once we can know for sure there really is a frame buffer here */ + struct gio_attach_args *ga = aux; + if (pnp != NULL) printf("framebuffer at %s", pnp); @@ -345,9 +431,6 @@ gio_print_fb(void *aux, const char *pnp) printf(" addr 0x%lx", ga->ga_addr); return UNCONF; -#else - return QUIET; -#endif } int @@ -361,12 +444,13 @@ gio_search(struct device *parent, void *vcf, void *aux) if (cf->cf_loc[1 /*GIOCF_ADDR*/] == -1) return 0; - ga.ga_product = -1; - ga.ga_slot = cf->cf_loc[0 /*GIOCF_SLOT*/]; ga.ga_addr = (uint64_t)cf->cf_loc[1 /*GIOCF_ADDR*/]; ga.ga_iot = sc->sc_iot; ga.ga_ioh = PHYS_TO_XKPHYS(ga.ga_addr, CCA_NC); ga.ga_dmat = sc->sc_dmat; + ga.ga_slot = cf->cf_loc[0 /*GIOCF_SLOT*/]; + ga.ga_product = -1; + ga.ga_descr = NULL; if ((*cf->cf_attach->ca_match)(parent, cf, &ga) == 0) return 0; @@ -393,17 +477,16 @@ gio_submatch(struct device *parent, void *vcf, void *aux) return (*cf->cf_attach->ca_match)(parent, cf, aux); } -#if 0 /* XXX involve wscons_machdep somehow */ int -gio_cnattach(void) +giofb_cnprobe() { - extern struct machine_bus_dma_tag imc_bus_dma_tag; /* XXX */ - extern bus_space_t imcbus_tag; /* XXX */ struct gio_attach_args ga; - uint32_t dummy; int i; for (i = 0; gfx_bases[i].base != 0; i++) { + if (gfx_bases[i].base != giofb_consaddr) + continue; + /* skip bases that don't apply to us */ if (gfx_bases[i].mach_type != sys_config.system_type) continue; @@ -412,43 +495,93 @@ gio_cnattach(void) gfx_bases[i].mach_subtype != sys_config.system_subtype) continue; - ga.ga_slot = -1; ga.ga_addr = gfx_bases[i].base; - ga.ga_iot = &imcbus_tag; /* XXX */ + ga.ga_iot = &imcbus_tag; ga.ga_ioh = PHYS_TO_XKPHYS(ga.ga_addr, CCA_NC); - ga.ga_dmat = &imc_bus_dma_tag; /* XXX */ + ga.ga_dmat = &imc_bus_dma_tag; + ga.ga_slot = -1; ga.ga_product = -1; - - if (gio_id(ga.ga_ioh, 1) == 0) + ga.ga_descr = NULL; + + if (gio_id(ga.ga_ioh, ga.ga_addr, 1) != GIO_FAKE_FB_ID) continue; #if NGRTWO > 0 - if (grtwo_cnattach(&ga) == 0) + if (grtwo_cnprobe(&ga) != 0) return 0; #endif - #if NLIGHT > 0 - if (light_cnattach(&ga) == 0) + if (light_cnprobe(&ga) != 0) return 0; #endif - #if NNEWPORT > 0 - if (newport_cnattach(&ga) == 0) + if (newport_cnprobe(&ga) != 0) return 0; #endif - } return ENXIO; } + +int +giofb_cnattach() +{ + struct gio_attach_args ga; + int i; + + for (i = 0; gfx_bases[i].base != 0; i++) { + if (gfx_bases[i].base != giofb_consaddr) + continue; + + /* skip bases that don't apply to us */ + if (gfx_bases[i].mach_type != sys_config.system_type) + continue; + + if (gfx_bases[i].mach_subtype != -1 && + gfx_bases[i].mach_subtype != sys_config.system_subtype) + continue; + + ga.ga_addr = gfx_bases[i].base; + ga.ga_iot = &imcbus_tag; + ga.ga_ioh = PHYS_TO_XKPHYS(ga.ga_addr, CCA_NC); + ga.ga_dmat = &imc_bus_dma_tag; + ga.ga_slot = -1; + ga.ga_product = -1; + ga.ga_descr = NULL; + + if (gio_id(ga.ga_ioh, ga.ga_addr, 1) != GIO_FAKE_FB_ID) + continue; + + /* + * We still need to probe before attach since we don't + * know the frame buffer type here. + */ +#if NGRTWO > 0 + if (grtwo_cnprobe(&ga) != 0 && + grtwo_cnattach(&ga) == 0) + return 0; #endif +#if NLIGHT > 0 + if (light_cnprobe(&ga) != 0 && + light_cnattach(&ga) == 0) + return 0; +#endif +#if NNEWPORT > 0 + if (newport_cnprobe(&ga) != 0 && + newport_cnattach(&ga) == 0) + return 0; +#endif + } + + return ENXIO; +} /* * Devices living in the expansion slots must enable or disable some * GIO arbiter settings. This is accomplished via imc(4) registers. */ int -gio_arb_config(int slot, uint32_t flags) +gio_arb_config(int slot, uint32_t flags) { if (flags == 0) return (EINVAL); diff --git a/sys/arch/sgi/gio/gioreg.h b/sys/arch/sgi/gio/gioreg.h index a5bf76444e3..c6f887f3e87 100644 --- a/sys/arch/sgi/gio/gioreg.h +++ b/sys/arch/sgi/gio/gioreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: gioreg.h,v 1.1 2012/03/28 20:44:23 miod Exp $ */ +/* $OpenBSD: gioreg.h,v 1.2 2012/04/16 22:28:12 miod Exp $ */ /* $NetBSD: gioreg.h,v 1.4 2006/08/31 00:01:10 rumble Exp $ */ /* @@ -66,3 +66,8 @@ #define GIO_PRODUCT_IS_64BIT(x) (!!((x) & 0x8000)) #define GIO_PRODUCT_HAS_ROM(x) (!!((x) & 0x10000)) #define GIO_PRODUCT_MANUCODE(x) ((x) >> 18) + +#define GIO_ADDR_GFX 0x1f000000 /* 4MB */ +#define GIO_ADDR_EXP0 0x1f400000 /* 2MB */ +#define GIO_ADDR_EXP1 0x1f600000 /* 4MB */ +#define GIO_ADDR_END 0x1fa00000 diff --git a/sys/arch/sgi/gio/giovar.h b/sys/arch/sgi/gio/giovar.h index 6c35c7561da..60382b3411b 100644 --- a/sys/arch/sgi/gio/giovar.h +++ b/sys/arch/sgi/gio/giovar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: giovar.h,v 1.1 2012/03/28 20:44:23 miod Exp $ */ +/* $OpenBSD: giovar.h,v 1.2 2012/04/16 22:28:13 miod Exp $ */ /* $NetBSD: giovar.h,v 1.10 2011/07/01 18:53:46 dyoung Exp $ */ /* @@ -38,14 +38,15 @@ */ struct gio_attach_args { - bus_space_tag_t ga_iot; - bus_space_handle_t ga_ioh; - bus_dma_tag_t ga_dmat; + bus_space_tag_t ga_iot; + bus_space_handle_t ga_ioh; + bus_dma_tag_t ga_dmat; - int ga_slot; /* not valid if graphics */ - u_int64_t ga_addr; + int ga_slot; /* -1 if graphics */ + u_int64_t ga_addr; - u_int32_t ga_product; /* not valid if graphics */ + u_int32_t ga_product; /* not valid if graphics */ + const char *ga_descr; /* only valid if graphics */ }; @@ -68,8 +69,19 @@ struct gio_attach_args { #define GIO_ARB_HPC2_32BIT 0x100 /* 32-bit secondary HPC (ignores slot)*/ #define GIO_ARB_HPC2_64BIT 0x200 /* 64-bit secondary HPC (ignores slot)*/ -int gio_cnattach(void); +/* + * Maximum number of graphics boards installed. The known limit is 2, + * but we're allowing room for some surprises. + */ +#define GIO_MAX_FB 3 + int gio_arb_config(int, uint32_t); void *gio_intr_establish(int, int, int (*)(void *), void *, const char *); const char *gio_product_string(int); + +int giofb_cnattach(void); +int giofb_cnprobe(void); + +extern paddr_t giofb_consaddr; +extern const char *giofb_names[GIO_MAX_FB]; diff --git a/sys/arch/sgi/sgi/ip22_machdep.c b/sys/arch/sgi/sgi/ip22_machdep.c index 9c49a90d58d..53f9aff11f9 100644 --- a/sys/arch/sgi/sgi/ip22_machdep.c +++ b/sys/arch/sgi/sgi/ip22_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip22_machdep.c,v 1.5 2012/04/15 20:39:36 miod Exp $ */ +/* $OpenBSD: ip22_machdep.c,v 1.6 2012/04/16 22:28:14 miod Exp $ */ /* * Copyright (c) 2012 Miodrag Vallat. @@ -40,44 +40,69 @@ #include <sgi/hpc/hpcreg.h> #include <sgi/hpc/iocreg.h> +#include "gio.h" + +#if NGIO > 0 +#include <sgi/gio/gioreg.h> +#include <sgi/gio/giovar.h> +#include <sgi/gio/lightreg.h> +#endif + extern char *hw_prod; int hpc_old = 0; int bios_year; -void ip22_arcbios_walk(void); -int ip22_arcbios_walk_component(arc_config_t *); -void ip22_memory_setup(void); +void ip22_arcbios_walk(void); +int ip22_arcbios_walk_component(arc_config_t *); +void ip22_memory_setup(void); +void ip22_video_setup(void); /* * Walk the ARCBios component tree to get hardware information we can't * obtain by other means. */ +#define IP22_HAS_L2 0x01 +#define IP22_HAS_AUDIO 0x02 +#define IP22_HAS_ENOUGH_FB 0x04 static int ip22_arcwalk_results = 0; -#define IP22_HAS_L2 0x01 -#define IP22_HAS_AUDIO 0x02 + +#if NGIO > 0 +static char ip22_fb_names[GIO_MAX_FB][64]; +#endif int ip22_arcbios_walk_component(arc_config_t *cf) { struct cpu_info *ci = curcpu(); arc_config_t *child; + arc_config64_t *cf64 = (arc_config64_t *)cf; +#if NGIO > 0 + static int fbidx = 0; +#endif /* * Split secondary caches are not supported. * No IP22 processor module uses them anyway. */ if (cf->class == arc_CacheClass && cf->type == arc_SecondaryCache) { + uint64_t key; + + if (bios_is_32bit) + key = cf->key; + else + key = cf64->key; + /* * Secondary cache information is encoded as WWLLSSSS, where * WW is the number of ways (should be 01) * LL is Log2(line size) (should be 04 or 05) * SS is Log2(cache size in 4KB units) (should be 0007) */ - ci->ci_l2size = (1 << 12) << (cf->key & 0x0000ffff); + ci->ci_l2size = (1 << 12) << (key & 0x0000ffff); /* L2 line size */ - ci->ci_cacheconfiguration = 1 << ((cf->key >> 16) & 0xff); + ci->ci_cacheconfiguration = 1 << ((key >> 16) & 0xff); ip22_arcwalk_results |= IP22_HAS_L2; } @@ -87,14 +112,46 @@ ip22_arcbios_walk_component(arc_config_t *cf) ip22_arcwalk_results |= IP22_HAS_AUDIO; } - if (ip22_arcwalk_results == (IP22_HAS_L2 | IP22_HAS_AUDIO)) +#if NGIO > 0 + if (cf->class == arc_ControllerClass && + cf->type == arc_DisplayController) { + if (fbidx >= GIO_MAX_FB) { + /* + * Not worth printing a message. If the system is + * configured for glass console, it will get + * overwritten anyway. + */ + } else { + const char *id; + size_t idlen; + + if (bios_is_32bit) { + idlen = cf->id_len; + id = (const char *)(vaddr_t)cf->id; + } else { + idlen = cf64->id_len; + id = (const char *)cf64->id; + } + if (idlen != 0) { + /* skip SGI- prefix */ + if (idlen >= 4 && strncmp(id, "SGI-", 4) == 0) { + id += 4; + idlen -= 4; + } + if (idlen >= sizeof(ip22_fb_names[0])) + idlen = sizeof(ip22_fb_names[0]) - 1; + bcopy(id, ip22_fb_names[fbidx], idlen); + } + giofb_names[fbidx] = ip22_fb_names[fbidx]; + fbidx++; + } + } +#endif + + if (ip22_arcwalk_results == + (IP22_HAS_L2 | IP22_HAS_AUDIO | IP22_HAS_ENOUGH_FB)) return 0; /* abort walk */ - /* - * It is safe to assume we have a 32-bit ARCBios, until - * IP26 and IP28 support is added, hence unconditional - * use of arc_config_t. - */ for (child = (arc_config_t *)Bios_GetChild(cf); child != NULL; child = (arc_config_t *)Bios_GetPeer(child)) { if (ip22_arcbios_walk_component(child) == 0) @@ -107,6 +164,9 @@ ip22_arcbios_walk_component(arc_config_t *cf) void ip22_arcbios_walk() { +#if NGIO == 0 + ip22_arcwalk_results |= IP22_HAS_ENOUGH_FB; +#endif (void)ip22_arcbios_walk_component((arc_config_t *)Bios_GetChild(NULL)); } @@ -220,6 +280,84 @@ dopanic: } void +ip22_video_setup() +{ +#if NGIO > 0 + /* + * According to Linux, the base address of the console device, + * if there is a glass console, can be obtained by invoking the + * 8th function pointer of the vendor-specific vector table. + * + * This function returns a pointer to a list of addresses (or + * whatever struct it is), which second field is the address we + * are looking for. + * + * However, the address does not point to the base address of the + * slot the frame buffer, but to some registers in it. While this + * might help identifying the actual frame buffer type, at the + * moment we are only interested in the base address. + */ + + long (*get_gfxinfo)(void); + vaddr_t fbaddr; + paddr_t fbphys; + + if (bios_is_32bit) { + int32_t *vec, *addr; + + vec = (int32_t *)(int64_t)(int32_t)ArcBiosBase32->vendor_vect; + get_gfxinfo = (long (*)(void))(int64_t)vec[8]; + addr = (int32_t *)(int64_t)(*get_gfxinfo)(); + fbaddr = addr[1]; + } else { + int64_t *vec, *addr; + + vec = (int64_t *)ArcBiosBase64->vendor_vect; + get_gfxinfo = (long (*)(void))vec[8]; + addr = (int64_t *)(*get_gfxinfo)(); + fbaddr = addr[1]; + } + + if (fbaddr >= CKSEG1_BASE && fbaddr < CKSSEG_BASE) + fbphys = CKSEG1_TO_PHYS(fbaddr); + else if (IS_XKPHYS(fbaddr)) + fbphys = XKPHYS_TO_PHYS(fbaddr); + else + return; + + if (fbphys < GIO_ADDR_GFX || fbphys >= GIO_ADDR_END) + return; + + /* + * Try to convert the address to a slot base or, for light(4) + * frame buffers, a frame buffer base. + * + * Verified addresses: + * grtwo slot + 0x00000000 + * impact ? + * light ? + * newport slot + 0x000f0000 (NEWPORT_REX3_OFFSET) + */ + + /* light(4) only exists on IP20 */ + if (sys_config.system_type == SGI_IP20) { + paddr_t tmp = fbphys & ~((paddr_t)LIGHT_SIZE - 1); + if (tmp == LIGHT_ADDR_0 || tmp == LIGHT_ADDR_1) { + giofb_consaddr = tmp; + return; + } + } + + if (fbphys < GIO_ADDR_EXP0) + giofb_consaddr = GIO_ADDR_GFX; + else if (fbphys < GIO_ADDR_EXP1) + giofb_consaddr = GIO_ADDR_EXP0; + else + giofb_consaddr = GIO_ADDR_EXP1; +#endif +} + +void ip22_setup() { u_long cpuspeed; @@ -303,6 +441,11 @@ ip22_setup() ip22_memory_setup(); /* + * Get glass console information, if necessary. + */ + ip22_video_setup(); + + /* * Register DMA-reachable memory constraints. * hpc(4) revision 1 and 1.5 only use 28-bit address pointers, thus * only 256MB are addressable; unfortunately, since physical memory diff --git a/sys/arch/sgi/sgi/wscons_machdep.c b/sys/arch/sgi/sgi/wscons_machdep.c index 8b6cc890300..e33db0b947c 100644 --- a/sys/arch/sgi/sgi/wscons_machdep.c +++ b/sys/arch/sgi/sgi/wscons_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wscons_machdep.c,v 1.9 2010/12/03 18:29:56 shadchin Exp $ */ +/* $OpenBSD: wscons_machdep.c,v 1.10 2012/04/16 22:28:15 miod Exp $ */ /* * Copyright (c) 2010 Miodrag Vallat. @@ -50,6 +50,7 @@ #include <machine/autoconf.h> #include <machine/bus.h> +#include <machine/cpu.h> #if defined(TGT_ORIGIN) #include <machine/mnode.h> #endif @@ -57,11 +58,8 @@ #include <mips64/arcbios.h> #include <mips64/archtype.h> -#include <sgi/localbus/crimebus.h> -#include <sgi/localbus/macebus.h> -#include <sgi/localbus/macebusvar.h> - #include <dev/cons.h> +#include <dev/ic/i8042reg.h> #include <dev/ic/pckbcvar.h> #include <dev/usb/ukbdvar.h> #include <dev/wscons/wskbdvar.h> @@ -71,6 +69,13 @@ #include <sgi/dev/gbereg.h> #include <sgi/dev/iockbcvar.h> #include <sgi/dev/mkbcreg.h> +#include <sgi/gio/giovar.h> +#include <sgi/hpc/hpcreg.h> +#include <sgi/hpc/hpcvar.h> +#include <sgi/hpc/iocreg.h> +#include <sgi/localbus/crimebus.h> +#include <sgi/localbus/macebus.h> +#include <sgi/localbus/macebusvar.h> #include <sgi/xbow/impactvar.h> #include <sgi/xbow/odysseyvar.h> @@ -81,11 +86,14 @@ #endif #include "gbe.h" +#include "gio.h" #include "iockbc.h" #include "impact.h" #include "mkbc.h" #include "odyssey.h" +#include "pckbc.h" #include "ukbd.h" +#include "zskbd.h" cons_decl(ws); extern bus_addr_t comconsaddr; @@ -119,6 +127,22 @@ wscnprobe(struct consdev *cp) cp->cn_pri = CN_DEAD; switch (sys_config.system_type) { +#if defined(TGT_INDIGO) || defined(TGT_INDY) || defined(TGT_INDIGO2) + case SGI_IP20: + case SGI_IP22: + case SGI_IP26: + case SGI_IP28: +#if NGIO > 0 + if (giofb_cnprobe() == 0) { + if (strncmp(bios_console, "video", 5) == 0) + cp->cn_pri = CN_FORCED; + else + cp->cn_pri = CN_MIDPRI; + } +#endif + break; +#endif /* TGT_INDIGO || TGT_INDY || TGT_INDIGO2 */ + #if defined(TGT_O2) case SGI_O2: #if NGBE > 0 @@ -130,7 +154,7 @@ wscnprobe(struct consdev *cp) } #endif break; -#endif +#endif /* TGT_O2 */ #if defined(TGT_ORIGIN) case SGI_IP27: @@ -143,7 +167,7 @@ wscnprobe(struct consdev *cp) cp->cn_pri = CN_MIDPRI; } break; -#endif +#endif /* TGT_ORIGIN */ #if defined(TGT_OCTANE) case SGI_OCTANE: @@ -154,7 +178,7 @@ wscnprobe(struct consdev *cp) cp->cn_pri = CN_MIDPRI; } break; -#endif +#endif /* TGT_OCTANE */ default: break; @@ -172,6 +196,31 @@ static int initted; initted = 1; switch (sys_config.system_type) { +#if defined(TGT_INDIGO) || defined(TGT_INDY) || defined(TGT_INDIGO2) + case SGI_IP20: + case SGI_IP22: + case SGI_IP26: + case SGI_IP28: +#if NGIO > 0 + if (giofb_cnattach() != 0) + return; +#endif + if (sys_config.system_type == SGI_IP20) { +#if NZSKBD > 0 + extern void zskbd_cnattach(int, int); + zskbd_cnattach(0, 0); +#endif + } else { +#if NPCKBC > 0 + if (pckbc_cnattach(&hpc3bus_tag, + HPC_BASE_ADDRESS_0 + IOC_BASE + IOC_KB_REGS + 3, + KBCMDP - KBDATAP, 0)) + return; +#endif + } + break; +#endif /* TGT_INDIGO || TGT_INDY || TGT_INDIGO2 */ + #if defined(TGT_O2) case SGI_O2: #if NGBE > 0 @@ -188,7 +237,7 @@ static int initted; ukbd_cnattach(); #endif break; -#endif +#endif /* TGT_O2 */ #if defined(TGT_OCTANE) || defined(TGT_ORIGIN) case SGI_IP27: @@ -196,7 +245,7 @@ static int initted; case SGI_OCTANE: widget_cnattach(); break; -#endif +#endif /* TGT_OCTANE || TGT_ORIGIN */ default: break; @@ -324,4 +373,4 @@ widget_cnattach() ukbd_cnattach(); #endif } -#endif +#endif /* TGT_ORIGIN || TGT_OCTANE */ |