summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/sgi/dev/com_ioc.c16
-rw-r--r--sys/arch/sgi/dev/gbe.c4
-rw-r--r--sys/arch/sgi/dev/iockbc.c322
-rw-r--r--sys/arch/sgi/dev/iockbcvar.h19
-rw-r--r--sys/arch/sgi/pci/ioc.c7
-rw-r--r--sys/arch/sgi/pci/iocvar.h6
-rw-r--r--sys/arch/sgi/pci/iof.c7
-rw-r--r--sys/arch/sgi/pci/iofvar.h6
-rw-r--r--sys/arch/sgi/sgi/ip27_machdep.c44
-rw-r--r--sys/arch/sgi/sgi/ip30.h6
-rw-r--r--sys/arch/sgi/sgi/ip30_machdep.c81
-rw-r--r--sys/arch/sgi/sgi/wscons_machdep.c215
-rw-r--r--sys/arch/sgi/xbow/odyssey.c150
-rw-r--r--sys/arch/sgi/xbow/odysseyvar.h19
14 files changed, 759 insertions, 143 deletions
diff --git a/sys/arch/sgi/dev/com_ioc.c b/sys/arch/sgi/dev/com_ioc.c
index 1f5a838f20b..066900d0c11 100644
--- a/sys/arch/sgi/dev/com_ioc.c
+++ b/sys/arch/sgi/dev/com_ioc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: com_ioc.c,v 1.7 2009/10/16 00:15:46 miod Exp $ */
+/* $OpenBSD: com_ioc.c,v 1.8 2010/03/07 13:44:24 miod Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -58,13 +58,14 @@ com_ioc_probe(struct device *parent, void *match, void *aux)
struct ioc_attach_args *iaa = aux;
bus_space_tag_t iot = iaa->iaa_memt;
bus_space_handle_t ioh;
- int rv = 0, console;
+ int rv = 0, console = 0;
if (strcmp(iaa->iaa_name, com_cd.cd_name) != 0)
return 0;
- console = iaa->iaa_memh + iaa->iaa_base ==
- comconsiot->bus_base + comconsaddr;
+ if (comconsiot != NULL)
+ console = iaa->iaa_memh + iaa->iaa_base ==
+ comconsiot->bus_base + comconsaddr;
/* if it's in use as console, it's there. */
if (!(console && !comconsattached)) {
@@ -87,10 +88,11 @@ com_ioc_attach(struct device *parent, struct device *self, void *aux)
struct com_softc *sc = (void *)self;
struct ioc_attach_args *iaa = aux;
bus_space_handle_t ioh;
- int console;
+ int console = 0;
- console = iaa->iaa_memh + iaa->iaa_base ==
- comconsiot->bus_base + comconsaddr;
+ if (comconsiot != NULL)
+ console = iaa->iaa_memh + iaa->iaa_base ==
+ comconsiot->bus_base + comconsaddr;
sc->sc_hwflags = 0;
sc->sc_swflags = 0;
diff --git a/sys/arch/sgi/dev/gbe.c b/sys/arch/sgi/dev/gbe.c
index 4c2abf3529d..bb1d77865cb 100644
--- a/sys/arch/sgi/dev/gbe.c
+++ b/sys/arch/sgi/dev/gbe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gbe.c,v 1.10 2009/10/26 20:14:42 miod Exp $ */
+/* $OpenBSD: gbe.c,v 1.11 2010/03/07 13:44:24 miod Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Joel Sing <jsing@openbsd.org>
@@ -1375,5 +1375,5 @@ gbe_cnattach(bus_space_tag_t iot, bus_addr_t addr)
wsdisplay_cnattach(&gbe_stdscreen, &gbe_consdata.ri, 0, 0, attr);
gbe_console = 1;
- return (1);
+ return (0);
}
diff --git a/sys/arch/sgi/dev/iockbc.c b/sys/arch/sgi/dev/iockbc.c
index ff7a3872158..14dbafbf3a7 100644
--- a/sys/arch/sgi/dev/iockbc.c
+++ b/sys/arch/sgi/dev/iockbc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: iockbc.c,v 1.4 2009/11/18 19:03:27 miod Exp $ */
+/* $OpenBSD: iockbc.c,v 1.5 2010/03/07 13:44:24 miod Exp $ */
/*
* Copyright (c) 2006, 2007, 2009 Joel Sing <jsing@openbsd.org>
*
@@ -65,8 +65,6 @@
#include <mips64/archtype.h>
-#include <sgi/dev/iockbcreg.h>
-
#include <sgi/pci/iocreg.h>
#include <sgi/pci/iocvar.h>
#include <sgi/pci/iofreg.h>
@@ -75,6 +73,12 @@
#include <dev/ic/pckbcvar.h>
#include <dev/pckbc/pckbdvar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+#include <sgi/dev/iockbcreg.h>
+#include <sgi/dev/iockbcvar.h>
+
#include "iockbc.h"
const char *iockbc_slot_names[] = { "kbd", "mouse" };
@@ -89,13 +93,19 @@ const char *iockbc_slot_names[] = { "kbd", "mouse" };
#define DPRINTF(x...)
#endif
-struct iockbc_softc {
- struct pckbc_softc sc_pckbc;
- bus_space_tag_t iot;
- bus_space_handle_t ioh;
- bus_addr_t rx[PCKBC_NSLOTS];
- bus_addr_t tx[PCKBC_NSLOTS];
+struct iockbc_reginfo {
+ bus_addr_t rx;
+ bus_addr_t tx;
bus_addr_t cs;
+ uint32_t busy;
+};
+
+struct iockbc_softc {
+ struct pckbc_softc sc_pckbc;
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ const struct iockbc_reginfo *reginfo;
+ int console;
};
int iockbc_match(struct device *, void *, void *);
@@ -138,16 +148,20 @@ struct pckbc_slotdata {
struct pckbc_devcmd cmds[NCMD];
int rx_queue[3];
int rx_index;
+ const struct iockbc_reginfo *reginfo;
};
#define CMD_IN_QUEUE(q) (TAILQ_FIRST(&(q)->cmdqueue) != NULL)
-static int iockbc_console;
+struct pckbc_internal iockbc_consdata;
-void iockbc_attach_common(struct iockbc_softc *, bus_addr_t);
+int iockbc_is_ioc_console(struct ioc_attach_args *);
+int iockbc_is_iof_console(struct iof_attach_args *);
+void iockbc_attach_common(struct iockbc_softc *, bus_addr_t, int);
void iockbc_start(struct pckbc_internal *, pckbc_slot_t);
int iockbc_attach_slot(struct iockbc_softc *, pckbc_slot_t);
-void iockbc_init_slotdata(struct pckbc_slotdata *);
+void iockbc_init_slotdata(struct pckbc_slotdata *,
+ const struct iockbc_reginfo *);
int iockbc_submatch(struct device *, void *, void *);
int iockbcprint(void *, const char *);
int iockbcintr(void *);
@@ -165,12 +179,46 @@ int
iockbc_match(struct device *parent, void *cf, void *aux)
{
/*
- * We expect ioc and iof NOT to attach us on if there are no PS/2 ports.
+ * We expect ioc and iof NOT to attach us if there are no PS/2 ports.
*/
return 1;
}
#if NIOCKBC_IOC > 0
+/*
+ * Register assignments
+ */
+
+const struct iockbc_reginfo iockbc_ioc_normal[PCKBC_NSLOTS] = {
+ [PCKBC_KBD_SLOT] = {
+ .rx = IOC3_KBC_KBD_RX,
+ .tx = IOC3_KBC_KBD_TX,
+ .cs = IOC3_KBC_CTRL_STATUS,
+ .busy = IOC3_KBC_STATUS_KBD_WRITE_PENDING
+ },
+ [PCKBC_AUX_SLOT] = {
+ .rx = IOC3_KBC_AUX_RX,
+ .tx = IOC3_KBC_AUX_TX,
+ .cs = IOC3_KBC_CTRL_STATUS,
+ .busy = IOC3_KBC_STATUS_AUX_WRITE_PENDING
+ }
+};
+
+const struct iockbc_reginfo iockbc_ioc_inverted[PCKBC_NSLOTS] = {
+ [PCKBC_KBD_SLOT] = {
+ .rx = IOC3_KBC_AUX_RX,
+ .tx = IOC3_KBC_AUX_TX,
+ .cs = IOC3_KBC_CTRL_STATUS,
+ .busy = IOC3_KBC_STATUS_AUX_WRITE_PENDING
+ },
+ [PCKBC_AUX_SLOT] = {
+ .rx = IOC3_KBC_KBD_RX,
+ .tx = IOC3_KBC_KBD_TX,
+ .cs = IOC3_KBC_CTRL_STATUS,
+ .busy = IOC3_KBC_STATUS_KBD_WRITE_PENDING
+ }
+};
+
void
iockbc_ioc_attach(struct device *parent, struct device *self, void *aux)
{
@@ -182,18 +230,10 @@ iockbc_ioc_attach(struct device *parent, struct device *self, void *aux)
*/
if (ISSET(iaa->iaa_flags, IOC_FLAGS_OBIO) &&
- sys_config.system_type == SGI_IP35) {
- isc->rx[PCKBC_KBD_SLOT] = IOC3_KBC_AUX_RX;
- isc->rx[PCKBC_AUX_SLOT] = IOC3_KBC_KBD_RX;
- isc->tx[PCKBC_KBD_SLOT] = IOC3_KBC_AUX_TX;
- isc->tx[PCKBC_AUX_SLOT] = IOC3_KBC_KBD_TX;
- } else {
- isc->rx[PCKBC_KBD_SLOT] = IOC3_KBC_KBD_RX;
- isc->rx[PCKBC_AUX_SLOT] = IOC3_KBC_AUX_RX;
- isc->tx[PCKBC_KBD_SLOT] = IOC3_KBC_KBD_TX;
- isc->tx[PCKBC_AUX_SLOT] = IOC3_KBC_AUX_TX;
- }
- isc->cs = IOC3_KBC_CTRL_STATUS;
+ sys_config.system_type == SGI_IP35)
+ isc->reginfo = iockbc_ioc_inverted;
+ else
+ isc->reginfo = iockbc_ioc_normal;
/* Setup bus space mapping. */
isc->iot = iaa->iaa_memt;
@@ -206,22 +246,37 @@ iockbc_ioc_attach(struct device *parent, struct device *self, void *aux)
else
printf(": unable to establish interrupt\n");
- iockbc_attach_common(isc, iaa->iaa_base);
+ iockbc_attach_common(isc, iaa->iaa_base, iockbc_is_ioc_console(iaa));
}
#endif
#if NIOCKBC_IOF > 0
+/*
+ * Register assignments
+ */
+
+const struct iockbc_reginfo iockbc_iof[PCKBC_NSLOTS] = {
+ [PCKBC_KBD_SLOT] = {
+ .rx = IOC4_KBC_KBD_RX,
+ .tx = IOC4_KBC_KBD_TX,
+ .cs = IOC4_KBC_CTRL_STATUS,
+ .busy = IOC3_KBC_STATUS_KBD_WRITE_PENDING
+ },
+ [PCKBC_AUX_SLOT] = {
+ .rx = IOC4_KBC_AUX_RX,
+ .tx = IOC4_KBC_AUX_TX,
+ .cs = IOC4_KBC_CTRL_STATUS,
+ .busy = IOC3_KBC_STATUS_AUX_WRITE_PENDING
+ }
+};
+
void
iockbc_iof_attach(struct device *parent, struct device *self, void *aux)
{
struct iockbc_softc *isc = (void*)self;
struct iof_attach_args *iaa = aux;
- isc->rx[PCKBC_KBD_SLOT] = IOC4_KBC_KBD_RX;
- isc->rx[PCKBC_AUX_SLOT] = IOC4_KBC_AUX_RX;
- isc->tx[PCKBC_KBD_SLOT] = IOC4_KBC_KBD_TX;
- isc->tx[PCKBC_AUX_SLOT] = IOC4_KBC_AUX_TX;
- isc->cs = IOC4_KBC_CTRL_STATUS;
+ isc->reginfo = iockbc_iof;
/* Setup bus space mapping. */
isc->iot = iaa->iaa_memt;
@@ -234,12 +289,13 @@ iockbc_iof_attach(struct device *parent, struct device *self, void *aux)
else
printf(": unable to establish interrupt\n");
- iockbc_attach_common(isc, iaa->iaa_base);
+ iockbc_attach_common(isc, iaa->iaa_base, iockbc_is_iof_console(iaa));
}
#endif
void
-iockbc_init_slotdata(struct pckbc_slotdata *q)
+iockbc_init_slotdata(struct pckbc_slotdata *q,
+ const struct iockbc_reginfo *reginfo)
{
int i;
TAILQ_INIT(&q->cmdqueue);
@@ -250,6 +306,8 @@ iockbc_init_slotdata(struct pckbc_slotdata *q)
q->polling = 0;
q->rx_index = -1;
+
+ q->reginfo = reginfo;
}
int
@@ -277,10 +335,10 @@ iockbc_submatch(struct device *parent, void *match, void *aux)
}
int
-iockbc_attach_slot(struct iockbc_softc *sc, pckbc_slot_t slot)
+iockbc_attach_slot(struct iockbc_softc *isc, pckbc_slot_t slot)
{
- struct pckbc_softc *isc = &sc->sc_pckbc;
- struct pckbc_internal *t = isc->id;
+ struct pckbc_softc *sc = &isc->sc_pckbc;
+ struct pckbc_internal *t = sc->id;
struct pckbc_attach_args pa;
int found;
@@ -292,7 +350,7 @@ iockbc_attach_slot(struct iockbc_softc *sc, pckbc_slot_t slot)
printf("Failed to allocate slot data!\n");
return 0;
}
- iockbc_init_slotdata(t->t_slotdata[slot]);
+ iockbc_init_slotdata(t->t_slotdata[slot], &isc->reginfo[slot]);
}
pa.pa_tag = t;
@@ -304,37 +362,45 @@ iockbc_attach_slot(struct iockbc_softc *sc, pckbc_slot_t slot)
}
void
-iockbc_attach_common(struct iockbc_softc *isc, bus_addr_t addr)
+iockbc_attach_common(struct iockbc_softc *isc, bus_addr_t addr, int console)
{
struct pckbc_softc *sc = &isc->sc_pckbc;
struct pckbc_internal *t;
+ bus_addr_t cs;
uint32_t csr;
- /*
- * Setup up controller: do not force pull clock and data lines low,
- * clamp clocks after three bytes received.
- */
- csr = bus_space_read_4(isc->iot, isc->ioh, isc->cs);
- csr &= ~(IOC3_KBC_CTRL_KBD_PULL_DATA_LOW |
- IOC3_KBC_CTRL_KBD_PULL_CLOCK_LOW |
- IOC3_KBC_CTRL_AUX_PULL_DATA_LOW |
- IOC3_KBC_CTRL_AUX_PULL_CLOCK_LOW |
- IOC3_KBC_CTRL_KBD_CLAMP_1 | IOC3_KBC_CTRL_AUX_CLAMP_1);
- csr |= IOC3_KBC_CTRL_KBD_CLAMP_3 | IOC3_KBC_CTRL_AUX_CLAMP_3;
- bus_space_write_4(isc->iot, isc->ioh, isc->cs, csr);
-
- /* Setup pckbc_internal structure. */
- t = malloc(sizeof(struct pckbc_internal), M_DEVBUF,
- M_WAITOK | M_ZERO);
- t->t_iot = isc->iot;
- t->t_ioh_d = isc->ioh;
- t->t_ioh_c = isc->ioh;
- t->t_addr = addr;
- t->t_sc = sc;
- sc->id = t;
-
- timeout_set(&t->t_cleanup, iockbc_cleanup, t);
- timeout_set(&t->t_poll, iockbc_poll, t);
+ if (console) {
+ iockbc_consdata.t_sc = sc;
+ sc->id = &iockbc_consdata;
+ isc->console = 1;
+ } else {
+ /*
+ * Setup up controller: do not force pull clock and data lines
+ * low, clamp clocks after three bytes received.
+ */
+ cs = isc->reginfo[0].cs;
+ csr = bus_space_read_4(isc->iot, isc->ioh, cs);
+ csr &= ~(IOC3_KBC_CTRL_KBD_PULL_DATA_LOW |
+ IOC3_KBC_CTRL_KBD_PULL_CLOCK_LOW |
+ IOC3_KBC_CTRL_AUX_PULL_DATA_LOW |
+ IOC3_KBC_CTRL_AUX_PULL_CLOCK_LOW |
+ IOC3_KBC_CTRL_KBD_CLAMP_1 | IOC3_KBC_CTRL_AUX_CLAMP_1);
+ csr |= IOC3_KBC_CTRL_KBD_CLAMP_3 | IOC3_KBC_CTRL_AUX_CLAMP_3;
+ bus_space_write_4(isc->iot, isc->ioh, cs, csr);
+
+ /* Setup pckbc_internal structure. */
+ t = malloc(sizeof(struct pckbc_internal), M_DEVBUF,
+ M_WAITOK | M_ZERO);
+ t->t_iot = isc->iot;
+ t->t_ioh_d = isc->ioh;
+ t->t_ioh_c = isc->ioh;
+ t->t_addr = addr;
+ t->t_sc = sc;
+ sc->id = t;
+
+ timeout_set(&t->t_cleanup, iockbc_cleanup, t);
+ timeout_set(&t->t_poll, iockbc_poll, t);
+ }
/*
* Attach "slots".
@@ -368,7 +434,6 @@ iockbcintr(void *vsc)
int
iockbcintr_internal(struct pckbc_internal *t, struct pckbc_softc *sc)
{
- struct iockbc_softc *isc = (void *)sc;
pckbc_slot_t slot;
struct pckbc_slotdata *q;
int served = 0;
@@ -398,7 +463,7 @@ iockbcintr_internal(struct pckbc_internal *t, struct pckbc_softc *sc)
}
val = bus_space_read_4(t->t_iot, t->t_ioh_d,
- isc->rx[slot]);
+ q->reginfo->rx);
if ((val & IOC3_KBC_DATA_VALID) == 0)
break;
@@ -447,21 +512,17 @@ iockbc_process_input(struct pckbc_softc *sc, struct pckbc_internal *t,
int
iockbc_poll_write(struct pckbc_internal *t, pckbc_slot_t slot, int val)
{
- struct iockbc_softc *isc = (void *)t->t_sc;
+ struct pckbc_slotdata *q = t->t_slotdata[slot];
bus_space_tag_t iot = t->t_iot;
bus_space_handle_t ioh = t->t_ioh_d;
- u_int64_t stat, offset, busy;
+ u_int64_t stat;
int timeout = 10000;
- offset = isc->tx[slot];
- busy = slot == PCKBC_AUX_SLOT ? IOC3_KBC_STATUS_AUX_WRITE_PENDING :
- IOC3_KBC_STATUS_KBD_WRITE_PENDING;
-
/* Attempt to write a value to the controller. */
while (timeout--) {
- stat = bus_space_read_4(iot, ioh, isc->cs);
- if ((stat & busy) == 0) {
- bus_space_write_4(iot, ioh, offset, val & 0xff);
+ stat = bus_space_read_4(iot, ioh, q->reginfo->cs);
+ if ((stat & q->reginfo->busy) == 0) {
+ bus_space_write_4(iot, ioh, q->reginfo->tx, val & 0xff);
return 0;
}
delay(50);
@@ -474,7 +535,6 @@ iockbc_poll_write(struct pckbc_internal *t, pckbc_slot_t slot, int val)
int
iockbc_poll_read(struct pckbc_internal *t, pckbc_slot_t slot)
{
- struct iockbc_softc *isc = (void *)t->t_sc;
struct pckbc_slotdata *q = t->t_slotdata[slot];
int timeout = 10000;
u_int32_t val;
@@ -485,7 +545,7 @@ iockbc_poll_read(struct pckbc_internal *t, pckbc_slot_t slot)
/* Poll input from controller. */
while (timeout--) {
- val = bus_space_read_4(t->t_iot, t->t_ioh_d, isc->rx[slot]);
+ val = bus_space_read_4(t->t_iot, t->t_ioh_d, q->reginfo->rx);
if (val & IOC3_KBC_DATA_VALID)
break;
delay(50);
@@ -855,6 +915,7 @@ pckbc_set_inputhandler(pckbc_tag_t self, pckbc_slot_t slot, pckbc_inputfcn func,
{
struct pckbc_internal *t = (struct pckbc_internal *)self;
struct pckbc_softc *sc = t->t_sc;
+ struct iockbc_softc *isc = (struct iockbc_softc *)sc;
if (slot >= PCKBC_NSLOTS)
panic("iockbc_set_inputhandler: bad slot %d", slot);
@@ -863,7 +924,7 @@ pckbc_set_inputhandler(pckbc_tag_t self, pckbc_slot_t slot, pckbc_inputfcn func,
sc->inputarg[slot] = arg;
sc->subname[slot] = name;
- if (iockbc_console && slot == PCKBC_KBD_SLOT)
+ if ((isc == NULL || isc->console) && slot == PCKBC_KBD_SLOT)
timeout_add_sec(&t->t_poll, 1);
}
@@ -903,3 +964,110 @@ pckbc_set_poll(pckbc_tag_t self, pckbc_slot_t slot, int on)
}
}
}
+
+/*
+ * Console support.
+ *
+ * There might multiple IOC3 and/or IOC4 devices in the system; the kernel
+ * will currently only use the one the debug serial console would be attached
+ * to as the console input device, regardless of the ConsoleIn variable.
+ */
+
+static int16_t iockbc_console_nasid;
+static int iockbc_console_widget;
+static int iockbc_console_npci;
+static uint32_t iockbc_console_type;
+
+static struct pckbc_slotdata iockbc_cons_slotdata;
+
+int
+iockbc_cnattach(int16_t nasid, int widget, int npci, uint32_t type,
+ pckbc_slot_t slot)
+{
+ bus_space_tag_t iot = &sys_config.console_io;
+ bus_space_handle_t ioh = (bus_space_handle_t)iot->bus_base;
+ struct pckbc_internal *t = &iockbc_consdata;
+ const struct iockbc_reginfo *reginfo = NULL;
+ uint32_t csr;
+ int is_ioc;
+ int rc;
+
+ is_ioc = type == PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3);
+ if (is_ioc) {
+#if NIOCKBC_IOC > 0
+ if (sys_config.system_type == SGI_IP35)
+ reginfo = &iockbc_ioc_inverted[slot];
+ else
+ reginfo = &iockbc_ioc_normal[slot];
+#endif
+ } else {
+#if NIOCKBC_IOF > 0
+ reginfo = &iockbc_iof[slot];
+#endif
+ }
+ if (reginfo == NULL)
+ return ENXIO;
+
+ /*
+ * Setup up controller: do not force pull clock and data lines
+ * low, clamp clocks after three bytes received.
+ */
+ csr = bus_space_read_4(iot, ioh, reginfo->cs);
+ csr &= ~(IOC3_KBC_CTRL_KBD_PULL_DATA_LOW |
+ IOC3_KBC_CTRL_KBD_PULL_CLOCK_LOW |
+ IOC3_KBC_CTRL_AUX_PULL_DATA_LOW |
+ IOC3_KBC_CTRL_AUX_PULL_CLOCK_LOW |
+ IOC3_KBC_CTRL_KBD_CLAMP_1 | IOC3_KBC_CTRL_AUX_CLAMP_1);
+ csr |= IOC3_KBC_CTRL_KBD_CLAMP_3 | IOC3_KBC_CTRL_AUX_CLAMP_3;
+ bus_space_write_4(iot, ioh, reginfo->cs, csr);
+
+ /* Setup pckbc_internal structure. */
+ t->t_iot = iot;
+ t->t_ioh_d = (bus_space_handle_t)iot->bus_base;
+ t->t_addr = 0; /* unused */
+
+ timeout_set(&t->t_cleanup, iockbc_cleanup, t);
+ timeout_set(&t->t_poll, iockbc_poll, t);
+
+ iockbc_init_slotdata(&iockbc_cons_slotdata, reginfo);
+ t->t_slotdata[slot] = &iockbc_cons_slotdata;
+
+ rc = pckbd_cnattach(t, slot);
+
+ /*
+ * Upon success, remember our configuration to be able to
+ * recognize the console input device during autoconf.
+ */
+ if (rc == 0) {
+ iockbc_console_nasid = nasid;
+ iockbc_console_widget = widget;
+ iockbc_console_npci = npci;
+ iockbc_console_type = type;
+ }
+
+ return rc;
+}
+
+#if NIOCKBC_IOC > 0
+int
+iockbc_is_ioc_console(struct ioc_attach_args *iaa)
+{
+ return iaa->iaa_nasid == iockbc_console_nasid &&
+ iaa->iaa_widget == iockbc_console_widget &&
+ iaa->iaa_npci == iockbc_console_npci &&
+ iockbc_console_type ==
+ PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3);
+}
+#endif
+
+#if NIOCKBC_IOF > 0
+int
+iockbc_is_iof_console(struct iof_attach_args *iaa)
+{
+ return iaa->iaa_nasid == iockbc_console_nasid &&
+ iaa->iaa_widget == iockbc_console_widget &&
+ iaa->iaa_npci == iockbc_console_npci &&
+ iockbc_console_type ==
+ PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC4);
+}
+#endif
diff --git a/sys/arch/sgi/dev/iockbcvar.h b/sys/arch/sgi/dev/iockbcvar.h
new file mode 100644
index 00000000000..e0a8ecc2910
--- /dev/null
+++ b/sys/arch/sgi/dev/iockbcvar.h
@@ -0,0 +1,19 @@
+/* $OpenBSD: iockbcvar.h,v 1.1 2010/03/07 13:44:24 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 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.
+ */
+
+int iockbc_cnattach(int16_t, int, int, uint32_t, pckbc_slot_t);
diff --git a/sys/arch/sgi/pci/ioc.c b/sys/arch/sgi/pci/ioc.c
index 24f64f2adaa..e1aa1afe2fb 100644
--- a/sys/arch/sgi/pci/ioc.c
+++ b/sys/arch/sgi/pci/ioc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ioc.c,v 1.31 2009/11/11 15:56:42 miod Exp $ */
+/* $OpenBSD: ioc.c,v 1.32 2010/03/07 13:44:26 miod Exp $ */
/*
* Copyright (c) 2008 Joel Sing.
@@ -66,6 +66,7 @@ struct ioc_intr {
struct ioc_softc {
struct device sc_dev;
+ int sc_npci;
struct mips_bus_space *sc_mem_bus_space;
@@ -170,6 +171,7 @@ ioc_attach(struct device *parent, struct device *self, void *aux)
}
sc->sc_pc = pa->pa_pc;
+ sc->sc_npci = pa->pa_device;
sc->sc_dmat = pa->pa_dmat;
/*
@@ -443,6 +445,9 @@ ioc_attach_child(struct ioc_softc *sc, const char *name, bus_addr_t base,
memset(&iaa, 0, sizeof iaa);
iaa.iaa_name = name;
+ iaa.iaa_nasid = pci_get_nasid(sc->sc_pc);
+ iaa.iaa_widget = pci_get_widget(sc->sc_pc);
+ iaa.iaa_npci = sc->sc_npci;
iaa.iaa_memt = sc->sc_memt;
iaa.iaa_memh = sc->sc_memh;
iaa.iaa_dmat = sc->sc_dmat;
diff --git a/sys/arch/sgi/pci/iocvar.h b/sys/arch/sgi/pci/iocvar.h
index 172e533e54e..6071e2bd24f 100644
--- a/sys/arch/sgi/pci/iocvar.h
+++ b/sys/arch/sgi/pci/iocvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iocvar.h,v 1.4 2009/11/11 15:56:42 miod Exp $ */
+/* $OpenBSD: iocvar.h,v 1.5 2010/03/07 13:44:26 miod Exp $ */
/*
* Copyright (c) 2008 Miodrag Vallat.
@@ -19,6 +19,10 @@
struct ioc_attach_args {
const char *iaa_name;
+ int16_t iaa_nasid;
+ int iaa_widget;
+ int iaa_npci;
+
bus_space_tag_t iaa_memt;
bus_space_handle_t iaa_memh;
bus_dma_tag_t iaa_dmat;
diff --git a/sys/arch/sgi/pci/iof.c b/sys/arch/sgi/pci/iof.c
index 7d6a6631f7a..bf95cddb66d 100644
--- a/sys/arch/sgi/pci/iof.c
+++ b/sys/arch/sgi/pci/iof.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: iof.c,v 1.4 2009/10/13 21:17:13 miod Exp $ */
+/* $OpenBSD: iof.c,v 1.5 2010/03/07 13:44:26 miod Exp $ */
/*
* Copyright (c) 2009 Miodrag Vallat.
@@ -56,6 +56,7 @@ struct iof_intr {
struct iof_softc {
struct device sc_dev;
+ int sc_npci;
struct mips_bus_space *sc_mem_bus_space;
@@ -126,6 +127,7 @@ iof_attach(struct device *parent, struct device *self, void *aux)
}
sc->sc_pc = pa->pa_pc;
+ sc->sc_npci = pa->pa_device;
sc->sc_dmat = pa->pa_dmat;
/*
@@ -210,6 +212,9 @@ iof_attach_child(struct device *iof, const char *name, bus_addr_t base,
struct iof_attach_args iaa;
iaa.iaa_name = name;
+ iaa.iaa_nasid = pci_get_nasid(sc->sc_pc);
+ iaa.iaa_widget = pci_get_widget(sc->sc_pc);
+ iaa.iaa_npci = sc->sc_npci;
iaa.iaa_memt = sc->sc_memt;
iaa.iaa_memh = sc->sc_memh;
iaa.iaa_dmat = sc->sc_dmat;
diff --git a/sys/arch/sgi/pci/iofvar.h b/sys/arch/sgi/pci/iofvar.h
index 5e8d7a09c93..97a3d00598f 100644
--- a/sys/arch/sgi/pci/iofvar.h
+++ b/sys/arch/sgi/pci/iofvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iofvar.h,v 1.2 2009/10/13 21:17:13 miod Exp $ */
+/* $OpenBSD: iofvar.h,v 1.3 2010/03/07 13:44:26 miod Exp $ */
/*
* Copyright (c) 2009 Miodrag Vallat.
@@ -19,6 +19,10 @@
struct iof_attach_args {
const char *iaa_name;
+ int16_t iaa_nasid;
+ int iaa_widget;
+ int iaa_npci;
+
bus_space_tag_t iaa_memt;
bus_space_handle_t iaa_memh;
bus_dma_tag_t iaa_dmat;
diff --git a/sys/arch/sgi/sgi/ip27_machdep.c b/sys/arch/sgi/sgi/ip27_machdep.c
index a9e4db2563b..fa4aeee8f48 100644
--- a/sys/arch/sgi/sgi/ip27_machdep.c
+++ b/sys/arch/sgi/sgi/ip27_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip27_machdep.c,v 1.42 2010/01/09 20:33:16 miod Exp $ */
+/* $OpenBSD: ip27_machdep.c,v 1.43 2010/03/07 13:44:26 miod Exp $ */
/*
* Copyright (c) 2008, 2009 Miodrag Vallat.
@@ -29,6 +29,7 @@
#include <sys/reboot.h>
#include <sys/tty.h>
+#include <mips64/arcbios.h>
#include <mips64/archtype.h>
#include <machine/autoconf.h>
@@ -58,6 +59,7 @@ paddr_t ip27_widget_short(int16_t, u_int);
paddr_t ip27_widget_long(int16_t, u_int);
paddr_t ip27_widget_map(int16_t, u_int,bus_addr_t *, bus_size_t *);
int ip27_widget_id(int16_t, u_int, uint32_t *);
+int ip27_widget_id_early(int16_t, u_int, uint32_t *);
void ip27_halt(int);
@@ -159,7 +161,7 @@ ip27_setup()
xbow_widget_base = ip27_widget_short;
xbow_widget_map = ip27_widget_map;
- xbow_widget_id = ip27_widget_id;
+ xbow_widget_id = ip27_widget_id_early;
md_halt = ip27_halt;
@@ -219,11 +221,10 @@ ip27_setup()
cons = kl_get_console();
xbow_build_bus_space(&sys_config.console_io, 0,
8 /* whatever nonzero */);
- /* Constrain to the correct window */
+ /* point to devio base */
sys_config.console_io.bus_base =
- cons->uart_base & 0xffffffffff000000UL;
-
- comconsaddr = cons->uart_base & 0x0000000000ffffffUL;
+ cons->uart_base & 0xfffffffffff00000UL;
+ comconsaddr = cons->uart_base & 0x00000000000fffffUL;
comconsrate = cons->baud;
if (comconsrate < 50 || comconsrate > 115200)
comconsrate = 9600;
@@ -236,10 +237,11 @@ ip27_setup()
paddr_t ioc4_base;
/*
- * IOC4 clocks are derived from the PCI clock, so we need to
- * figure out whether this is an 66MHz or a 33MHz bus.
+ * IOC4 clocks are derived from the PCI clock,
+ * so we need to figure out whether this is an 66MHz
+ * or a 33MHz bus.
*/
- ioc4_base = cons->uart_base & ~0xfffffUL; /* point to devio */
+ ioc4_base = sys_config.console_io.bus_base;
ioc4_mcr = *(volatile uint32_t *)(ioc4_base + IOC4_MCR);
if (ioc4_mcr & IOC4_MCR_PCI_66MHZ)
comconsfreq = 66666667;
@@ -314,6 +316,8 @@ ip27_autoconf(struct device *parent)
struct cpu_attach_args caa;
uint node;
+ xbow_widget_id = ip27_widget_id;
+
/*
* Attach the CPU we are running on early; other processors,
* if any, will get attached as they are discovered.
@@ -505,6 +509,28 @@ ip27_widget_id(int16_t nasid, u_int widget, uint32_t *wid)
}
/*
+ * Same as the above, but usable before we can handle faults.
+ * Expects the caller to only use valid widget numbers...
+ */
+int
+ip27_widget_id_early(int16_t nasid, u_int widget, uint32_t *wid)
+{
+ paddr_t wpa;
+
+ if (widget != 0)
+ {
+ if (widget < WIDGET_MIN || widget > WIDGET_MAX)
+ return EINVAL;
+ }
+
+ wpa = ip27_widget_short(nasid, widget);
+ if (wid != NULL)
+ *wid = *(uint32_t *)(wpa + (WIDGET_ID | 4));
+
+ return 0;
+}
+
+/*
* Reboot code
*/
diff --git a/sys/arch/sgi/sgi/ip30.h b/sys/arch/sgi/sgi/ip30.h
index b9b561ad99b..af851668db5 100644
--- a/sys/arch/sgi/sgi/ip30.h
+++ b/sys/arch/sgi/sgi/ip30.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip30.h,v 1.8 2010/01/19 19:54:24 miod Exp $ */
+/* $OpenBSD: ip30.h,v 1.9 2010/03/07 13:44:26 miod Exp $ */
/*
* Copyright (c) 2008, 2009 Miodrag Vallat.
@@ -34,6 +34,8 @@
#define IP30_HEART_WIDGET 8
#define IP30_BRIDGE_WIDGET 15
+#define IP30_IOC_SLOTNO 2
+
/*
* On-board IOC3 specific GPIO registers wiring
*/
@@ -93,4 +95,6 @@ struct ip30_gda {
void *tlb_handlers[3];
uint64_t nmi_count;
};
+
+int ip30_find_video(void);
#endif
diff --git a/sys/arch/sgi/sgi/ip30_machdep.c b/sys/arch/sgi/sgi/ip30_machdep.c
index 75cb72af464..29c19aab1f9 100644
--- a/sys/arch/sgi/sgi/ip30_machdep.c
+++ b/sys/arch/sgi/sgi/ip30_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip30_machdep.c,v 1.36 2010/02/28 18:01:39 miod Exp $ */
+/* $OpenBSD: ip30_machdep.c,v 1.37 2010/03/07 13:44:26 miod Exp $ */
/*
* Copyright (c) 2008, 2009 Miodrag Vallat.
@@ -38,6 +38,7 @@
#include <sgi/sgi/ip30.h>
#include <sgi/xbow/widget.h>
#include <sgi/xbow/xbow.h>
+#include <sgi/xbow/xbowdevs.h>
#include <sgi/xbow/xbridgereg.h> /* BRIDGE_PCI0_MEM_SPACE_BASE */
#include <sgi/xbow/xheartreg.h>
@@ -169,7 +170,7 @@ ip30_setup()
/*
* Initialize the early console parameters.
- * On Octane, the BRIDGE is always widet 15, and IOC3 is always
+ * On Octane, the BRIDGE is always widget 15, and IOC3 is always
* mapped in memory space at address 0x500000.
*
* Also, note that by using a direct widget bus_space, there is
@@ -180,9 +181,9 @@ ip30_setup()
xbow_build_bus_space(&sys_config.console_io, 0, 15);
sys_config.console_io.bus_base = ip30_widget_long(0, 15) +
- BRIDGE_PCI0_MEM_SPACE_BASE;
+ BRIDGE_PCI0_MEM_SPACE_BASE + 0x500000;
- comconsaddr = 0x500000 + IOC3_UARTA_BASE;
+ comconsaddr = IOC3_UARTA_BASE;
comconsfreq = 22000000 / 3;
comconsiot = &sys_config.console_io;
comconsrate = bios_getenvint("dbaud");
@@ -202,7 +203,7 @@ ip30_setup()
* Octane and Octane2 can be told apart with a GPIO source bit
* in the onboard IOC3.
*/
- ip30_iocbase = sys_config.console_io.bus_base + 0x500000;
+ ip30_iocbase = sys_config.console_io.bus_base;
if (*(volatile uint32_t *)
(ip30_iocbase + IOC3_GPPR(IP30_GPIO_CLASSIC)) != 0)
hw_prod = "Octane";
@@ -320,6 +321,76 @@ ip30_widget_id(int16_t nasid, u_int widget, uint32_t *wid)
}
/*
+ * Figure out which video widget to use.
+ *
+ * If we are running with glass console, ConsoleOut will be `video(#)' with
+ * the optional number being the number of the video device in the ARCBios
+ * component tree.
+ *
+ * Unfortunately, we do not know how to match an ARCBios component to a
+ * given widget (the PROM can... it's just not sharing this with us).
+ *
+ * So simply walk the available widget space and count video devices.
+ */
+
+int
+ip30_find_video()
+{
+ uint widid, head;
+ uint32_t id, vendor, product;
+ char *p;
+
+ if (strncmp(bios_console, "video", 5) != 0)
+ return 0; /* not graphics console */
+
+ p = bios_console + 5;
+ switch (*p) {
+ case '(':
+ /* 8 widgets max -> single digit */
+ p++;
+ if (*p == ')')
+ head = 0;
+ else {
+ if (*p < '0' || *p > '9')
+ return 0;
+ head = *p++ - '0';
+ if (*p != ')')
+ return 0;
+ }
+ break;
+ case '\0':
+ head = 0;
+ break;
+ default:
+ return 0;
+ }
+
+ for (widid = WIDGET_MIN; widid <= WIDGET_MAX; widid++) {
+ if (ip30_widget_id(0, widid, &id) != 0)
+ continue;
+
+ vendor = (id & WIDGET_ID_VENDOR_MASK) >>
+ WIDGET_ID_VENDOR_SHIFT;
+ product = (id & WIDGET_ID_PRODUCT_MASK) >>
+ WIDGET_ID_PRODUCT_SHIFT;
+
+ if ((vendor == XBOW_VENDOR_SGI2 &&
+ product == XBOW_PRODUCT_SGI2_ODYSSEY) ||
+ (vendor == XBOW_VENDOR_SGI5 &&
+ product == XBOW_PRODUCT_SGI5_IMPACT) ||
+ (vendor == XBOW_VENDOR_SGI5 &&
+ product == XBOW_PRODUCT_SGI5_KONA)) {
+ /* found a video device */
+ if (head == 0)
+ return widid;
+ head--;
+ }
+ }
+
+ return 0;
+}
+
+/*
* Fun with the lightbar
*/
uint32_t
diff --git a/sys/arch/sgi/sgi/wscons_machdep.c b/sys/arch/sgi/sgi/wscons_machdep.c
index 9c8575864d9..bd12e4725d3 100644
--- a/sys/arch/sgi/sgi/wscons_machdep.c
+++ b/sys/arch/sgi/sgi/wscons_machdep.c
@@ -1,6 +1,21 @@
-/* $OpenBSD: wscons_machdep.c,v 1.4 2009/10/26 18:00:06 miod Exp $ */
+/* $OpenBSD: wscons_machdep.c,v 1.5 2010/03/07 13:44:26 miod Exp $ */
/*
+ * Copyright (c) 2010 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) 2001 Aaron Campbell
* All rights reserved.
*
@@ -35,31 +50,57 @@
#include <machine/autoconf.h>
#include <machine/bus.h>
+#if defined(TGT_ORIGIN)
+#include <machine/mnode.h>
+#endif
#include <mips64/arcbios.h>
#include <mips64/archtype.h>
#include <sgi/localbus/crimebus.h>
+#include <sgi/localbus/macebus.h>
#include <sgi/localbus/macebusvar.h>
-#include <sgi/dev/gbereg.h>
-#include <sgi/dev/mkbcreg.h>
-
#include <dev/cons.h>
#include <dev/ic/pckbcvar.h>
#include <dev/usb/ukbdvar.h>
#include <dev/wscons/wskbdvar.h>
#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
-#include "gbe.h"
-#include "mkbc.h"
+#include <sgi/dev/gbereg.h>
+#include <sgi/dev/iockbcvar.h>
+#include <sgi/dev/mkbcreg.h>
+#include <sgi/xbow/odysseyvar.h>
-#include "wsdisplay.h"
-#if NWSDISPLAY > 0
-#include <dev/wscons/wsdisplayvar.h>
+#if defined(TGT_OCTANE)
+#include <sgi/sgi/ip30.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
#endif
+#include "gbe.h"
+#include "iockbc.h"
+#include "mkbc.h"
+#include "odyssey.h"
+#include "ukbd.h"
+
cons_decl(ws);
+extern bus_addr_t comconsaddr;
+
+#if defined(TGT_OCTANE) || defined(TGT_ORIGIN)
+int16_t output_widget_nasid;
+int output_widget_id;
+int (*output_widget_cninit)(int16_t, int) = NULL;
+
+int16_t input_widget_nasid;
+int input_widget_id;
+int input_widget_npci;
+uint32_t input_widget_type;
+
+int widget_cnprobe(void);
+void widget_cnattach(void);
+#endif
void
wscnprobe(struct consdev *cp)
@@ -81,9 +122,10 @@ wscnprobe(struct consdev *cp)
cp->cn_pri = CN_DEAD;
switch (sys_config.system_type) {
+#if defined(TGT_O2)
case SGI_O2:
#if NGBE > 0
- if (gbe_cnprobe(&crimebus_tag, GBE_BASE)) {
+ if (gbe_cnprobe(&crimebus_tag, GBE_BASE) != 0) {
if (strncmp(bios_console, "video", 5) == 0)
cp->cn_pri = CN_FORCED;
else
@@ -91,6 +133,32 @@ wscnprobe(struct consdev *cp)
}
#endif
break;
+#endif
+
+#if defined(TGT_ORIGIN)
+ case SGI_IP27:
+ case SGI_IP35:
+ if (widget_cnprobe() != 0) {
+ if (strncmp(bios_console,
+ "/dev/graphics/textport", 22) == 0)
+ cp->cn_pri = CN_FORCED;
+ else
+ cp->cn_pri = CN_MIDPRI;
+ }
+ break;
+#endif
+
+#if defined(TGT_OCTANE)
+ case SGI_OCTANE:
+ if (widget_cnprobe() != 0) {
+ if (strncmp(bios_console, "video", 5) == 0)
+ cp->cn_pri = CN_FORCED;
+ else
+ cp->cn_pri = CN_MIDPRI;
+ }
+ break;
+#endif
+
default:
break;
}
@@ -106,14 +174,37 @@ static int initted;
initted = 1;
+ switch (sys_config.system_type) {
+#if defined(TGT_O2)
+ case SGI_O2:
#if NGBE > 0
- if (!gbe_cnattach(&crimebus_tag, GBE_BASE))
- return;
+ if (gbe_cnattach(&crimebus_tag, GBE_BASE) != 0)
+ return;
#endif
+
#if NMKBC > 0
- if (!mkbc_cnattach(&macebus_tag, 0x00320000, PCKBC_KBD_SLOT))
- return;
+ if (mkbc_cnattach(&macebus_tag, MACE_IO_KBC_OFFS,
+ PCKBC_KBD_SLOT) == 0)
+ return; /* console keyboard found */
#endif
+#if NUKBD > 0
+ /* fallback keyboard console attachment if the others failed */
+ ukbd_cnattach();
+#endif
+ break;
+#endif
+
+#if defined(TGT_OCTANE) || defined(TGT_ORIGIN)
+ case SGI_IP27:
+ case SGI_IP35:
+ case SGI_OCTANE:
+ widget_cnattach();
+ break;
+#endif
+
+ default:
+ break;
+ }
}
void
@@ -139,3 +230,99 @@ wscnpollc(dev_t dev, int on)
{
wskbd_cnpollc(dev, on);
}
+
+/*
+ * Try to figure out if we have a glass console widget, and if we have
+ * a driver for it.
+ */
+
+#if defined(TGT_OCTANE) || defined(TGT_ORIGIN)
+int
+widget_cnprobe()
+{
+#ifdef TGT_ORIGIN
+ console_t *cons;
+#endif
+
+ switch (sys_config.system_type) {
+#ifdef TGT_ORIGIN
+ case SGI_IP27:
+ case SGI_IP35:
+ /*
+ * Our first pass over the KL configuration data has figured
+ * out which component is the glass console, if any.
+ */
+ if (kl_glass_console == NULL)
+ return 0;
+ output_widget_nasid = kl_glass_console->nasid;
+ output_widget_id = kl_glass_console->widid;
+
+ cons = kl_get_console();
+ input_widget_nasid = cons->nasid;
+ input_widget_id = cons->wid;
+ input_widget_npci = cons->npci;
+ input_widget_type = (uint32_t)cons->type;
+ break;
+#endif
+#ifdef TGT_OCTANE
+ case SGI_OCTANE:
+ output_widget_nasid = masternasid;
+ output_widget_id = ip30_find_video();
+ if (output_widget_id == 0)
+ return 0;
+
+ input_widget_nasid = masternasid;
+ input_widget_id = IP30_BRIDGE_WIDGET;
+ input_widget_npci = IP30_IOC_SLOTNO;
+ input_widget_type =
+ PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3);
+ break;
+#endif
+ default:
+ return 0;
+ }
+
+ /*
+ * Try supported frame buffers in no particular order.
+ */
+
+#if NODYSSEY > 0
+ if (odyssey_cnprobe(output_widget_nasid, output_widget_id) != 0) {
+ output_widget_cninit = odyssey_cnattach;
+ goto success;
+ }
+#endif
+
+ return 0;
+
+success:
+ /*
+ * At this point, we are commited to setup a glass console,
+ * so prevent serial console from winning over.
+ */
+ comconsaddr = 0;
+
+ return 1;
+}
+
+void
+widget_cnattach()
+{
+ /* should not happen */
+ if (output_widget_cninit == NULL)
+ return;
+
+ if ((*output_widget_cninit)(output_widget_nasid, output_widget_id) != 0)
+ return;
+
+#if NIOCKBC > 0
+ if (iockbc_cnattach(input_widget_nasid, input_widget_id,
+ input_widget_npci, input_widget_type, PCKBC_KBD_SLOT) == 0)
+ return; /* console keyboard found */
+#endif
+#if NUKBD > 0
+ /* fallback keyboard console attachment if the others failed */
+ ukbd_cnattach();
+#endif
+}
+#endif
diff --git a/sys/arch/sgi/xbow/odyssey.c b/sys/arch/sgi/xbow/odyssey.c
index b7cc082de55..f425da0ef19 100644
--- a/sys/arch/sgi/xbow/odyssey.c
+++ b/sys/arch/sgi/xbow/odyssey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: odyssey.c,v 1.1 2010/03/04 14:50:35 jsing Exp $ */
+/* $OpenBSD: odyssey.c,v 1.2 2010/03/07 13:44:26 miod Exp $ */
/*
* Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org>
*
@@ -36,9 +36,11 @@
#include <mips64/arcbios.h>
+#include <sgi/xbow/odysseyreg.h>
+#include <sgi/xbow/odysseyvar.h>
+#include <sgi/xbow/widget.h>
#include <sgi/xbow/xbow.h>
#include <sgi/xbow/xbowdevs.h>
-#include <sgi/xbow/odysseyreg.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
@@ -86,6 +88,8 @@ struct odyssey_softc {
int odyssey_match(struct device *, void *, void *);
void odyssey_attach(struct device *, struct device *, void *);
+int odyssey_is_console(struct xbow_attach_args *);
+
void odyssey_cmd_wait(struct odyssey_softc *);
void odyssey_data_wait(struct odyssey_softc *);
void odyssey_cmd_flush(struct odyssey_softc *, int);
@@ -126,6 +130,9 @@ int odyssey_show_screen(void *, void *, int, void (*)(void *, int, int),
void *);
void odyssey_burner(void *, u_int, u_int);
+static struct odyssey_screen odyssey_consdata;
+static struct odyssey_softc odyssey_cons_sc;
+
struct wsscreen_descr odyssey_stdscreen = {
"std", /* Screen name. */
};
@@ -192,36 +199,47 @@ odyssey_attach(struct device *parent, struct device *self, void *aux)
bcopy(xaa->xaa_iot, &sc->iot_store, sizeof(struct mips_bus_space));
sc->iot = &sc->iot_store;
- /*
- * Setup screen data.
- */
- sc->curscr = malloc(sizeof(struct odyssey_screen), M_DEVBUF, M_NOWAIT);
- if (sc->curscr == NULL) {
- printf("failed to allocate screen memory!\n");
- return;
- }
- sc->curscr->sc = (void *)sc;
- screen = sc->curscr;
-
/* Setup bus space mappings. */
if (bus_space_map(sc->iot, ODYSSEY_REG_OFFSET, ODYSSEY_REG_SIZE,
BUS_SPACE_MAP_LINEAR, &sc->ioh)) {
- printf("failed to map framebuffer bus space!\n");
+ printf("failed to map bus space!\n");
return;
}
- /* Setup hardware and clear screen. */
- odyssey_setup(sc);
- odyssey_fillrect(sc, 0, 0, 1280, 1024, 0x000000);
- odyssey_cmd_flush(sc, 0);
+ if (odyssey_is_console(xaa)) {
+ /*
+ * Setup has already been done via odyssey_cnattach().
+ */
+ screen = &odyssey_consdata;
+ sc->curscr = screen;
+ sc->curscr->sc = (void *)sc;
+ sc->console = 1;
+ } else {
+ /*
+ * Setup screen data.
+ */
+ sc->curscr = malloc(sizeof(struct odyssey_screen), M_DEVBUF,
+ M_NOWAIT);
+ if (sc->curscr == NULL) {
+ printf("failed to allocate screen memory!\n");
+ return;
+ }
+ sc->curscr->sc = (void *)sc;
+ screen = sc->curscr;
- /* Set screen defaults. */
- screen->width = 1280;
- screen->height = 1024;
- screen->depth = 32;
- screen->linebytes = screen->width * screen->depth / 8;
+ /* Setup hardware and clear screen. */
+ odyssey_setup(sc);
+ odyssey_fillrect(sc, 0, 0, 1280, 1024, 0x000000);
+ odyssey_cmd_flush(sc, 0);
- odyssey_init_screen(screen);
+ /* Set screen defaults. */
+ screen->width = 1280;
+ screen->height = 1024;
+ screen->depth = 32;
+ screen->linebytes = screen->width * screen->depth / 8;
+
+ odyssey_init_screen(screen);
+ }
waa.console = sc->console;
waa.scrdata = &odyssey_screenlist;
@@ -1046,3 +1064,87 @@ ieee754_sp(int32_t v)
return (sign << 31) | (exp << 23) | ((v << (23 - i)) & 0x7fffff);
}
+
+/*
+ * Console support.
+ */
+
+static int16_t odyssey_console_nasid;
+static int odyssey_console_widget;
+
+int
+odyssey_cnprobe(int16_t nasid, int widget)
+{
+ u_int32_t wid, vendor, product;
+
+ /* Probe for Odyssey graphics card. */
+ if (xbow_widget_id(nasid, widget, &wid) != 0)
+ return 0;
+
+ vendor = (wid & WIDGET_ID_VENDOR_MASK) >> WIDGET_ID_VENDOR_SHIFT;
+ product = (wid & WIDGET_ID_PRODUCT_MASK) >> WIDGET_ID_PRODUCT_SHIFT;
+
+ if (vendor != XBOW_VENDOR_SGI2 || product != XBOW_PRODUCT_SGI2_ODYSSEY)
+ return 0;
+
+ if (strncmp(bios_graphics, "alive", 5) != 0)
+ return 0;
+
+ return 1;
+}
+
+int
+odyssey_cnattach(int16_t nasid, int widget)
+{
+ struct odyssey_softc *sc;
+ struct odyssey_screen *screen;
+ long attr;
+ int rc;
+
+ sc = &odyssey_cons_sc;
+ screen = &odyssey_consdata;
+ sc->curscr = screen;
+ sc->curscr->sc = (void *)sc;
+
+ /* Build bus space accessor. */
+ xbow_build_bus_space(&sc->iot_store, nasid, widget);
+ sc->iot = &sc->iot_store;
+
+ /* Setup bus space mappings. */
+ rc = bus_space_map(sc->iot, ODYSSEY_REG_OFFSET, ODYSSEY_REG_SIZE,
+ BUS_SPACE_MAP_LINEAR, &sc->ioh);
+ if (rc != 0)
+ return rc;
+
+ /* Setup hardware and clear screen. */
+ odyssey_setup(sc);
+ odyssey_fillrect(sc, 0, 0, 1280, 1024, 0x000000);
+ odyssey_cmd_flush(sc, 0);
+
+ /* Set screen defaults. */
+ screen->width = 1280;
+ screen->height = 1024;
+ screen->depth = 32;
+ screen->linebytes = screen->width * screen->depth / 8;
+
+ odyssey_init_screen(screen);
+
+ /*
+ * Attach wsdisplay.
+ */
+ odyssey_consdata.ri.ri_ops.alloc_attr(&odyssey_consdata.ri,
+ 0, 0, 0, &attr);
+ wsdisplay_cnattach(&odyssey_stdscreen, &odyssey_consdata.ri,
+ 0, 0, attr);
+ odyssey_console_nasid = nasid;
+ odyssey_console_widget = widget;
+
+ return 0;
+}
+
+int
+odyssey_is_console(struct xbow_attach_args *xaa)
+{
+ return xaa->xaa_nasid == odyssey_console_nasid &&
+ xaa->xaa_widget == odyssey_console_widget;
+}
diff --git a/sys/arch/sgi/xbow/odysseyvar.h b/sys/arch/sgi/xbow/odysseyvar.h
new file mode 100644
index 00000000000..f11567a12a9
--- /dev/null
+++ b/sys/arch/sgi/xbow/odysseyvar.h
@@ -0,0 +1,19 @@
+/* $OpenBSD: odysseyvar.h,v 1.1 2010/03/07 13:44:26 miod Exp $ */
+/*
+ * Copyright (c) 2010 Joel Sing <jsing@openbsd.org>
+ *
+ * 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.
+ */
+
+int odyssey_cnprobe(int16_t, int);
+int odyssey_cnattach(int16_t, int);