diff options
Diffstat (limited to 'sys/arch/sgi/dev')
29 files changed, 0 insertions, 10806 deletions
diff --git a/sys/arch/sgi/dev/com_ioc.c b/sys/arch/sgi/dev/com_ioc.c deleted file mode 100644 index cb8adcc79e9..00000000000 --- a/sys/arch/sgi/dev/com_ioc.c +++ /dev/null @@ -1,131 +0,0 @@ -/* $OpenBSD: com_ioc.c,v 1.9 2012/10/03 22:46:09 miod Exp $ */ - -/* - * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/tty.h> - -#include <machine/autoconf.h> -#include <machine/bus.h> -#include <machine/intr.h> - -#include <dev/ic/comreg.h> -#include <dev/ic/comvar.h> -#include <dev/ic/ns16550reg.h> - -#include <sgi/pci/iocvar.h> - -int com_ioc_probe(struct device *, void *, void *); -void com_ioc_attach(struct device *, struct device *, void *); - -struct cfattach com_ioc_ca = { - sizeof(struct com_softc), com_ioc_probe, com_ioc_attach -}; - -extern struct cfdriver com_cd; - -int -com_ioc_probe(struct device *parent, void *match, void *aux) -{ - struct cfdata *cf = match; - struct ioc_attach_args *iaa = aux; - bus_space_tag_t iot = iaa->iaa_memt; - bus_space_handle_t ioh; - int rv = 0, console = 0; - - if (strcmp(iaa->iaa_name, com_cd.cd_name) != 0) - return 0; - - 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)) { - if (bus_space_subregion(iot, iaa->iaa_memh, - iaa->iaa_base, COM_NPORTS, &ioh) == 0) - rv = comprobe1(iot, ioh); - } else - rv = 1; - - /* make a config stanza with exact locators match over a generic line */ - if (cf->cf_loc[0] != -1) - rv += rv; - - return rv; -} - -void -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 = 0; - - if (comconsiot != NULL) - console = iaa->iaa_memh + iaa->iaa_base == - comconsiot->bus_base + comconsaddr; - - sc->sc_hwflags = 0; - sc->sc_swflags = 0; - sc->sc_frequency = 22000000 / 3; - - /* if it's in use as console, it's there. */ - if (!(console && !comconsattached)) { - sc->sc_iot = iaa->iaa_memt; - sc->sc_iobase = iaa->iaa_base; - - if (bus_space_subregion(iaa->iaa_memt, iaa->iaa_memh, - iaa->iaa_base, COM_NPORTS, &ioh) != 0) { - printf(": can't map registers\n"); - return; - } - } else { - /* - * If we are the console, reuse the existing bus_space - * information, so that comcnattach() invokes bus_space_map() - * with correct parameters. - */ - sc->sc_iot = comconsiot; - sc->sc_iobase = comconsaddr; - - if (comcnattach(sc->sc_iot, sc->sc_iobase, comconsrate, - sc->sc_frequency, (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8)) - panic("can't setup serial console"); - ioh = comconsioh; - } - - sc->sc_ioh = ioh; - - com_attach_subr(sc); - - ioc_intr_establish(parent, iaa->iaa_dev, IPL_TTY, comintr, - (void *)sc, sc->sc_dev.dv_xname); -} diff --git a/sys/arch/sgi/dev/com_iof.c b/sys/arch/sgi/dev/com_iof.c deleted file mode 100644 index 0bbe36fae3d..00000000000 --- a/sys/arch/sgi/dev/com_iof.c +++ /dev/null @@ -1,128 +0,0 @@ -/* $OpenBSD: com_iof.c,v 1.5 2009/10/16 00:15:46 miod Exp $ */ - -/* - * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/tty.h> - -#include <machine/autoconf.h> -#include <machine/bus.h> - -#include <dev/ic/comreg.h> -#include <dev/ic/comvar.h> -#include <dev/ic/ns16550reg.h> - -#include <sgi/pci/iofvar.h> - -int com_iof_probe(struct device *, void *, void *); -void com_iof_attach(struct device *, struct device *, void *); - -struct cfattach com_iof_ca = { - sizeof(struct com_softc), com_iof_probe, com_iof_attach -}; - -extern struct cfdriver com_cd; - -int -com_iof_probe(struct device *parent, void *match, void *aux) -{ - struct cfdata *cf = match; - struct iof_attach_args *iaa = aux; - bus_space_tag_t iot = iaa->iaa_memt; - bus_space_handle_t ioh; - int rv = 0, console; - - if (strcmp(iaa->iaa_name, com_cd.cd_name) != 0) - return 0; - - console = iaa->iaa_memh + iaa->iaa_base == - comconsiot->bus_base + comconsaddr; - - /* if it's in use as console, it's there. */ - if (!(console && !comconsattached)) { - if (bus_space_subregion(iot, iaa->iaa_memh, - iaa->iaa_base, COM_NPORTS, &ioh) == 0) - rv = comprobe1(iot, ioh); - } else - rv = 1; - - /* make a config stanza with exact locators match over a generic line */ - if (cf->cf_loc[0] != -1) - rv += rv; - - return rv; -} - -void -com_iof_attach(struct device *parent, struct device *self, void *aux) -{ - struct com_softc *sc = (void *)self; - struct iof_attach_args *iaa = aux; - bus_space_handle_t ioh; - int console; - - console = iaa->iaa_memh + iaa->iaa_base == - comconsiot->bus_base + comconsaddr; - - sc->sc_hwflags = 0; - sc->sc_swflags = 0; - sc->sc_frequency = iaa->iaa_clock; - - /* if it's in use as console, it's there. */ - if (!(console && !comconsattached)) { - sc->sc_iot = iaa->iaa_memt; - sc->sc_iobase = iaa->iaa_base; - - if (bus_space_subregion(iaa->iaa_memt, iaa->iaa_memh, - iaa->iaa_base, COM_NPORTS, &ioh) != 0) { - printf(": can't map registers\n"); - return; - } - } else { - /* - * If we are the console, reuse the existing bus_space - * information, so that comcnattach() invokes bus_space_map() - * with correct parameters. - */ - sc->sc_iot = comconsiot; - sc->sc_iobase = comconsaddr; - - if (comcnattach(sc->sc_iot, sc->sc_iobase, comconsrate, - sc->sc_frequency, (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8)) - panic("can't setup serial console"); - ioh = comconsioh; - } - - sc->sc_ioh = ioh; - - com_attach_subr(sc); - - iof_intr_establish(parent, iaa->iaa_dev, IPL_TTY, comintr, - (void *)sc, sc->sc_dev.dv_xname); -} diff --git a/sys/arch/sgi/dev/dsrtc.c b/sys/arch/sgi/dev/dsrtc.c deleted file mode 100644 index 722c647e599..00000000000 --- a/sys/arch/sgi/dev/dsrtc.c +++ /dev/null @@ -1,461 +0,0 @@ -/* $OpenBSD: dsrtc.c,v 1.14 2020/05/21 01:48:43 visa Exp $ */ - -/* - * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/systm.h> -#include <sys/device.h> - -#include <machine/autoconf.h> -#include <machine/bus.h> - -#include <dev/clock_subr.h> -#include <dev/ic/ds1687reg.h> -#include <dev/ic/mk48txxreg.h> - -#include <mips64/archtype.h> - -#include <sgi/dev/dsrtcvar.h> -#include <sgi/localbus/macebusvar.h> -#include <sgi/pci/iocreg.h> -#include <sgi/pci/iocvar.h> -#include <sgi/pci/iofvar.h> - -struct dsrtc_softc { - struct device sc_dev; - struct todr_chip_handle sc_todr; - bus_space_tag_t sc_clkt; - bus_space_handle_t sc_clkh, sc_clkh2; - int sc_yrbase; - - int (*read)(struct dsrtc_softc *, int); - void (*write)(struct dsrtc_softc *, int, int); -}; - -int dsrtc_match(struct device *, void *, void *); -void dsrtc_attach_ioc(struct device *, struct device *, void *); -void dsrtc_attach_iof(struct device *, struct device *, void *); -void dsrtc_attach_macebus(struct device *, struct device *, void *); - -struct cfdriver dsrtc_cd = { - NULL, "dsrtc", DV_DULL -}; - -struct cfattach dsrtc_macebus_ca = { - sizeof(struct dsrtc_softc), dsrtc_match, dsrtc_attach_macebus -}; - -struct cfattach dsrtc_ioc_ca = { - sizeof(struct dsrtc_softc), dsrtc_match, dsrtc_attach_ioc -}; - -struct cfattach dsrtc_iof_ca = { - sizeof(struct dsrtc_softc), dsrtc_match, dsrtc_attach_ioc -}; - -int ip32_dsrtc_read(struct dsrtc_softc *, int); -void ip32_dsrtc_write(struct dsrtc_softc *, int, int); -int ioc_ds1687_dsrtc_read(struct dsrtc_softc *, int); -void ioc_ds1687_dsrtc_write(struct dsrtc_softc *, int, int); - -int ds1687_gettime(struct todr_chip_handle *, struct timeval *); -int ds1687_settime(struct todr_chip_handle *, struct timeval *); -int ds1742_gettime(struct todr_chip_handle *, struct timeval *); -int ds1742_settime(struct todr_chip_handle *, struct timeval *); - -static inline int frombcd(int, int); -static inline int tobcd(int, int); -static inline int -frombcd(int x, int binary) -{ - return binary ? x : (x >> 4) * 10 + (x & 0xf); -} -static inline int -tobcd(int x, int binary) -{ - return binary ? x : (x / 10 * 16) + (x % 10); -} - -int -dsrtc_match(struct device *parent, void *match, void *aux) -{ - /* - * Depending on what dsrtc attaches to, the actual attach_args - * may be a different struct, but all of them start with the - * same name field. - */ - struct mainbus_attach_args *maa = aux; - - return strcmp(maa->maa_name, dsrtc_cd.cd_name) == 0; -} - -void -dsrtc_attach_ioc(struct device *parent, struct device *self, void *aux) -{ - struct dsrtc_softc *sc = (void *)self; - struct ioc_attach_args *iaa = aux; - bus_space_handle_t ih, ih2; - - /* - * The IOC3 RTC is either a Dallas (now Maxim) DS1397 or compatible - * (likely a more recent DS1687), or a DS1747 or compatible - * (itself being a Mostek MK48T35 clone). - * - * Surprisingly, the chip found on Fuel has a DS1742W label, - * which has much less memory than the DS1747. I guess whatever - * the chip is, it is mapped to the end of the DS1747 address - * space, so that the clock registers always appear at the same - * addresses in memory. - */ - - sc->sc_clkt = iaa->iaa_memt; - - if (iaa->iaa_base != IOC3_BYTEBUS_0) { - /* DS1687 */ - - if (bus_space_subregion(iaa->iaa_memt, iaa->iaa_memh, - IOC3_BYTEBUS_1, 1, &ih) != 0 || - bus_space_subregion(iaa->iaa_memt, iaa->iaa_memh, - IOC3_BYTEBUS_2, 1, &ih2) != 0) - goto fail; - - printf(": DS1687\n"); - - sc->sc_clkh = ih; - sc->sc_clkh2 = ih2; - - sc->read = ioc_ds1687_dsrtc_read; - sc->write = ioc_ds1687_dsrtc_write; - - sc->sc_todr.todr_gettime = ds1687_gettime; - sc->sc_todr.todr_settime = ds1687_settime; - } else { - /* DS1742W */ - - if (bus_space_subregion(iaa->iaa_memt, iaa->iaa_memh, - iaa->iaa_base + MK48T35_CLKOFF, - MK48T35_CLKSZ - MK48T35_CLKOFF, &ih) != 0) - goto fail; - - printf(": DS1742W\n"); - - sc->sc_clkh = ih; - - /* - * For some reason, the base year differs between IP27 - * and IP35. - */ - sc->sc_yrbase = sys_config.system_type == SGI_IP35 ? - POSIX_BASE_YEAR - 2 : POSIX_BASE_YEAR; - - sc->sc_todr.todr_gettime = ds1742_gettime; - sc->sc_todr.todr_settime = ds1742_settime; - } - sc->sc_todr.cookie = self; - todr_attach(&sc->sc_todr); - - return; - -fail: - printf(": can't map registers\n"); -} - -void -dsrtc_attach_iof(struct device *parent, struct device *self, void *aux) -{ - struct dsrtc_softc *sc = (void *)self; - struct iof_attach_args *iaa = aux; - bus_space_handle_t ih; - - /* - * The IOC4 RTC is a DS1747 or compatible (itself being a Mostek - * MK48T35 clone). - */ - - if (bus_space_subregion(iaa->iaa_memt, iaa->iaa_memh, - iaa->iaa_base + MK48T35_CLKOFF, - MK48T35_CLKSZ - MK48T35_CLKOFF, &ih) != 0) - goto fail; - - printf(": DS1742W\n"); - - sc->sc_clkh = ih; - - /* - * For some reason, the base year differs between IP27 - * and IP35. - */ - sc->sc_yrbase = sys_config.system_type == SGI_IP35 ? - POSIX_BASE_YEAR - 2 : POSIX_BASE_YEAR; - - sc->sc_todr.cookie = self; - sc->sc_todr.todr_gettime = ds1742_gettime; - sc->sc_todr.todr_settime = ds1742_settime; - todr_attach(&sc->sc_todr); - - return; - -fail: - printf(": can't map registers\n"); -} - -void -dsrtc_attach_macebus(struct device *parent, struct device *self, void *aux) -{ - struct dsrtc_softc *sc = (void *)self; - struct macebus_attach_args *maa = aux; - - sc->sc_clkt = maa->maa_iot; - if (bus_space_map(sc->sc_clkt, maa->maa_baseaddr, 128 * 256, 0, - &sc->sc_clkh)) { - printf(": can't map registers\n"); - return; - } - - printf(": DS1687\n"); - - sc->read = ip32_dsrtc_read; - sc->write = ip32_dsrtc_write; - - sc->sc_todr.cookie = self; - sc->sc_todr.todr_gettime = ds1687_gettime; - sc->sc_todr.todr_settime = ds1687_settime; - todr_attach(&sc->sc_todr); -} - -int -ip32_dsrtc_read(struct dsrtc_softc *sc, int reg) -{ - return bus_space_read_1(sc->sc_clkt, sc->sc_clkh, reg); -} - -void -ip32_dsrtc_write(struct dsrtc_softc *sc, int reg, int val) -{ - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, reg, val); -} - -int -ioc_ds1687_dsrtc_read(struct dsrtc_softc *sc, int reg) -{ - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, 0, reg); - return bus_space_read_1(sc->sc_clkt, sc->sc_clkh2, 0); -} - -void -ioc_ds1687_dsrtc_write(struct dsrtc_softc *sc, int reg, int val) -{ - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, 0, reg); - bus_space_write_1(sc->sc_clkt, sc->sc_clkh2, 0, val); -} - -/* - * Dallas DS1687 clock driver. - */ - -int -ds1687_gettime(struct todr_chip_handle *handle, struct timeval *tv) -{ - struct clock_ymdhms dt; - struct dsrtc_softc *sc = handle->cookie; - int ctrl, dm; - - /* Select bank 1. */ - ctrl = (*sc->read)(sc, DS1687_CTRL_A); - (*sc->write)(sc, DS1687_CTRL_A, ctrl | DS1687_BANK_1); - - /* Figure out which data mode to use. */ - dm = (*sc->read)(sc, DS1687_CTRL_B) & DS1687_DM_1; - - /* Wait for no update in progress. */ - while ((*sc->read)(sc, DS1687_CTRL_A) & DS1687_UIP) - /* Do nothing. */; - - /* Read the RTC. */ - dt.dt_sec = frombcd((*sc->read)(sc, DS1687_SEC), dm); - dt.dt_min = frombcd((*sc->read)(sc, DS1687_MIN), dm); - dt.dt_hour = frombcd((*sc->read)(sc, DS1687_HOUR), dm); - dt.dt_day = frombcd((*sc->read)(sc, DS1687_DAY), dm); - dt.dt_mon = frombcd((*sc->read)(sc, DS1687_MONTH), dm); - dt.dt_year = frombcd((*sc->read)(sc, DS1687_YEAR), dm); - dt.dt_year += frombcd((*sc->read)(sc, DS1687_CENTURY), dm) * 100; - - tv->tv_sec = clock_ymdhms_to_secs(&dt); - tv->tv_usec = 0; - return 0; -} - -int -ds1687_settime(struct todr_chip_handle *handle, struct timeval *tv) -{ - struct clock_ymdhms dt; - struct dsrtc_softc *sc = handle->cookie; - int year, century, ctrl, dm; - - clock_secs_to_ymdhms(tv->tv_sec, &dt); - - century = dt.dt_year / 100; - year = dt.dt_year % 100; - - /* Select bank 1. */ - ctrl = (*sc->read)(sc, DS1687_CTRL_A); - (*sc->write)(sc, DS1687_CTRL_A, ctrl | DS1687_BANK_1); - - /* Figure out which data mode to use, and select 24 hour time. */ - ctrl = (*sc->read)(sc, DS1687_CTRL_B); - dm = ctrl & DS1687_DM_1; - (*sc->write)(sc, DS1687_CTRL_B, ctrl | DS1687_24_HR); - - /* Prevent updates. */ - ctrl = (*sc->read)(sc, DS1687_CTRL_B); - (*sc->write)(sc, DS1687_CTRL_B, ctrl | DS1687_SET_CLOCK); - - /* Update the RTC. */ - (*sc->write)(sc, DS1687_SEC, tobcd(dt.dt_sec, dm)); - (*sc->write)(sc, DS1687_MIN, tobcd(dt.dt_min, dm)); - (*sc->write)(sc, DS1687_HOUR, tobcd(dt.dt_hour, dm)); - (*sc->write)(sc, DS1687_DOW, tobcd(dt.dt_wday + 1, dm)); - (*sc->write)(sc, DS1687_DAY, tobcd(dt.dt_day, dm)); - (*sc->write)(sc, DS1687_MONTH, tobcd(dt.dt_mon, dm)); - (*sc->write)(sc, DS1687_YEAR, tobcd(year, dm)); - (*sc->write)(sc, DS1687_CENTURY, tobcd(century, dm)); - - /* Enable updates. */ - (*sc->write)(sc, DS1687_CTRL_B, ctrl); - - return 0; -} - -/* - * Dallas DS1742 clock driver. - */ - -int -ds1742_gettime(struct todr_chip_handle *handle, struct timeval *tv) -{ - struct clock_ymdhms dt; - struct dsrtc_softc *sc = handle->cookie; - int csr; - - /* Freeze update. */ - csr = bus_space_read_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR); - csr |= MK48TXX_CSR_READ; - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR, csr); - - /* Read the RTC. */ - dt.dt_sec = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh, - MK48TXX_ISEC), 0); - dt.dt_min = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh, - MK48TXX_IMIN), 0); - dt.dt_hour = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh, - MK48TXX_IHOUR), 0); - dt.dt_day = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh, - MK48TXX_IDAY), 0); - dt.dt_mon = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh, - MK48TXX_IMON), 0); - dt.dt_year = frombcd(bus_space_read_1(sc->sc_clkt, sc->sc_clkh, - MK48TXX_IYEAR), 0) + sc->sc_yrbase; - - /* Enable updates again. */ - csr = bus_space_read_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR); - csr &= ~MK48TXX_CSR_READ; - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR, csr); - - tv->tv_sec = clock_ymdhms_to_secs(&dt); - tv->tv_usec = 0; - return 0; -} - -int -ds1742_settime(struct todr_chip_handle *handle, struct timeval *tv) -{ - struct clock_ymdhms dt; - struct dsrtc_softc *sc = handle->cookie; - int csr; - - clock_secs_to_ymdhms(tv->tv_sec, &dt); - - /* Enable write. */ - csr = bus_space_read_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR); - csr |= MK48TXX_CSR_WRITE; - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR, csr); - - /* Update the RTC. */ - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ISEC, - tobcd(dt.dt_sec, 0)); - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IMIN, - tobcd(dt.dt_min, 0)); - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IHOUR, - tobcd(dt.dt_hour, 0)); - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IWDAY, - tobcd(dt.dt_wday + 1, 0)); - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IDAY, - tobcd(dt.dt_day, 0)); - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IMON, - tobcd(dt.dt_mon, 0)); - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_IYEAR, - tobcd(dt.dt_year - sc->sc_yrbase, 0)); - - /* Load new values. */ - csr = bus_space_read_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR); - csr &= ~MK48TXX_CSR_WRITE; - bus_space_write_1(sc->sc_clkt, sc->sc_clkh, MK48TXX_ICSR, csr); - - return 0; -} - -/* - * Routines allowing external access to the RTC registers, used by - * power(4). - */ - -int -dsrtc_register_read(int reg) -{ - struct dsrtc_softc *sc; - - if (dsrtc_cd.cd_ndevs == 0 || - (sc = (struct dsrtc_softc *)dsrtc_cd.cd_devs[0]) == NULL || - sc->read == NULL) - return -1; - - return (*sc->read)(sc, reg); -} - -void -dsrtc_register_write(int reg, int val) -{ - struct dsrtc_softc *sc; - - if (dsrtc_cd.cd_ndevs == 0 || - (sc = (struct dsrtc_softc *)dsrtc_cd.cd_devs[0]) == NULL || - sc->write == NULL) - return; - - (*sc->write)(sc, reg, val); -} diff --git a/sys/arch/sgi/dev/dsrtcvar.h b/sys/arch/sgi/dev/dsrtcvar.h deleted file mode 100644 index e4bfd6122d3..00000000000 --- a/sys/arch/sgi/dev/dsrtcvar.h +++ /dev/null @@ -1,25 +0,0 @@ -/* $OpenBSD: dsrtcvar.h,v 1.1 2009/05/15 23:03:32 miod Exp $ */ - -/* - * Copyright (c) 2009 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. - */ - -/* - * Routines allowing external access to the RTC registers, used by - * power(4). - */ - -int dsrtc_register_read(int); -void dsrtc_register_write(int, int); diff --git a/sys/arch/sgi/dev/gbe.c b/sys/arch/sgi/dev/gbe.c deleted file mode 100644 index ba8ad0268e6..00000000000 --- a/sys/arch/sgi/dev/gbe.c +++ /dev/null @@ -1,1410 +0,0 @@ -/* $OpenBSD: gbe.c,v 1.23 2020/05/25 09:55:48 jsg Exp $ */ - -/* - * Copyright (c) 2007, 2008, 2009 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. - */ - -/* - * Graphics Back End (GBE) Framebuffer for SGI O2. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/malloc.h> - -#include <uvm/uvm_extern.h> - -#include <machine/autoconf.h> -#include <machine/bus.h> - -#include <mips64/arcbios.h> - -#include <sgi/dev/gl.h> -#include <sgi/localbus/crimebus.h> -#include <sgi/localbus/macebusvar.h> - -#include <dev/wscons/wsconsio.h> -#include <dev/wscons/wsdisplayvar.h> -#include <dev/rasops/rasops.h> - -#include "gbereg.h" - -/* Amount of memory to allocate for framebuffer. */ -#define GBE_FB_SIZE 8 * 1 << 20 - -/* - * Colourmap data. - */ -struct gbe_cmap { - u_int8_t cm_red[256]; - u_int8_t cm_green[256]; - u_int8_t cm_blue[256]; -}; - -/* - * Screen data. - */ -struct gbe_screen { - struct device *sc; /* Back pointer. */ - - struct rasops_info ri; /* Screen raster display info. */ - struct rasops_info ri_tile; /* Raster info for rasops tile. */ - struct gbe_cmap cmap; /* Display colour map. */ - - int fb_size; /* Size of framebuffer memory. */ - int tm_size; /* Size of tilemap memory. */ - - caddr_t tm; /* Address of tilemap memory. */ - paddr_t tm_phys; /* Physical address of tilemap. */ - caddr_t fb; /* Address of framebuffer memory. */ - paddr_t fb_phys; /* Physical address of framebuffer. */ - caddr_t ro; /* Address of rasops tile. */ - paddr_t ro_phys; /* Physical address of rasops tile. */ - - int width; /* Width in pixels. */ - int height; /* Height in pixels. */ - int depth; /* Colour depth in bits. */ - int mode; /* Display mode. */ - int bufmode; /* Rendering engine buffer mode. */ - int linebytes; /* Bytes per line. */ - int ro_curpos; /* Current position in rasops tile. */ -}; - -/* - * GBE device data. - */ -struct gbe_softc { - struct device sc_dev; - - bus_space_tag_t iot; - bus_space_handle_t ioh; /* GBE registers. */ - bus_space_handle_t re_ioh; /* Rendering engine registers. */ - bus_dma_tag_t dmat; - - int rev; /* Hardware revision. */ - int console; /* Is this the console? */ - int screens; /* No of screens allocated. */ - - struct gbe_screen *curscr; /* Current screen. */ -}; - -/* - * Hardware and device related functions. - */ -void gbe_init_screen(struct gbe_screen *); -void gbe_enable(struct gbe_softc *); -void gbe_disable(struct gbe_softc *); -void gbe_setup(struct gbe_softc *); -void gbe_setcolour(struct gbe_softc *, u_int, u_int8_t, u_int8_t, u_int8_t); -void gbe_wait_re_idle(struct gbe_softc *); - -/* - * Colour map handling for indexed modes. - */ -int gbe_getcmap(struct gbe_cmap *, struct wsdisplay_cmap *); -int gbe_putcmap(struct gbe_cmap *, struct wsdisplay_cmap *); -void gbe_loadcmap(struct gbe_screen *, u_int, u_int); - -/* - * Interfaces for wscons. - */ -int gbe_ioctl(void *, u_long, caddr_t, int, struct proc *); -paddr_t gbe_mmap(void *, off_t, int); -int gbe_alloc_screen(void *, const struct wsscreen_descr *, void **, - int *, int *, uint32_t *); -void gbe_free_screen(void *, void *); -int gbe_show_screen(void *, void *, int, void (*)(void *, int, int), - void *); -int gbe_load_font(void *, void *, struct wsdisplay_font *); -int gbe_list_font(void *, struct wsdisplay_font *); - -/* - * Hardware acceleration for rasops. - */ -void gbe_rop(struct gbe_softc *, int, int, int, int, int); -void gbe_copyrect(struct gbe_softc *, int, int, int, int, int, int, int); -void gbe_fillrect(struct gbe_softc *, int, int, int, int, int); -int gbe_do_cursor(struct rasops_info *); -int gbe_putchar(void *, int, int, u_int, uint32_t); -int gbe_copycols(void *, int, int, int, int); -int gbe_erasecols(void *, int, int, int, uint32_t); -int gbe_copyrows(void *, int, int, int); -int gbe_eraserows(void *, int, int, uint32_t); - -static struct gbe_screen gbe_consdata; -static int gbe_console; - -struct wsscreen_descr gbe_stdscreen = { - "std", /* Screen name. */ -}; - -struct wsdisplay_accessops gbe_accessops = { - .ioctl = gbe_ioctl, - .mmap = gbe_mmap, - .alloc_screen = gbe_alloc_screen, - .free_screen = gbe_free_screen, - .show_screen = gbe_show_screen, - .load_font = gbe_load_font, - .list_font = gbe_list_font -}; - -const struct wsscreen_descr *gbe_scrlist[] = { - &gbe_stdscreen -}; - -struct wsscreen_list gbe_screenlist = { - sizeof(gbe_scrlist) / sizeof(struct wsscreen_descr *), gbe_scrlist -}; - -int gbe_match(struct device *, void *, void *); -void gbe_attach(struct device *, struct device *, void *); -int gbe_activate(struct device *, int); - -struct cfattach gbe_ca = { - sizeof (struct gbe_softc), gbe_match, gbe_attach, - NULL, gbe_activate -}; - -struct cfdriver gbe_cd = { - NULL, "gbe", DV_DULL -}; - -int -gbe_match(struct device *parent, void *cf, void *aux) -{ - struct mainbus_attach_args *maa = aux; - - if (strcmp(maa->maa_name, gbe_cd.cd_name) != 0) - return 0; - - return 1; -} - -void -gbe_attach(struct device *parent, struct device *self, void *aux) -{ - struct gbe_softc *gsc = (void*)self; - struct gbe_screen *screen; - struct wsemuldisplaydev_attach_args waa; - bus_dma_segment_t tm_segs[1]; - bus_dma_segment_t fb_segs[1]; - bus_dma_segment_t ro_segs[1]; - bus_dmamap_t tm_dmamap; - bus_dmamap_t fb_dmamap; - bus_dmamap_t ro_dmamap; - int tm_nsegs; - int fb_nsegs; - int ro_nsegs; - uint32_t val; - uint32_t attr; - - printf(": "); - - /* GBE isn't strictly on the crimebus, but use this for now... */ - gsc->iot = &crimebus_tag; - gsc->dmat = &mace_bus_dma_tag; - gsc->console = gbe_console; - gsc->screens = 0; - - if (gsc->console == 1) { - - /* - * We've already been setup via gbe_cnattach(). - */ - - gsc->ioh = PHYS_TO_XKPHYS(GBE_BASE, CCA_NC); - gsc->re_ioh = PHYS_TO_XKPHYS(RE_BASE, CCA_NC); - - gsc->rev = bus_space_read_4(gsc->iot, gsc->ioh, GBE_CTRL_STAT) - & 0xf; - - gsc->curscr = &gbe_consdata; - gbe_consdata.sc = (void*)self; - - printf("rev %u, %iMB, %dx%d at %d bits\n", gsc->rev, - gbe_consdata.fb_size >> 20, gbe_consdata.width, - gbe_consdata.height, gbe_consdata.depth); - - waa.console = gsc->console; - waa.scrdata = &gbe_screenlist; - waa.accessops = &gbe_accessops; - waa.accesscookie = &gbe_consdata; - waa.defaultscreens = 0; - config_found(self, &waa, wsemuldisplaydevprint); - - return; - } - - /* - * Setup screen data. - */ - gsc->curscr = malloc(sizeof(struct gbe_screen), M_DEVBUF, M_NOWAIT); - if (gsc->curscr == NULL) { - printf("failed to allocate screen memory!\n"); - return; - } - gsc->curscr->sc = (void *)gsc; - screen = gsc->curscr; - - /* - * Setup bus space mappings. - */ - if (bus_space_map(gsc->iot, GBE_BASE - CRIMEBUS_BASE, GBE_REG_SIZE, - BUS_SPACE_MAP_LINEAR, &gsc->ioh)) { - printf("failed to map framebuffer bus space!\n"); - return; - } - - if (bus_space_map(gsc->iot, RE_BASE - CRIMEBUS_BASE, RE_REG_SIZE, - BUS_SPACE_MAP_LINEAR, &gsc->re_ioh)) { - printf("failed to map rendering engine bus space!\n"); - goto fail0; - } - - /* Determine GBE revision. */ - gsc->rev = bus_space_read_4(gsc->iot, gsc->ioh, GBE_CTRL_STAT) & 0xf; - - /* Determine resolution configured by firmware. */ - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_HCMAP); - screen->width = (val >> GBE_VT_HCMAP_ON_SHIFT) & 0xfff; - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_VCMAP); - screen->height = (val >> GBE_VT_VCMAP_ON_SHIFT) & 0xfff; - - if (screen->width == 0 || screen->height == 0) { - printf("device has not been setup by firmware!\n"); - goto fail1; - } - - /* Setup screen defaults. */ - screen->fb_size = GBE_FB_SIZE; - screen->tm_size = GBE_TLB_SIZE * sizeof(uint16_t); - screen->depth = 8; - screen->linebytes = screen->width * screen->depth / 8; - - /* - * Setup DMA for tilemap. - */ - if (bus_dmamap_create(gsc->dmat, screen->tm_size, 1, screen->tm_size, - 0, BUS_DMA_NOWAIT, &tm_dmamap)) { - printf("failed to create DMA map for tilemap!\n"); - goto fail1; - } - - if (bus_dmamem_alloc(gsc->dmat, screen->tm_size, 65536, 0, tm_segs, 1, - &tm_nsegs, BUS_DMA_NOWAIT)) { - printf("failed to allocate DMA memory for tilemap!\n"); - goto fail2; - } - - if (bus_dmamem_map(gsc->dmat, tm_segs, tm_nsegs, screen->tm_size, - &screen->tm, BUS_DMA_COHERENT)) { - printf("failed to map DMA memory for tilemap!\n"); - goto fail3; - } - - if (bus_dmamap_load(gsc->dmat, tm_dmamap, screen->tm, screen->tm_size, - NULL, BUS_DMA_NOWAIT)){ - printf("failed to load DMA map for tilemap\n"); - goto fail4; - } - - /* - * Setup DMA for framebuffer. - */ - if (bus_dmamap_create(gsc->dmat, screen->fb_size, 1, screen->fb_size, - 0, BUS_DMA_NOWAIT, &fb_dmamap)) { - printf("failed to create DMA map for framebuffer!\n"); - goto fail5; - } - - if (bus_dmamem_alloc(gsc->dmat, screen->fb_size, 65536, 0, fb_segs, - 1, &fb_nsegs, BUS_DMA_NOWAIT)) { - printf("failed to allocate DMA memory for framebuffer!\n"); - goto fail6; - } - - if (bus_dmamem_map(gsc->dmat, fb_segs, fb_nsegs, screen->fb_size, - &screen->fb, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) { - printf("failed to map DMA memory for framebuffer!\n"); - goto fail7; - } - - if (bus_dmamap_load(gsc->dmat, fb_dmamap, screen->fb, screen->fb_size, - NULL, BUS_DMA_NOWAIT)) { - printf("failed to load DMA map for framebuffer\n"); - goto fail8; - } - - /* - * Setup DMA for rasops tile. - */ - if (bus_dmamap_create(gsc->dmat, GBE_TILE_SIZE, 1, GBE_TILE_SIZE, - 0, BUS_DMA_NOWAIT, &ro_dmamap)) { - printf("failed to create DMA map for rasops tile!\n"); - goto fail9; - } - - if (bus_dmamem_alloc(gsc->dmat, GBE_TILE_SIZE, 65536, 0, ro_segs, - 1, &ro_nsegs, BUS_DMA_NOWAIT)) { - printf("failed to allocate DMA memory for rasops tile!\n"); - goto fail10; - } - - if (bus_dmamem_map(gsc->dmat, ro_segs, ro_nsegs, GBE_TILE_SIZE, - &screen->ro, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) { - printf("failed to map DMA memory for rasops tile!\n"); - goto fail11; - } - - if (bus_dmamap_load(gsc->dmat, ro_dmamap, screen->ro, GBE_TILE_SIZE, - NULL, BUS_DMA_NOWAIT)) { - printf("failed to load DMA map for rasops tile\n"); - goto fail12; - } - - screen->tm_phys = tm_dmamap->dm_segs[0].ds_addr; - screen->fb_phys = fb_dmamap->dm_segs[0].ds_addr; - screen->ro_phys = ro_dmamap->dm_segs[0].ds_addr; - - gbe_init_screen(screen); - gbe_disable(gsc); - gbe_setup(gsc); - gbe_enable(gsc); - - /* Load colourmap if required. */ - if (screen->depth == 8) - gbe_loadcmap(screen, 0, 255); - - /* Clear framebuffer. */ - gbe_fillrect(gsc, 0, 0, screen->width, screen->height, 0); - - printf("rev %u, %iMB, %dx%d at %d bits\n", gsc->rev, - screen->fb_size >> 20, screen->width, screen->height, - screen->depth); - - /* - * Attach wsdisplay. - */ - - /* Attach as console if necessary. */ - if (strncmp(bios_console, "video", 5) == 0) { - screen->ri.ri_ops.pack_attr(&screen->ri, 0, 0, 0, &attr); - wsdisplay_cnattach(&gbe_stdscreen, &screen->ri, 0, 0, attr); - gsc->console = 1; - } - - waa.console = gsc->console; - waa.scrdata = &gbe_screenlist; - waa.accessops = &gbe_accessops; - waa.accesscookie = screen; - waa.defaultscreens = 0; - config_found(self, &waa, wsemuldisplaydevprint); - - return; - -fail12: - bus_dmamem_unmap(gsc->dmat, screen->ro, GBE_TILE_SIZE); -fail11: - bus_dmamem_free(gsc->dmat, ro_segs, ro_nsegs); -fail10: - bus_dmamap_destroy(gsc->dmat, ro_dmamap); -fail9: - bus_dmamap_unload(gsc->dmat, fb_dmamap); -fail8: - bus_dmamem_unmap(gsc->dmat, screen->fb, screen->fb_size); -fail7: - bus_dmamem_free(gsc->dmat, fb_segs, fb_nsegs); -fail6: - bus_dmamap_destroy(gsc->dmat, fb_dmamap); -fail5: - bus_dmamap_unload(gsc->dmat, tm_dmamap); -fail4: - bus_dmamem_unmap(gsc->dmat, screen->tm, screen->tm_size); -fail3: - bus_dmamem_free(gsc->dmat, tm_segs, tm_nsegs); -fail2: - bus_dmamap_destroy(gsc->dmat, tm_dmamap); -fail1: - bus_space_unmap(gsc->iot, gsc->re_ioh, RE_REG_SIZE); -fail0: - bus_space_unmap(gsc->iot, gsc->ioh, GBE_REG_SIZE); -} - -int -gbe_activate(struct device *self, int act) -{ - struct gbe_softc *gsc = (struct gbe_softc *)self; - int ret = 0; - - switch (act) { - case DVACT_POWERDOWN: - gbe_disable(gsc); - break; - } - - return (ret); -} - -/* - * GBE hardware specific functions. - */ - -void -gbe_init_screen(struct gbe_screen *screen) -{ - uint16_t *tm; - int i; - - /* - * Initialise screen. - */ - screen->mode = WSDISPLAYIO_MODE_EMUL; - - /* Initialise rasops. */ - memset(&screen->ri, 0, sizeof(struct rasops_info)); - - screen->ri.ri_flg = RI_CENTER; - screen->ri.ri_depth = screen->depth; - screen->ri.ri_width = screen->width; - screen->ri.ri_height = screen->height; - screen->ri.ri_bits = (void *)screen->fb; - screen->ri.ri_stride = screen->linebytes; - - if (screen->depth == 32) { - screen->ri.ri_rpos = 24; - screen->ri.ri_rnum = 8; - screen->ri.ri_gpos = 16; - screen->ri.ri_gnum = 8; - screen->ri.ri_bpos = 8; - screen->ri.ri_bnum = 8; - } else if (screen->depth == 16) { - screen->ri.ri_rpos = 10; - screen->ri.ri_rnum = 5; - screen->ri.ri_gpos = 5; - screen->ri.ri_gnum = 5; - screen->ri.ri_bpos = 0; - screen->ri.ri_bnum = 5; - } - - rasops_init(&screen->ri, screen->height / 8, screen->width / 8); - - /* Create a rasops instance that can draw into a single tile. */ - memcpy(&screen->ri_tile, &screen->ri, sizeof(struct rasops_info)); - screen->ri_tile.ri_flg = 0; - screen->ri_tile.ri_width = GBE_TILE_WIDTH >> (screen->depth >> 4); - screen->ri_tile.ri_height = GBE_TILE_HEIGHT; - screen->ri_tile.ri_stride = screen->ri_tile.ri_width * - screen->depth / 8; - screen->ri_tile.ri_xorigin = 0; - screen->ri_tile.ri_yorigin = 0; - screen->ri_tile.ri_bits = screen->ro; - screen->ri_tile.ri_origbits = screen->ro; - screen->ro_curpos = 0; - - screen->ri.ri_hw = screen->sc; - - screen->ri.ri_do_cursor = gbe_do_cursor; - screen->ri.ri_ops.putchar = gbe_putchar; - screen->ri.ri_ops.copyrows = gbe_copyrows; - screen->ri.ri_ops.copycols = gbe_copycols; - screen->ri.ri_ops.eraserows = gbe_eraserows; - screen->ri.ri_ops.erasecols = gbe_erasecols; - - gbe_stdscreen.ncols = screen->ri.ri_cols; - gbe_stdscreen.nrows = screen->ri.ri_rows; - gbe_stdscreen.textops = &screen->ri.ri_ops; - gbe_stdscreen.fontwidth = screen->ri.ri_font->fontwidth; - gbe_stdscreen.fontheight = screen->ri.ri_font->fontheight; - gbe_stdscreen.capabilities = screen->ri.ri_caps; - - /* - * Map framebuffer into tilemap. Each entry in the tilemap is 16 bits - * wide. Each tile is 64KB or 2^16 bits, hence the last 16 bits of the - * address will range from 0x0000 to 0xffff. As a result we simply - * discard the lower 16 bits and store bits 17 through 32 as an entry - * in the tilemap. - */ - tm = (void *)screen->tm; - for (i = 0; i < (screen->fb_size >> GBE_TILE_SHIFT) && - i < GBE_TLB_SIZE; i++) - tm[i] = (screen->fb_phys >> GBE_TILE_SHIFT) + i; -} - -void -gbe_enable(struct gbe_softc *gsc) -{ - struct gbe_screen *screen = gsc->curscr; - uint32_t val; - int i; - - /* Enable dot clock. */ - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK, - val | GBE_DOTCLOCK_RUN); - for (i = 0; i < 10000; i++) { - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); - if ((val & GBE_DOTCLOCK_RUN) == GBE_DOTCLOCK_RUN) - break; - delay(10); - } - if (i == 10000) - printf("timeout enabling dot clock!\n"); - - /* Unfreeze pixel counter. */ - bus_space_write_4(gsc->iot, gsc->ioh, GBE_VT_XY, 0); - for (i = 0; i < 10000; i++) { - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_XY); - if ((val & GBE_VT_XY_FREEZE) == 0) - break; - delay(10); - } - if (i == 10000) - printf("timeout unfreezing pixel counter!\n"); - - /* Disable sync-on-green. */ - if (strcmp(osloadoptions, "nosog") == 0) - bus_space_write_4(gsc->iot, gsc->ioh, GBE_VT_FLAGS, - GBE_VT_SYNC_LOW); - - /* Provide GBE with address of tilemap and enable DMA. */ - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_CTRL, - ((screen->tm_phys >> 9) << - GBE_FB_CTRL_TILE_PTR_SHIFT) | GBE_FB_CTRL_DMA_ENABLE); -} - -void -gbe_disable(struct gbe_softc *gsc) -{ - uint32_t val; - int i; - - /* Nothing to do if the pixel counter is frozen! */ - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_XY); - if ((val & GBE_VT_XY_FREEZE) == GBE_VT_XY_FREEZE) - return; - - /* Enable sync-on-green. */ - bus_space_write_4(gsc->iot, gsc->ioh, GBE_VT_FLAGS, 0); - - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); - if ((val & GBE_DOTCLOCK_RUN) == 0) - return; - - /* Disable overlay and turn off hardware cursor. */ - bus_space_write_4(gsc->iot, gsc->ioh, GBE_OVERLAY_TILE, 0); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_CURSOR_CTRL, 0); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_DID_CTRL, 0); - - /* Disable DMA. */ - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_OVERLAY_CTRL); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_OVERLAY_CTRL, - val & ~GBE_OVERLAY_CTRL_DMA_ENABLE); - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_FB_CTRL); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_CTRL, - val & ~GBE_FB_CTRL_DMA_ENABLE); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_DID_CTRL, 0); - for (i = 0; i < 100000; i++) { - if ((bus_space_read_4(gsc->iot, gsc->ioh, GBE_OVERLAY_HW_CTRL) - & GBE_OVERLAY_CTRL_DMA_ENABLE) == 0 && - (bus_space_read_4(gsc->iot, gsc->ioh, GBE_FB_HW_CTRL) - & GBE_FB_CTRL_DMA_ENABLE) == 0 && - bus_space_read_4(gsc->iot, gsc->ioh, GBE_DID_HW_CTRL) == 0) - break; - delay(10); - } - if (i == 100000) - printf("timeout disabling DMA!\n"); - - /* Wait for the end of pixel refresh. */ - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_VPIX) - & GBE_VT_VPIX_OFF_MASK; - for (i = 0; i < 100000; i++) { - if (((bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_XY) - & GBE_VT_XY_Y_MASK) >> GBE_VT_XY_Y_SHIFT) < val) - break; - delay(1); - } - if (i == 100000) - printf("timeout waiting for pixel refresh!\n"); - for (i = 0; i < 100000; i++) { - if (((bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_XY) - & GBE_VT_XY_Y_MASK) >> GBE_VT_XY_Y_SHIFT) > val) - break; - delay(1); - } - if (i == 100000) - printf("timeout waiting for pixel refresh!\n"); - - /* Freeze pixel counter. */ - bus_space_write_4(gsc->iot, gsc->ioh, GBE_VT_XY, GBE_VT_XY_FREEZE); - for (i = 0; i < 100000; i++) { - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_XY); - if ((val & GBE_VT_XY_FREEZE) == GBE_VT_XY_FREEZE) - break; - delay(10); - } - if (i == 100000) - printf("timeout freezing pixel counter!\n"); - - /* Disable dot clock. */ - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK, - val & ~GBE_DOTCLOCK_RUN); - for (i = 0; i < 100000; i++) { - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_DOTCLOCK); - if ((val & GBE_DOTCLOCK_RUN) == 0) - break; - delay(10); - } - if (i == 100000) - printf("timeout disabling dot clock!\n"); - - /* Reset DMA fifo. */ - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE); - val &= ~(1 << GBE_FB_SIZE_TILE_FIFO_RESET_SHIFT); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE, - val | (1 << GBE_FB_SIZE_TILE_FIFO_RESET_SHIFT)); - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE, val); -} - -void -gbe_setup(struct gbe_softc *gsc) -{ - struct gbe_screen *screen = gsc->curscr; - int i, t, cmode, tile_width, tiles_x, tiles_y; - u_char *colour; - uint16_t *tm; - uint32_t val; - uint64_t reg; - - /* - * Setup framebuffer. - */ - switch (screen->depth) { - case 32: - cmode = GBE_CMODE_RGB8; - screen->bufmode = COLOUR_DEPTH_32 << BUFMODE_BUFDEPTH_SHIFT | - PIXEL_TYPE_RGB << BUFMODE_PIXTYPE_SHIFT | - COLOUR_DEPTH_32 << BUFMODE_PIXDEPTH_SHIFT; - break; - case 16: - cmode = GBE_CMODE_ARGB5; - screen->bufmode = COLOUR_DEPTH_16 << BUFMODE_BUFDEPTH_SHIFT | - PIXEL_TYPE_RGBA << BUFMODE_PIXTYPE_SHIFT | - COLOUR_DEPTH_16 << BUFMODE_PIXDEPTH_SHIFT; - break; - case 8: - default: - cmode = GBE_CMODE_I8; - screen->bufmode = COLOUR_DEPTH_8 << BUFMODE_BUFDEPTH_SHIFT | - PIXEL_TYPE_CI << BUFMODE_PIXTYPE_SHIFT | - COLOUR_DEPTH_8 << BUFMODE_PIXDEPTH_SHIFT; - break; - } - - /* Calculate tile width in bytes and screen size in tiles. */ - tile_width = GBE_TILE_WIDTH >> (screen->depth >> 4); - tiles_x = (screen->width + tile_width - 1) >> - (GBE_TILE_WIDTH_SHIFT - (screen->depth >> 4)); - tiles_y = (screen->height + GBE_TILE_HEIGHT - 1) >> - GBE_TILE_HEIGHT_SHIFT; - - if (screen->mode != WSDISPLAYIO_MODE_EMUL) { - - /* - * Setup the framebuffer in "linear" mode. We trick the - * framebuffer into linear mode by telling it that it is one - * tile wide and specifying an adjusted framebuffer height. - */ - - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE, - ((screen->depth >> 4) << GBE_FB_SIZE_TILE_DEPTH_SHIFT) | - (1 << GBE_FB_SIZE_TILE_WIDTH_SHIFT)); - - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_PIXEL, - (screen->width * screen->height / tile_width) << - GBE_FB_SIZE_PIXEL_HEIGHT_SHIFT); - - } else { - - /* - * Setup the framebuffer in tiled mode. Provide the tile - * colour depth, screen width in whole and partial tiles, - * and the framebuffer height in pixels. - */ - - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_TILE, - ((screen->depth >> 4) << GBE_FB_SIZE_TILE_DEPTH_SHIFT) | - ((screen->width / tile_width) << - GBE_FB_SIZE_TILE_WIDTH_SHIFT) | - (((screen->width % tile_width) >> (screen->depth >> 4)) / - 32)); - - bus_space_write_4(gsc->iot, gsc->ioh, GBE_FB_SIZE_PIXEL, - screen->height << GBE_FB_SIZE_PIXEL_HEIGHT_SHIFT); - - } - - /* Set colour mode registers. */ - val = (cmode << GBE_WID_MODE_SHIFT) | GBE_BMODE_BOTH; - for (i = 0; i < (32 * 4); i += 4) - bus_space_write_4(gsc->iot, gsc->ioh, GBE_MODE + i, val); - - /* - * Initialise colourmap if required. - */ - if (screen->depth == 8) { - for (i = 0; i < 16; i++) { - colour = (u_char *)&rasops_cmap[i * 3]; - screen->cmap.cm_red[i] = colour[0]; - screen->cmap.cm_green[i] = colour[1]; - screen->cmap.cm_blue[i] = colour[2]; - } - for (i = 240; i < 256; i++) { - colour = (u_char *)&rasops_cmap[i * 3]; - screen->cmap.cm_red[i] = colour[0]; - screen->cmap.cm_green[i] = colour[1]; - screen->cmap.cm_blue[i] = colour[2]; - } - } - - /* - * Setup an alpha ramp. - */ - for (i = 0; i < GBE_GMAP_ENTRIES; i++) - bus_space_write_4(gsc->iot, gsc->ioh, - GBE_GMAP + i * sizeof(u_int32_t), - (i << 24) | (i << 16) | (i << 8)); - - /* - * Initialise the rendering engine. - */ - val = screen->mode | BUF_TYPE_TLB_A << BUFMODE_BUFTYPE_SHIFT; - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_BUFMODE_SRC, val); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_BUFMODE_DST, val); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_CLIPMODE, 0); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_COLOUR_MASK, 0xffffffff); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PIXEL_XFER_X_STEP, 1); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PIXEL_XFER_Y_STEP, 1); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_WINOFFSET_DST, 0); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_WINOFFSET_SRC, 0); - - /* - * Load framebuffer tiles into TLB A. Each TLB consists of a 16x16 - * tile array representing 2048x2048 pixels. Each entry in the TLB - * consists of four 16-bit entries which represent bits 17:32 of the - * 64KB tile address. As a result, we can make use of the tilemap - * which already stores tile entries in the same format. - */ - tm = (void *)screen->tm; - for (i = 0, t = 0; i < GBE_TLB_SIZE; i++) { - reg <<= 16; - if (i % 16 < tiles_x) - reg |= (tm[t++] | 0x8000); - if (i % 4 == 3) - bus_space_write_8(gsc->iot, gsc->re_ioh, - RE_TLB_A + (i >> 2) * 8, reg); - } - - /* Load single tile into TLB B for rasops. */ - bus_space_write_8(gsc->iot, gsc->re_ioh, - RE_TLB_B, (screen->ro_phys >> 16 | 0x8000) << 48); -} - -void -gbe_wait_re_idle(struct gbe_softc *gsc) -{ - int i; - - /* Wait until rendering engine is idle. */ - for (i = 0; i < 100000; i++) { - if (bus_space_read_4(gsc->iot, gsc->re_ioh, RE_PP_STATUS) & - RE_PP_STATUS_IDLE) - break; - delay(1); - } - if (i == 100000) - printf("%s: rendering engine did not become idle!\n", - gsc->sc_dev.dv_xname); -} - -/* - * Interfaces for wscons. - */ - -int -gbe_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) -{ - struct gbe_screen *screen = (struct gbe_screen *)v; - int rc, mode; - - switch (cmd) { - case WSDISPLAYIO_GTYPE: - *(u_int *)data = WSDISPLAY_TYPE_GBE; - break; - - case WSDISPLAYIO_GINFO: - { - struct wsdisplay_fbinfo *fb = (struct wsdisplay_fbinfo *)data; - - fb->height = screen->height; - fb->width = screen->width; - fb->depth = screen->depth; - fb->cmsize = screen->depth == 8 ? 256 : 0; - } - break; - - case WSDISPLAYIO_LINEBYTES: - *(u_int *)data = screen->linebytes; - break; - - case WSDISPLAYIO_GETCMAP: - if (screen->depth == 8) { - struct wsdisplay_cmap *cm = - (struct wsdisplay_cmap *)data; - - rc = gbe_getcmap(&screen->cmap, cm); - if (rc != 0) - return (rc); - } - break; - - case WSDISPLAYIO_PUTCMAP: - if (screen->depth == 8) { - struct wsdisplay_cmap *cm = - (struct wsdisplay_cmap *)data; - - rc = gbe_putcmap(&screen->cmap, cm); - if (rc != 0) - return (rc); - gbe_loadcmap(screen, cm->index, cm->index + cm->count); - } - break; - - case WSDISPLAYIO_GMODE: - *(u_int *)data = screen->mode; - break; - - case WSDISPLAYIO_SMODE: - mode = *(u_int *)data; - if (mode == WSDISPLAYIO_MODE_EMUL || - mode == WSDISPLAYIO_MODE_MAPPED || - mode == WSDISPLAYIO_MODE_DUMBFB) { - - screen->mode = mode; - - gbe_disable((struct gbe_softc *)screen->sc); - gbe_setup((struct gbe_softc *)screen->sc); - gbe_enable((struct gbe_softc *)screen->sc); - - /* Clear framebuffer if entering emulated mode. */ - if (screen->mode == WSDISPLAYIO_MODE_EMUL) - gbe_fillrect((struct gbe_softc *)screen->sc, - 0, 0, screen->width, screen->height, 0); - } - break; - - case WSDISPLAYIO_GVIDEO: - case WSDISPLAYIO_SVIDEO: - /* Handled by the upper layer. */ - break; - - default: - return (-1); - } - - return (0); -} - -paddr_t -gbe_mmap(void *v, off_t offset, int protection) -{ - struct gbe_screen *screen = (void *)v; - paddr_t pa; - - if (offset >= 0 && offset < screen->fb_size) - pa = screen->fb_phys + offset; - else - pa = -1; - - return (pa); -} - -int -gbe_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, - int *curxp, int *curyp, uint32_t *attrp) -{ - struct gbe_screen *screen = (struct gbe_screen *)v; - struct gbe_softc *gsc = (struct gbe_softc *)screen->sc; - - /* We do not allow multiple consoles at the moment. */ - if (gsc->screens > 0) - return (ENOMEM); - - gsc->screens++; - - /* Return rasops_info via cookie. */ - *cookiep = &screen->ri; - - /* Move cursor to top left of screen. */ - *curxp = 0; - *curyp = 0; - - /* Correct screen attributes. */ - screen->ri.ri_ops.pack_attr(&screen->ri, 0, 0, 0, attrp); - - return (0); -} - -void -gbe_free_screen(void *v, void *cookie) -{ - /* We do not allow multiple consoles at the moment. */ -} - -int -gbe_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int), - void *cbarg) -{ - /* We do not allow multiple consoles at the moment. */ - return (0); -} - -int -gbe_load_font(void *v, void *emulcookie, struct wsdisplay_font *font) -{ - struct gbe_screen *screen = (struct gbe_screen *)v; - - return rasops_load_font(&screen->ri, emulcookie, font); -} - -int -gbe_list_font(void *v, struct wsdisplay_font *font) -{ - struct gbe_screen *screen = (struct gbe_screen *)v; - - return rasops_list_font(&screen->ri, font); -} - -/* - * Colour map handling for indexed modes. - */ - -void -gbe_setcolour(struct gbe_softc *gsc, u_int index, u_int8_t r, u_int8_t g, - u_int8_t b) -{ - int i; - - /* Wait until the colourmap FIFO has free space. */ - for (i = 0; i < 10000; i++) { - if (bus_space_read_4(gsc->iot, gsc->ioh, GBE_CMAP_FIFO) - < GBE_CMAP_FIFO_ENTRIES) - break; - delay(10); - } - if (i == 10000) - printf("colourmap FIFO has no free space!\n"); - - bus_space_write_4(gsc->iot, gsc->ioh, - GBE_CMAP + index * sizeof(u_int32_t), - ((u_int)r << 24) | ((u_int)g << 16) | ((u_int)b << 8)); -} - -int -gbe_getcmap(struct gbe_cmap *cm, struct wsdisplay_cmap *rcm) -{ - u_int index = rcm->index, count = rcm->count; - int rc; - - if (index >= 256 || count > 256 - index) - return (EINVAL); - - if ((rc = copyout(&cm->cm_red[index], rcm->red, count)) != 0) - return (rc); - if ((rc = copyout(&cm->cm_green[index], rcm->green, count)) != 0) - return (rc); - if ((rc = copyout(&cm->cm_blue[index], rcm->blue, count)) != 0) - return (rc); - - return (0); -} - -int -gbe_putcmap(struct gbe_cmap *cm, struct wsdisplay_cmap *rcm) -{ - u_int index = rcm->index, count = rcm->count; - int rc; - - if (index >= 256 || count > 256 - index) - return (EINVAL); - - if ((rc = copyin(rcm->red, &cm->cm_red[index], count)) != 0) - return (rc); - if ((rc = copyin(rcm->green, &cm->cm_green[index], count)) != 0) - return (rc); - if ((rc = copyin(rcm->blue, &cm->cm_blue[index], count)) != 0) - return (rc); - - return (0); -} - -void -gbe_loadcmap(struct gbe_screen *screen, u_int start, u_int end) -{ - struct gbe_softc *gsc = (void *)screen->sc; - struct gbe_cmap *cm = &screen->cmap; - - for (; start <= end; start++) - gbe_setcolour(gsc, start, - cm->cm_red[start], cm->cm_green[start], cm->cm_blue[start]); -} - -/* - * Hardware accelerated functions for rasops. - */ - -void -gbe_rop(struct gbe_softc *gsc, int x, int y, int w, int h, int op) -{ - gbe_wait_re_idle(gsc); - - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PRIMITIVE, - PRIMITIVE_RECTANGLE | PRIMITIVE_LRTB); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_DRAWMODE, - DRAWMODE_BITMASK | DRAWMODE_BYTEMASK | DRAWMODE_PIXEL_XFER | - DRAWMODE_LOGIC_OP); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_LOGIC_OP, op); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PIXEL_XFER_SRC, - (x << 16) | (y & 0xffff)); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_0, - (x << 16) | (y & 0xffff)); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_1 | RE_START, - ((x + w - 1) << 16) | ((y + h - 1) & 0xffff)); -} - -void -gbe_copyrect(struct gbe_softc *gsc, int src, int sx, int sy, int dx, int dy, - int w, int h) -{ - int direction, x0, y0, x1, y1; - - if (sx >= dx && sy >= dy) { - direction = PRIMITIVE_LRTB; - x0 = dx; - y0 = dy; - x1 = dx + w - 1; - y1 = dy + h - 1; - } else if (sx >= dx && sy < dy) { - direction = PRIMITIVE_LRBT; - sy = sy + h - 1; - x0 = dx; - y0 = dy + h - 1; - x1 = dx + w - 1; - y1 = dy; - } else if (sx < dx && sy >= dy) { - direction = PRIMITIVE_RLTB; - sx = sx + w - 1; - x0 = dx + w - 1; - y0 = dy; - x1 = dx; - y1 = dy + h - 1; - } else if (sx < dx && sy < dy) { - direction = PRIMITIVE_RLBT; - sy = sy + h - 1; - sx = sx + w - 1; - x0 = dx + w - 1; - y0 = dy + h - 1; - x1 = dx; - y1 = dy; - } - - gbe_wait_re_idle(gsc); - - if (src != BUF_TYPE_TLB_A) - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_BUFMODE_SRC, - gsc->curscr->bufmode | (src << BUFMODE_BUFTYPE_SHIFT)); - - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PRIMITIVE, - PRIMITIVE_RECTANGLE | direction); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_DRAWMODE, - DRAWMODE_BITMASK | DRAWMODE_BYTEMASK | DRAWMODE_PIXEL_XFER); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PIXEL_XFER_SRC, - (sx << 16) | (sy & 0xffff)); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_0, - (x0 << 16) | (y0 & 0xffff)); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_1 | RE_START, - (x1 << 16) | (y1 & 0xffff)); - - if (src != BUF_TYPE_TLB_A) { - gbe_wait_re_idle(gsc); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_BUFMODE_SRC, - gsc->curscr->bufmode | - (BUF_TYPE_TLB_A << BUFMODE_BUFTYPE_SHIFT)); - } -} - -void -gbe_fillrect(struct gbe_softc *gsc, int x, int y, int w, int h, int bg) -{ - - gbe_wait_re_idle(gsc); - - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_PRIMITIVE, - PRIMITIVE_RECTANGLE | PRIMITIVE_LRTB); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_DRAWMODE, - DRAWMODE_BITMASK | DRAWMODE_BYTEMASK); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_SHADE_FG_COLOUR, bg); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_0, - (x << 16) | (y & 0xffff)); - bus_space_write_4(gsc->iot, gsc->re_ioh, RE_PP_VERTEX_X_1 | RE_START, - ((x + w - 1) << 16) | ((y + h - 1) & 0xffff)); -} - -int -gbe_do_cursor(struct rasops_info *ri) -{ - struct gbe_softc *sc = ri->ri_hw; - int y, x, w, h; - - w = ri->ri_font->fontwidth; - h = ri->ri_font->fontheight; - x = ri->ri_xorigin + ri->ri_ccol * w; - y = ri->ri_yorigin + ri->ri_crow * h; - - gbe_rop(sc, x, y, w, h, OPENGL_LOGIC_OP_COPY_INVERTED); - - return 0; -} - -int -gbe_putchar(void *cookie, int row, int col, u_int uc, uint32_t attr) -{ - struct rasops_info *ri = cookie; - struct gbe_softc *gsc = ri->ri_hw; - struct gbe_screen *screen = gsc->curscr; - struct rasops_info *ri_tile = &screen->ri_tile; - int x, y, w, h; - - w = ri->ri_font->fontwidth; - h = ri->ri_font->fontheight; - x = ri->ri_xorigin + col * w; - y = ri->ri_yorigin + row * h; - - ri_tile->ri_ops.putchar(ri_tile, 0, screen->ro_curpos, uc, attr); - - gbe_copyrect(gsc, BUF_TYPE_TLB_B, screen->ro_curpos * w, 0, x, y, w, h); - - screen->ro_curpos++; - if ((screen->ro_curpos + 1) * w > screen->ri_tile.ri_width) - screen->ro_curpos = 0; - - return 0; -} - -int -gbe_copycols(void *cookie, int row, int src, int dst, int num) -{ - struct rasops_info *ri = cookie; - struct gbe_softc *sc = ri->ri_hw; - - num *= ri->ri_font->fontwidth; - src *= ri->ri_font->fontwidth; - dst *= ri->ri_font->fontwidth; - row *= ri->ri_font->fontheight; - - gbe_copyrect(sc, BUF_TYPE_TLB_A, ri->ri_xorigin + src, - ri->ri_yorigin + row, ri->ri_xorigin + dst, ri->ri_yorigin + row, - num, ri->ri_font->fontheight); - - return 0; -} - -int -gbe_erasecols(void *cookie, int row, int col, int num, uint32_t attr) -{ - struct rasops_info *ri = cookie; - struct gbe_softc *sc = ri->ri_hw; - int bg, fg; - - ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); - - row *= ri->ri_font->fontheight; - col *= ri->ri_font->fontwidth; - num *= ri->ri_font->fontwidth; - - gbe_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, - num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); - - return 0; -} - -int -gbe_copyrows(void *cookie, int src, int dst, int num) -{ - struct rasops_info *ri = cookie; - struct gbe_softc *sc = ri->ri_hw; - - num *= ri->ri_font->fontheight; - src *= ri->ri_font->fontheight; - dst *= ri->ri_font->fontheight; - - gbe_copyrect(sc, BUF_TYPE_TLB_A, ri->ri_xorigin, ri->ri_yorigin + src, - ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num); - - return 0; -} - -int -gbe_eraserows(void *cookie, int row, int num, uint32_t attr) -{ - struct rasops_info *ri = cookie; - struct gbe_softc *sc = ri->ri_hw; - int x, y, w, bg, fg; - - ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); - - if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { - num = ri->ri_height; - x = y = 0; - w = ri->ri_width; - } else { - num *= ri->ri_font->fontheight; - x = ri->ri_xorigin; - y = ri->ri_yorigin + row * ri->ri_font->fontheight; - w = ri->ri_emuwidth; - } - - gbe_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); - - return 0; -} - -/* - * Console functions for early display. - */ - -int -gbe_cnprobe(bus_space_tag_t iot, bus_addr_t addr) -{ - bus_space_handle_t ioh; - int val, width, height; - - /* Setup bus space mapping. */ - ioh = PHYS_TO_XKPHYS(addr, CCA_NC); - - /* Determine resolution configured by firmware. */ - val = bus_space_read_4(iot, ioh, GBE_VT_HCMAP); - width = (val >> GBE_VT_HCMAP_ON_SHIFT) & 0xfff; - val = bus_space_read_4(iot, ioh, GBE_VT_VCMAP); - height = (val >> GBE_VT_VCMAP_ON_SHIFT) & 0xfff; - - /* Ensure that the firmware has setup the device. */ - if (width != 0 && height != 0) - return (1); - else - return (0); -} - -int -gbe_cnattach(bus_space_tag_t iot, bus_addr_t addr) -{ - struct gbe_softc *gsc; - uint32_t val; - paddr_t pa; - vaddr_t va; - uint32_t attr; - - /* - * Setup GBE for use as early console. - */ - va = pmap_steal_memory(sizeof(struct gbe_softc), NULL, NULL); - gsc = (struct gbe_softc *)va; - gsc->curscr = &gbe_consdata; - gbe_consdata.sc = (struct device *)gsc; - - /* Setup bus space mapping. */ - gsc->iot = iot; - gsc->ioh = PHYS_TO_XKPHYS(addr, CCA_NC); - gsc->re_ioh = PHYS_TO_XKPHYS(RE_BASE, CCA_NC); - - /* Determine GBE revision. */ - gsc->rev = bus_space_read_4(gsc->iot, gsc->ioh, GBE_CTRL_STAT) & 0xf; - - /* Determine resolution configured by firmware. */ - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_HCMAP); - gbe_consdata.width = (val >> GBE_VT_HCMAP_ON_SHIFT) & 0xfff; - val = bus_space_read_4(gsc->iot, gsc->ioh, GBE_VT_VCMAP); - gbe_consdata.height = (val >> GBE_VT_VCMAP_ON_SHIFT) & 0xfff; - - /* Ensure that the firmware has setup the device. */ - if (gbe_consdata.width == 0 || gbe_consdata.height == 0) - return (ENXIO); - - /* Setup screen defaults. */ - gbe_consdata.fb_size = GBE_FB_SIZE; - gbe_consdata.tm_size = GBE_TLB_SIZE * sizeof(uint16_t); - gbe_consdata.depth = 8; - gbe_consdata.linebytes = gbe_consdata.width * gbe_consdata.depth / 8; - - /* - * Steal memory for tilemap - 64KB aligned and coherent. - */ - va = pmap_steal_memory(gbe_consdata.tm_size + 65536, NULL, NULL); - pmap_extract(pmap_kernel(), va, &pa); - gbe_consdata.tm_phys = ((pa >> 16) + 1) << 16; - gbe_consdata.tm = (caddr_t)PHYS_TO_XKPHYS(gbe_consdata.tm_phys, CCA_NC); - - /* - * Steal memory for framebuffer - 64KB aligned and coherent. - */ - va = pmap_steal_memory(gbe_consdata.fb_size + 65536, NULL, NULL); - pmap_extract(pmap_kernel(), va, &pa); - gbe_consdata.fb_phys = ((pa >> 16) + 1) << 16; - gbe_consdata.fb = (caddr_t)PHYS_TO_XKPHYS(gbe_consdata.fb_phys, CCA_NC); - - /* - * Steal memory for rasops tile - 64KB aligned and coherent. - */ - va = pmap_steal_memory(GBE_TILE_SIZE + 65536, NULL, NULL); - pmap_extract(pmap_kernel(), va, &pa); - gbe_consdata.ro_phys = ((pa >> 16) + 1) << 16; - gbe_consdata.ro = (caddr_t)PHYS_TO_XKPHYS(gbe_consdata.ro_phys, CCA_NC); - - /* - * Setup GBE hardware. - */ - gbe_init_screen(&gbe_consdata); - gbe_disable(gsc); - gbe_setup(gsc); - gbe_enable(gsc); - - /* Load colourmap if required. */ - if (gbe_consdata.depth == 8) - gbe_loadcmap(&gbe_consdata, 0, 255); - - /* Clear framebuffer. */ - gbe_fillrect(gsc, 0, 0, gbe_consdata.width, gbe_consdata.height, 0); - - /* - * Attach wsdisplay. - */ - gbe_consdata.ri.ri_ops.pack_attr(&gbe_consdata.ri, 0, 0, 0, &attr); - wsdisplay_cnattach(&gbe_stdscreen, &gbe_consdata.ri, 0, 0, attr); - gbe_console = 1; - - return (0); -} diff --git a/sys/arch/sgi/dev/gbereg.h b/sys/arch/sgi/dev/gbereg.h deleted file mode 100644 index c20007fa3c5..00000000000 --- a/sys/arch/sgi/dev/gbereg.h +++ /dev/null @@ -1,206 +0,0 @@ -/* $OpenBSD: gbereg.h,v 1.6 2012/05/29 17:37:09 mikeb Exp $ */ - -/* - * Copyright (c) 2007, 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. - */ - -/* - * GBE Framebuffer for SGI O2. - */ - -#define GBE_BASE 0x16000000 -#define GBE_REG_SIZE 0x100000 -#define GBE_TLB_SIZE 128 - -#define GBE_TILE_SHIFT 16 -#define GBE_TILE_SIZE (1 << GBE_TILE_SHIFT) - -#define GBE_TILE_WIDTH 512 /* Width of tile in bytes. */ -#define GBE_TILE_WIDTH_SHIFT 9 -#define GBE_TILE_HEIGHT 128 /* Height of tile in bytes. */ -#define GBE_TILE_HEIGHT_SHIFT 7 - -/* - * GBE Registers. - */ - -#define GBE_CTRL_STAT 0x00000000 /* General control/status */ -#define GBE_CURSOR_ON 0x00000001 -#define GBE_DOTCLOCK 0x00000004 /* Dotclock */ -#define GBE_DOTCLOCK_RUN 0x00100000 /* Enable dotclock */ -#define GBE_VT_XY 0x00010000 /* Current dot coordinates */ -#define GBE_VT_XY_X_SHIFT 0 -#define GBE_VT_XY_X_MASK 0x00000fff -#define GBE_VT_XY_Y_SHIFT 12 -#define GBE_VT_XY_Y_MASK 0x00fff000 -#define GBE_VT_XY_FREEZE 0x80000000 /* Freeze pixel counter */ -#define GBE_VT_MAXXY 0x00010004 /* */ -#define GBE_VT_VSYNC 0x00010008 /* Vertical sync on/off */ -#define GBE_VT_HSYNC 0x0001000c /* Horizontal sync on/off */ -#define GBE_VT_VBLANK 0x00010010 /* Vertical blanking */ -#define GBE_VT_HBLANK 0x00010014 /* Horizontal blanking */ -#define GBE_VT_FLAGS 0x00010018 /* Video timing flags */ -#define GBE_VT_SYNC_LOW 0x00000020 /* Sync on green */ -#define GBE_VT_HPIX 0x00010034 /* Horizontal pixel on/off */ -#define GBE_VT_VPIX 0x00010038 /* Vertical pixel on/off */ -#define GBE_VT_VPIX_OFF_MASK 0x00000fff -#define GBE_VT_VPIX_OFF_SHIFT 0 -#define GBE_VT_VPIX_ON_MASK 0x00fff000 -#define GBE_VT_VPIX_ON_SHIFT 12 -#define GBE_VT_HCMAP 0x0001003c /* Horizontal cmap write */ -#define GBE_VT_HCMAP_ON_SHIFT 12 -#define GBE_VT_VCMAP 0x00010040 /* Vertical cmap write */ -#define GBE_VT_VCMAP_ON_SHIFT 12 -#define GBE_VT_DIDSTARTXY 0x00010044 /* DID reset at x/y */ -#define GBE_VT_CRSSTARTXY 0x00010048 /* CRS reset at x/y */ -#define GBE_VT_VCSTARTXY 0x0001004c /* VC reset at x/y */ -#define GBE_OVERLAY_TILE 0x00020000 /* Overlay plane - tile width */ -#define GBE_OVERLAY_HW_CTRL 0x00020004 /* Overlay plane - h/w control */ -#define GBE_OVERLAY_CTRL 0x00020008 /* Overlay plane - control */ -#define GBE_OVERLAY_CTRL_DMA_ENABLE 0x00000001 -#define GBE_FB_SIZE_TILE 0x00030000 /* Framebuffer - tile size */ -#define GBE_FB_SIZE_TILE_WIDTH_SHIFT 5 -#define GBE_FB_SIZE_TILE_DEPTH_SHIFT 13 -#define GBE_FB_SIZE_TILE_FIFO_RESET_SHIFT 15 -#define GBE_FB_SIZE_PIXEL 0x00030004 /* Framebuffer - pixel size */ -#define GBE_FB_SIZE_PIXEL_HEIGHT_SHIFT 16 -#define GBE_FB_HW_CTRL 0x00030008 /* Framebuffer - hardware control */ -#define GBE_FB_CTRL 0x0003000c /* Framebuffer - control */ -#define GBE_FB_CTRL_TILE_PTR_SHIFT 9 -#define GBE_FB_CTRL_DMA_ENABLE 0x00000001 -#define GBE_DID_HW_CTRL 0x00040000 /* DID hardware control */ -#define GBE_DID_CTRL 0x00040004 /* DID control */ -#define GBE_MODE 0x00048000 /* Colour mode */ -#define GBE_WID_MODE_SHIFT 2 -#define GBE_CMAP 0x050000 /* Colourmap */ -#define GBE_CMAP_ENTRIES 6144 -#define GBE_CMAP_FIFO 0x058000 /* Colourmap FIFO status */ -#define GBE_CMAP_FIFO_ENTRIES 63 -#define GBE_GMAP 0x060000 /* Gammamap */ -#define GBE_GMAP_ENTRIES 256 -#define GBE_CURSOR_POS 0x00070000 /* Cursor position */ -#define GBE_CURSOR_CTRL 0x00070004 /* Cursor control */ - -/* - * GBE Constants. - */ - -#define GBE_FB_DEPTH_8 0 -#define GBE_FB_DEPTH_16 1 -#define GBE_FB_DEPTH_32 2 - -#define GBE_CMODE_I8 0 /* 8 bit indexed */ -#define GBE_CMODE_I12 1 /* 12 bit indexed */ -#define GBE_CMODE_RG3B2 2 /* 3:3:2 direct */ -#define GBE_CMODE_RGB4 3 /* 4:4:4 direct */ -#define GBE_CMODE_ARGB5 4 /* 1:5:5:5 direct */ -#define GBE_CMODE_RGB8 5 /* 8:8:8 direct */ -#define GBE_CMODE_RGBA5 6 /* 5:5:5:5 direct */ -#define GBE_CMODE_RGB10 7 /* 10:10:10 direct */ - -#define GBE_BMODE_BOTH 3 - -/* - * Rendering Engine Registers. - */ - -#define RE_BASE 0x15000000 -#define RE_REG_SIZE 0x5000 -#define RE_START 0x00000800 /* Start rendering operation. */ - -/* TLB Registers. */ -#define RE_TLB_A 0x00001000 /* 256 16-bit tile entries. */ -#define RE_TLB_B 0x00001200 -#define RE_TLB_C 0x00001400 -#define RE_TLB_TEX 0x00001600 -#define RE_TLB_CLIP_ID 0x000016e0 -#define RE_TLB_LINEAR_A 0x00001700 -#define RE_TLB_LINEAR_B 0x00001780 - -/* Pixel Pipeline Registers. */ -#define RE_PP_BUFMODE_SRC 0x00002000 -#define RE_PP_BUFMODE_DST 0x00002008 -#define RE_PP_CLIPMODE 0x00002010 -#define RE_PP_DRAWMODE 0x00002018 -#define DRAWMODE_STENCIL 0x1 << 0 -#define DRAWMODE_DEPTH_MASK 0x1 << 1 -#define DRAWMODE_DEPTH_TEST 0x1 << 2 -#define DRAWMODE_BYTEMASK 0xf << 3 -#define DRAWMODE_BITMASK 0x1 << 7 -#define DRAWMODE_DITHER 0x1 << 8 -#define DRAWMODE_LOGIC_OP 0x1 << 9 -#define DRAWMODE_ALPHA_BLEND 0x1 << 10 -#define DRAWMODE_PIXEL_XFER 0x1 << 21 -#define RE_PP_WINOFFSET_SRC 0x00002050 -#define RE_PP_WINOFFSET_DST 0x00002058 -#define RE_PP_PRIMITIVE 0x00002060 /* Drawing primitive. */ -#define PRIMITIVE_POINT 0x0 << 24 -#define PRIMITIVE_LINE 0x1 << 24 -#define PRIMITIVE_TRIANGLE 0x2 << 24 -#define PRIMITIVE_RECTANGLE 0x3 << 24 -#define PRIMITIVE_LRBT 0x0 << 16 -#define PRIMITIVE_RLBT 0x1 << 16 -#define PRIMITIVE_LRTB 0x2 << 16 -#define PRIMITIVE_RLTB 0x3 << 16 -#define RE_PP_VERTEX_X_0 0x00002070 /* (x0,y0) vertex. */ -#define RE_PP_VERTEX_X_1 0x00002074 /* (x1,y1) vertex. */ -#define RE_PP_VERTEX_X_2 0x00002078 /* (x2,y2) vertex. */ -#define RE_PP_PIXEL_XFER_SRC 0x000020a0 /* Pixel transfer source. */ -#define RE_PP_PIXEL_XFER_X_STEP 0x000020a8 -#define RE_PP_PIXEL_XFER_Y_STEP 0x000020ac -#define RE_PP_STIPPLE_MODE 0x000020c0 -#define RE_PP_STIPPLE_PATTERN 0x000020c4 -#define RE_PP_SHADE_FG_COLOUR 0x000020d0 -#define RE_PP_SHADE_BG_COLOUR 0x000020d8 -#define RE_PP_LOGIC_OP 0x000021b0 /* Logic operation. */ -#define RE_PP_COLOUR_MASK 0x000021b8 /* Colour buffer plane mask. */ -#define COLOUR_MASK_NONE 0xffffffff -#define RE_PP_NULL 0x000021f0 -#define RE_PP_FLUSH 0x000021f8 - -#define BUFMODE_PIXDEPTH_SHIFT 2 /* Pixel colour depth. */ -#define BUFMODE_PIXTYPE_SHIFT 4 /* Pixel format. */ -#define BUFMODE_BUFDEPTH_SHIFT 8 /* Buffer colour depth. */ -#define BUFMODE_BUFTYPE_SHIFT 10 /* Source or destination. */ - -/* Status Registers. */ -#define RE_PP_STATUS 0x00004000 -#define RE_PP_STATUS_IDLE 0x10000000 -#define RE_PP_STATUS_READY 0x02000000 - -/* - * Rendering Engine Constants. - */ - -#define COLOUR_DEPTH_8 0x0 -#define COLOUR_DEPTH_16 0x1 -#define COLOUR_DEPTH_32 0x2 - -#define PIXEL_TYPE_CI 0x0 -#define PIXEL_TYPE_RGB 0x1 -#define PIXEL_TYPE_RGBA 0x2 -#define PIXEL_TYPE_ABGR 0x3 - -#define BUF_TYPE_TLB_A 0x0 -#define BUF_TYPE_TLB_B 0x1 -#define BUF_TYPE_TLB_C 0x2 -#define BUF_TYPE_LINEAR_A 0x4 -#define BUF_TYPE_LINEAR_B 0x5 - -/* - * Console functions. - */ -int gbe_cnprobe(bus_space_tag_t, bus_addr_t addr); -int gbe_cnattach(bus_space_tag_t, bus_addr_t addr); diff --git a/sys/arch/sgi/dev/gl.h b/sys/arch/sgi/dev/gl.h deleted file mode 100644 index 9cbf88cc12b..00000000000 --- a/sys/arch/sgi/dev/gl.h +++ /dev/null @@ -1,39 +0,0 @@ -/* $OpenBSD: gl.h,v 1.1 2012/04/16 22:17:13 miod Exp $ */ -/* - * Copyright (c) 2009, 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. - */ - -/* - * OpenGL defines - */ - -/* Logic Operations. */ -#define OPENGL_LOGIC_OP_CLEAR 0 -#define OPENGL_LOGIC_OP_AND 1 -#define OPENGL_LOGIC_OP_AND_REVERSE 2 -#define OPENGL_LOGIC_OP_COPY 3 -#define OPENGL_LOGIC_OP_AND_INVERTED 4 -#define OPENGL_LOGIC_OP_NOOP 5 -#define OPENGL_LOGIC_OP_XOR 6 -#define OPENGL_LOGIC_OP_OR 7 -#define OPENGL_LOGIC_OP_NOR 8 -#define OPENGL_LOGIC_OP_EQUIV 9 -#define OPENGL_LOGIC_OP_INVERT 10 -#define OPENGL_LOGIC_OP_OR_REVERSE 11 -#define OPENGL_LOGIC_OP_COPY_INVERTED 12 -#define OPENGL_LOGIC_OP_OR_INVERTED 13 -#define OPENGL_LOGIC_OP_NAND 14 -#define OPENGL_LOGIC_OP_SET 15 - diff --git a/sys/arch/sgi/dev/if_iec.c b/sys/arch/sgi/dev/if_iec.c deleted file mode 100644 index 44c58f42de8..00000000000 --- a/sys/arch/sgi/dev/if_iec.c +++ /dev/null @@ -1,1401 +0,0 @@ -/* $OpenBSD: if_iec.c,v 1.27 2020/07/10 13:26:36 patrick Exp $ */ - -/* - * Copyright (c) 2009 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. - */ -/* - * Heavily based upon if_mec.c with the following license terms: - * - * OpenBSD: if_mec.c,v 1.22 2009/10/26 18:00:06 miod Exp - * - * Copyright (c) 2004 Izumi Tsutsui. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Copyright (c) 2003 Christopher SEKIYA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the - * NetBSD Project. See http://www.NetBSD.org/ for - * information about NetBSD. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * IOC3 Ethernet driver - */ - -#include "bpfilter.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/timeout.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/errno.h> - -#include <net/if.h> -#include <net/if_media.h> - -#if NBPFILTER > 0 -#include <net/bpf.h> -#endif - -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include <machine/autoconf.h> -#include <machine/bus.h> -#include <machine/intr.h> - -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> - -#include <sgi/dev/if_iecreg.h> -#include <sgi/dev/owmacvar.h> -#include <sgi/pci/iocreg.h> -#include <sgi/pci/iocvar.h> - -#ifdef IEC_DEBUG -#define IEC_DEBUG_RESET 0x01 -#define IEC_DEBUG_START 0x02 -#define IEC_DEBUG_STOP 0x04 -#define IEC_DEBUG_INTR 0x08 -#define IEC_DEBUG_RXINTR 0x10 -#define IEC_DEBUG_TXINTR 0x20 -#define IEC_DEBUG_MII 0x40 -uint32_t iec_debug = 0xffffffff; -#define DPRINTF(x, y) if (iec_debug & (x)) printf y -#else -#define DPRINTF(x, y) /* nothing */ -#endif - -/* - * Transmit descriptor list size. - */ -#define IEC_NTXDESC IEC_NTXDESC_MAX -#define IEC_NEXTTX(x) (((x) + 1) % IEC_NTXDESC_MAX) - -/* - * Software state for TX. - */ -struct iec_txsoft { - struct mbuf *txs_mbuf; /* Head of our mbuf chain. */ - bus_dmamap_t txs_dmamap; /* Our DMA map. */ - uint32_t txs_flags; -}; - -/* - * Receive buffer management. - * - * The RX buffers chip register points to a contiguous array of - * 512 8-bit pointers to the RX buffers themselves. - */ - -/* - * Receive descriptor list sizes (these depend on the size of the SSRAM). - */ -#define IEC_NRXDESC_SMALL 64 -#define IEC_NRXDESC_LARGE 128 - -/* - * In addition to the receive descriptor themselves, we'll need an array - * of 512 RX descriptor pointers (regardless of how many real descriptors - * we use), aligned on a 4KB boundary. - */ - -/* - * Control structures for DMA ops. - */ -struct iec_control_data { - /* - * TX descriptors and buffers. - */ - struct iec_txdesc icd_txdesc[IEC_NTXDESC_MAX]; - - /* - * RX descriptors and buffers. - */ - struct iec_rxdesc icd_rxdesc[1]; -}; - -/* - * Alignment restrictions (found by trial and error, might be slightly - * pessimistic). - * - base address of rx desc pointer array should be aligned on a - * 16KB boundary. - * - base address of rx and tx desc array should be aligned on - * 16KB boundaries (note layout of struct iec_control_data makes sure - * the rx desc array starts 16KB after the tx desc array). - * - each txdesc should be 128 byte aligned (this is also enforced by - * struct iec_control_data layout). - * - each rxdesc should be aligned on a 4KB boundary (this is enforced by - * struct iec_control_data and struct icd_rxdesc layouts). - */ -#define IEC_DMA_BOUNDARY 0x4000 - -#define IEC_CDOFF(x) offsetof(struct iec_control_data, x) -#define IEC_CDTXOFF(x) IEC_CDOFF(icd_txdesc[(x)]) -#define IEC_CDRXOFF(x) IEC_CDOFF(icd_rxdesc[(x)]) - -/* - * Software state per device. - */ -struct iec_softc { - struct device sc_dev; /* Generic device structures. */ - struct arpcom sc_ac; /* Ethernet common part. */ - - bus_space_tag_t sc_st; /* bus_space tag. */ - bus_space_handle_t sc_sh; /* bus_space handle. */ - bus_dma_tag_t sc_dmat; /* bus_dma tag. */ - - struct mii_data sc_mii; /* MII/media information. */ - int sc_phyaddr; /* MII address. */ - struct timeout sc_tick; /* Tick timeout. */ - - uint64_t *sc_rxarr; /* kva for rx pointers array. */ - bus_dmamap_t sc_rxarrmap; /* bus_dma map for rx pointers array. */ -#define sc_rxptrdma sc_rxarrmap->dm_segs[0].ds_addr - - bus_dmamap_t sc_cddmamap; /* bus_dma map for control data. */ -#define sc_cddma sc_cddmamap->dm_segs[0].ds_addr - - /* Pointer to allocated control data. */ - struct iec_control_data *sc_control_data; -#define sc_txdesc sc_control_data->icd_txdesc -#define sc_rxdesc sc_control_data->icd_rxdesc - - /* Software state for TX descs. */ - struct iec_txsoft sc_txsoft[IEC_NTXDESC]; - - int sc_txpending; /* Number of TX requests pending. */ - int sc_txdirty; /* First dirty TX descriptor. */ - int sc_txlast; /* Last used TX descriptor. */ - - uint32_t sc_rxci; /* Saved RX consumer index. */ - uint32_t sc_rxpi; /* Saved RX producer index. */ - uint32_t sc_nrxdesc; /* Amount of RX descriptors. */ - - uint32_t sc_mcr; /* Current MCR value. */ -}; - -#define IEC_CDTXADDR(sc, x) ((sc)->sc_cddma + IEC_CDTXOFF(x)) -#define IEC_CDRXADDR(sc, x) ((sc)->sc_cddma + IEC_CDRXOFF(x)) - -#define IEC_TXDESCSYNC(sc, x, ops) \ - bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ - IEC_CDTXOFF(x), IEC_TXDESCSIZE, (ops)) -#define IEC_TXCMDSYNC(sc, x, ops) \ - bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ - IEC_CDTXOFF(x), 2 * sizeof(uint32_t), (ops)) - -#define IEC_RXSTATSYNC(sc, x, ops) \ - bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ - IEC_CDRXOFF(x), 2 * sizeof(uint32_t), (ops)) -#define IEC_RXBUFSYNC(sc, x, len, ops) \ - bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ - IEC_CDRXOFF(x) + IEC_RXD_BUFOFFSET, (len), (ops)) - -/* XXX these values should be moved to <net/if_ether.h> ? */ -#define ETHER_PAD_LEN (ETHER_MIN_LEN - ETHER_CRC_LEN) - -struct cfdriver iec_cd = { - NULL, "iec", DV_IFNET -}; - -#define DEVNAME(sc) ((sc)->sc_dev.dv_xname) - -int iec_match(struct device *, void *, void *); -void iec_attach(struct device *, struct device *, void *); - -struct cfattach iec_ca = { - sizeof(struct iec_softc), iec_match, iec_attach -}; - -int iec_mii_readreg(struct device *, int, int); -void iec_mii_writereg(struct device *, int, int, int); -int iec_mii_wait(struct iec_softc *); -void iec_statchg(struct device *); -void iec_mediastatus(struct ifnet *, struct ifmediareq *); -int iec_mediachange(struct ifnet *); - -int iec_alloc_physical(struct iec_softc *, bus_dmamap_t *, - bus_dma_segment_t *, vaddr_t *, bus_addr_t, bus_size_t, - const char *); -struct mbuf * - iec_get(struct iec_softc *, uint8_t *, size_t); -void iec_iff(struct iec_softc *); -int iec_init(struct ifnet * ifp); -int iec_intr(void *arg); -int iec_ioctl(struct ifnet *, u_long, caddr_t); -void iec_reset(struct iec_softc *); -void iec_rxintr(struct iec_softc *, uint32_t); -int iec_ssram_probe(struct iec_softc *); -void iec_start(struct ifnet *); -void iec_stop(struct ifnet *); -void iec_tick(void *); -void iec_txintr(struct iec_softc *, uint32_t); -void iec_watchdog(struct ifnet *); - -int -iec_match(struct device *parent, void *match, void *aux) -{ - /* - * We expect ioc NOT to attach us on if there is no Ethernet - * component. - */ - return 1; -} - -void -iec_attach(struct device *parent, struct device *self, void *aux) -{ - struct iec_softc *sc = (void *)self; - struct ioc_attach_args *iaa = aux; - struct ifnet *ifp = &sc->sc_ac.ac_if; - struct mii_softc *child; - bus_dma_segment_t seg1; - bus_dma_segment_t seg2; - bus_size_t control_size; - int i, rc; - - sc->sc_st = iaa->iaa_memt; - sc->sc_sh = iaa->iaa_memh; - sc->sc_dmat = iaa->iaa_dmat; - - /* - * Try and figure out how much SSRAM is available, and decide - * how many RX buffers to use. - */ - i = iec_ssram_probe(sc); - printf(": %dKB SSRAM", i); - - /* - * Allocate a page for RX descriptor pointers, suitable for use - * by the device. - */ - rc = iec_alloc_physical(sc, &sc->sc_rxarrmap, &seg1, - (vaddr_t *)&sc->sc_rxarr, IEC_DMA_BOUNDARY, - IEC_NRXDESC_MAX * sizeof(uint64_t), "rxdesc pointer array"); - if (rc != 0) - return; - - /* - * Allocate the RX and TX descriptors. - */ - control_size = IEC_NTXDESC_MAX * sizeof(struct iec_txdesc) + - sc->sc_nrxdesc * sizeof(struct iec_rxdesc); - rc = iec_alloc_physical(sc, &sc->sc_cddmamap, &seg2, - (vaddr_t *)&sc->sc_control_data, IEC_DMA_BOUNDARY, - control_size, "rx and tx descriptors"); - if (rc != 0) - goto fail_1; - - /* - * Initialize RX pointer array. - */ - - for (i = 0; i < IEC_NRXDESC_MAX; i++) - sc->sc_rxarr[i] = IEC_CDRXADDR(sc, i & (sc->sc_nrxdesc - 1)); - - /* Create TX buffer DMA maps. */ - for (i = 0; i < IEC_NTXDESC; i++) { - if ((rc = bus_dmamap_create(sc->sc_dmat, - MCLBYTES, 1, MCLBYTES, 0, 0, - &sc->sc_txsoft[i].txs_dmamap)) != 0) { - printf(": unable to create tx DMA map %d, error = %d\n", - i, rc); - goto fail_4; - } - } - - timeout_set(&sc->sc_tick, iec_tick, sc); - - bcopy(iaa->iaa_enaddr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN); - printf(", address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr)); - - /* Reset device. */ - iec_reset(sc); - - /* Done, now attach everything. */ - - sc->sc_mii.mii_ifp = ifp; - sc->sc_mii.mii_readreg = iec_mii_readreg; - sc->sc_mii.mii_writereg = iec_mii_writereg; - sc->sc_mii.mii_statchg = iec_statchg; - - /* Set up PHY properties. */ - ifmedia_init(&sc->sc_mii.mii_media, 0, iec_mediachange, - iec_mediastatus); - mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, - MII_OFFSET_ANY, 0); - - child = LIST_FIRST(&sc->sc_mii.mii_phys); - if (child == NULL) { - /* No PHY attached. */ - ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL, - 0, NULL); - ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL); - } else { - ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO); - sc->sc_phyaddr = child->mii_phy; - } - - bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); - ifp->if_softc = sc; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = iec_ioctl; - ifp->if_start = iec_start; - ifp->if_watchdog = iec_watchdog; - - if_attach(ifp); - ifq_set_maxlen(&ifp->if_snd, IEC_NTXDESC - 1); - ether_ifattach(ifp); - - /* Establish interrupt handler. */ - ioc_intr_establish(parent, iaa->iaa_dev, IPL_NET, - iec_intr, sc, sc->sc_dev.dv_xname); - - return; - - /* - * Free any resources we've allocated during the failed attach - * attempt. Do this in reverse order and fall through. - */ -fail_4: - for (i = 0; i < IEC_NTXDESC; i++) { - if (sc->sc_txsoft[i].txs_dmamap != NULL) - bus_dmamap_destroy(sc->sc_dmat, - sc->sc_txsoft[i].txs_dmamap); - } - - bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); - bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); - bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data, - control_size); - bus_dmamem_free(sc->sc_dmat, &seg2, 1); -fail_1: - bus_dmamap_unload(sc->sc_dmat, sc->sc_rxarrmap); - bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxarrmap); - bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_rxarr, - IEC_NRXDESC_MAX * sizeof(uint64_t)); - bus_dmamem_free(sc->sc_dmat, &seg1, 1); -} - -/* - * Allocate contiguous physical memory. - */ -int -iec_alloc_physical(struct iec_softc *sc, bus_dmamap_t *dmamap, - bus_dma_segment_t *dmaseg, vaddr_t *va, bus_addr_t alignment, - bus_size_t len, const char *what) -{ - int nseg; - int rc; - - rc = bus_dmamem_alloc(sc->sc_dmat, len, alignment, 0, dmaseg, 1, &nseg, - BUS_DMA_NOWAIT); - if (rc != 0) { - printf("%s: unable to allocate %s memory: error %d\n", - DEVNAME(sc), what, rc); - goto fail1; - } - - rc = bus_dmamem_map(sc->sc_dmat, dmaseg, nseg, len, - (caddr_t *)va, BUS_DMA_NOWAIT | BUS_DMA_COHERENT); - if (rc != 0) { - printf("%s: unable to map %s memory: error %d\n", - DEVNAME(sc), what, rc); - goto fail2; - } - - rc = bus_dmamap_create(sc->sc_dmat, len, 1, len, 0, BUS_DMA_NOWAIT, - dmamap); - if (rc != 0) { - printf("%s: unable to create %s dma map: error %d\n", - DEVNAME(sc), what, rc); - goto fail3; - } - - rc = bus_dmamap_load(sc->sc_dmat, *dmamap, (void *)*va, len, NULL, - BUS_DMA_NOWAIT); - if (rc != 0) { - printf("%s: unable to load %s dma map: error %d\n", - DEVNAME(sc), what, rc); - goto fail4; - } - - memset((caddr_t)*va, 0, len); - return 0; - -fail4: - bus_dmamap_destroy(sc->sc_dmat, *dmamap); -fail3: - bus_dmamem_unmap(sc->sc_dmat, (caddr_t)*va, len); -fail2: - bus_dmamem_free(sc->sc_dmat, dmaseg, 1); -fail1: - return rc; -} - -int -iec_mii_readreg(struct device *self, int phy, int reg) -{ - struct iec_softc *sc = (void *)self; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - - if (iec_mii_wait(sc) != 0) - return 0; - - bus_space_write_4(st, sh, IOC3_ENET_MICR, IOC3_ENET_MICR_READ | - (phy << IOC3_ENET_MICR_PHY_SHIFT) | - (reg & IOC3_ENET_MICR_REG_MASK)); - delay(25); - - if (iec_mii_wait(sc) == 0) - return bus_space_read_4(st, sh, IOC3_ENET_MIDR_R) & - IOC3_ENET_MIDR_MASK; - - DPRINTF(IEC_DEBUG_MII, ("MII timed out reading %x\n", reg)); - return 0; -} - -void -iec_mii_writereg(struct device *self, int phy, int reg, int val) -{ - struct iec_softc *sc = (void *)self; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - - if (iec_mii_wait(sc) != 0) { - DPRINTF(IEC_DEBUG_MII, - ("MII timed out writing %x: %x\n", reg, val)); - return; - } - - bus_space_write_4(st, sh, IOC3_ENET_MIDR_W, val & IOC3_ENET_MIDR_MASK); - delay(60); - bus_space_write_4(st, sh, IOC3_ENET_MICR, - (phy << IOC3_ENET_MICR_PHY_SHIFT) | - (reg & IOC3_ENET_MICR_REG_MASK)); - delay(60); - - iec_mii_wait(sc); -} - -int -iec_mii_wait(struct iec_softc *sc) -{ - uint32_t busy; - int i; - - for (i = 0; i < 100; i++) { - busy = bus_space_read_4(sc->sc_st, sc->sc_sh, IOC3_ENET_MICR); - if ((busy & IOC3_ENET_MICR_BUSY) == 0) - return 0; - delay(30); - } - - printf("%s: MII timed out\n", sc->sc_dev.dv_xname); - return 1; -} - -void -iec_statchg(struct device *self) -{ - struct iec_softc *sc = (void *)self; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - uint32_t tcsr; - - if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0) { - tcsr = IOC3_ENET_TCSR_FULL_DUPLEX; - sc->sc_mcr |= IOC3_ENET_MCR_DUPLEX; - } else { - tcsr = IOC3_ENET_TCSR_HALF_DUPLEX; - sc->sc_mcr &= ~IOC3_ENET_MCR_DUPLEX; - } - - bus_space_write_4(st, sh, IOC3_ENET_MCR, sc->sc_mcr); - bus_space_write_4(st, sh, IOC3_ENET_TCSR, tcsr); -} - -void -iec_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct iec_softc *sc = ifp->if_softc; - - if ((ifp->if_flags & IFF_UP) == 0) - return; - - mii_pollstat(&sc->sc_mii); - ifmr->ifm_status = sc->sc_mii.mii_media_status; - ifmr->ifm_active = sc->sc_mii.mii_media_active; -} - -int -iec_mediachange(struct ifnet *ifp) -{ - struct iec_softc *sc = ifp->if_softc; - - if ((ifp->if_flags & IFF_UP) == 0) - return 0; - - return mii_mediachg(&sc->sc_mii); -} - -int -iec_init(struct ifnet *ifp) -{ - struct iec_softc *sc = ifp->if_softc; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - struct iec_rxdesc *rxd; - int i; - - /* Cancel any pending I/O. */ - iec_stop(ifp); - - /* Reset device. */ - iec_reset(sc); - - /* Setup filter for multicast or promisc mode. */ - iec_iff(sc); - - /* - * Initialize TX ring. - */ - - bus_space_write_4(st, sh, IOC3_ENET_TBR_H, IEC_CDTXADDR(sc, 0) >> 32); - bus_space_write_4(st, sh, IOC3_ENET_TBR_L, - (uint32_t)IEC_CDTXADDR(sc, 0)); - bus_space_write_4(st, sh, IOC3_ENET_TCIR, 0); - bus_space_write_4(st, sh, IOC3_ENET_TPIR, 0); - (void)bus_space_read_4(st, sh, IOC3_ENET_TCIR); - - sc->sc_txpending = 0; - sc->sc_txdirty = 0; - sc->sc_txlast = IEC_NTXDESC - 1; - - /* - * Initialize RX ring. - */ - - /* Point the RX base register to our RX pointers array. */ - bus_space_write_4(st, sh, IOC3_ENET_RBR_H, sc->sc_rxptrdma >> 32); - bus_space_write_4(st, sh, IOC3_ENET_RBR_L, (uint32_t)sc->sc_rxptrdma); - - sc->sc_rxci = 0; - sc->sc_rxpi = sc->sc_nrxdesc + 1; - bus_space_write_4(st, sh, IOC3_ENET_RCIR, - sc->sc_rxci * sizeof(uint64_t)); - bus_space_write_4(st, sh, IOC3_ENET_RPIR, - (sc->sc_rxpi * sizeof(uint64_t)) | IOC3_ENET_PIR_SET); - - /* Interrupt as soon as available RX desc reach this limit */ - bus_space_write_4(st, sh, IOC3_ENET_RCSR, - sc->sc_rxpi - sc->sc_rxci - 1); - /* Set up RX timer to interrupt immediately upon reception. */ - bus_space_write_4(st, sh, IOC3_ENET_RTR, 0); - - /* Initialize RX buffers. */ - for (i = 0; i < sc->sc_nrxdesc; i++) { - rxd = &sc->sc_rxdesc[i]; - rxd->rxd_stat = 0; - IEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); - IEC_RXBUFSYNC(sc, i, ETHER_MAX_LEN, BUS_DMASYNC_PREREAD); - } - - /* Enable DMA, and RX and TX interrupts */ - sc->sc_mcr &= IOC3_ENET_MCR_LARGE_SSRAM | IOC3_ENET_MCR_PARITY_ENABLE | - IOC3_ENET_MCR_PADEN; - sc->sc_mcr |= IOC3_ENET_MCR_TX_DMA | IOC3_ENET_MCR_TX | - IOC3_ENET_MCR_RX_DMA | IOC3_ENET_MCR_RX | - ((IEC_RXD_BUFOFFSET >> 1) << IOC3_ENET_MCR_RXOFF_SHIFT); - bus_space_write_4(st, sh, IOC3_ENET_MCR, sc->sc_mcr); - bus_space_write_4(st, sh, IOC3_ENET_IER, - IOC3_ENET_ISR_RX_TIMER | IOC3_ENET_ISR_RX_THRESHOLD | - (IOC3_ENET_ISR_TX_ALL & ~IOC3_ENET_ISR_TX_EMPTY)); - (void)bus_space_read_4(st, sh, IOC3_ENET_IER); - - timeout_add_sec(&sc->sc_tick, 1); - - ifp->if_flags |= IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - iec_start(ifp); - - mii_mediachg(&sc->sc_mii); - - return 0; -} - -void -iec_reset(struct iec_softc *sc) -{ - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - uint64_t address; - int i; - - DPRINTF(IEC_DEBUG_RESET, ("iec_reset\n")); - - /* Reset chip. */ - bus_space_write_4(st, sh, IOC3_ENET_MCR, IOC3_ENET_MCR_RESET); - delay(1000); - bus_space_write_4(st, sh, IOC3_ENET_MCR, 0); - delay(1000); - - bus_space_write_4(st, sh, IOC3_ENET_RBAR, 0); - - /* Set Ethernet address. */ - address = 0; - for (i = 0; i < ETHER_ADDR_LEN; i++) { - address <<= 8; - address += sc->sc_ac.ac_enaddr[ETHER_ADDR_LEN - 1 - i]; - } - bus_space_write_4(st, sh, IOC3_ENET_MAR_H, address >> 32); - bus_space_write_4(st, sh, IOC3_ENET_MAR_L, (uint32_t)address); - - /* Default to 100/half and let auto-negotiation work its magic. */ - bus_space_write_4(st, sh, IOC3_ENET_TCSR, IOC3_ENET_TCSR_HALF_DUPLEX); - - /* Reset collisions counter */ - (void)bus_space_read_4(st, sh, IOC3_ENET_TCDC); - - bus_space_write_4(st, sh, IOC3_ENET_RSR, 0x4d696f64); - - bus_space_write_4(st, sh, IOC3_ENET_HAR_H, 0); - bus_space_write_4(st, sh, IOC3_ENET_HAR_L, 0); -} - -void -iec_start(struct ifnet *ifp) -{ - struct iec_softc *sc = ifp->if_softc; - struct mbuf *m0; - struct iec_txdesc *txd; - struct iec_txsoft *txs; - bus_dmamap_t dmamap; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - uint64_t txdaddr; - int error, firstdirty, nexttx, opending; - int len; - - if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) - return; - - /* - * Remember the previous txpending and the first transmit descriptor. - */ - opending = sc->sc_txpending; - firstdirty = IEC_NEXTTX(sc->sc_txlast); - - DPRINTF(IEC_DEBUG_START, ("iec_start: opending = %d, firstdirty = %d\n", - opending, firstdirty)); - - while (sc->sc_txpending < IEC_NTXDESC - 1) { - /* Grab a packet off the queue. */ - m0 = ifq_dequeue(&ifp->if_snd); - if (m0 == NULL) - break; - - /* - * Get the next available transmit descriptor. - */ - nexttx = IEC_NEXTTX(sc->sc_txlast); - txd = &sc->sc_txdesc[nexttx]; - txs = &sc->sc_txsoft[nexttx]; - - len = m0->m_pkthdr.len; - - DPRINTF(IEC_DEBUG_START, - ("iec_start: len = %d, nexttx = %d\n", len, nexttx)); - - if (len <= IEC_TXD_BUFSIZE) { - /* - * If the packet is small enough, - * just copy it to the buffer in txdesc and - * pad with zeroes. - */ - DPRINTF(IEC_DEBUG_START, ("iec_start: short packet\n")); - - m_copydata(m0, 0, m0->m_pkthdr.len, txd->txd_buf); - if (len < ETHER_PAD_LEN) { - /* - * XXX would IOC3_ENET_MCR_PADEN in MCR do this - * XXX for us? - */ - memset(txd->txd_buf + len, 0, - ETHER_PAD_LEN - len); - len = ETHER_PAD_LEN; - } - - txs->txs_flags = IEC_TXCMD_BUF_V; - } else { - /* - * Although the packet may fit in the txdesc - * itself, we do not make use of this option, - * and use the two data pointers to handle it. - * There are two pointers because each chunk must - * not cross a 16KB boundary. - */ - dmamap = txs->txs_dmamap; - if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, - BUS_DMA_WRITE | BUS_DMA_NOWAIT) != 0) { - struct mbuf *m; - - DPRINTF(IEC_DEBUG_START, - ("iec_start: re-allocating mbuf\n")); - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) { - printf("%s: unable to allocate " - "TX mbuf\n", sc->sc_dev.dv_xname); - break; - } - if (len > (MHLEN - ETHER_ALIGN)) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - printf("%s: unable to allocate " - "TX cluster\n", - sc->sc_dev.dv_xname); - m_freem(m); - break; - } - } - /* - * Each packet has the Ethernet header, so - * in many cases the header isn't 4-byte aligned - * and data after the header is 4-byte aligned. - * Thus adding 2-byte offset before copying to - * new mbuf avoids unaligned copy and this may - * improve performance. - */ - m->m_data += ETHER_ALIGN; - m_copydata(m0, 0, len, mtod(m, caddr_t)); - m->m_pkthdr.len = m->m_len = len; - m_freem(m0); - m0 = m; - error = bus_dmamap_load_mbuf(sc->sc_dmat, - dmamap, m, BUS_DMA_WRITE | BUS_DMA_NOWAIT); - if (error) { - printf("%s: unable to load TX buffer, " - "error = %d\n", - sc->sc_dev.dv_xname, error); - m_freem(m); - break; - } - } - - txdaddr = dmamap->dm_segs[0].ds_addr; - txs->txs_flags = IEC_TXCMD_PTR0_V; - DPRINTF(IEC_DEBUG_START, - ("iec_start: ds_addr = %p\n", - dmamap->dm_segs[0].ds_addr)); - - DPRINTF(IEC_DEBUG_START, - ("iec_start: txdaddr = %p, len = %d\n", - txdaddr, len)); - - /* - * Sync the DMA map for TX mbuf. - * - * XXX unaligned part doesn't have to be sync'ed, - * but it's harmless... - */ - bus_dmamap_sync(sc->sc_dmat, dmamap, 0, - dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE); - } - -#if NBPFILTER > 0 - /* - * Pass packet to bpf if there is a listener. - */ - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT); -#endif - - /* - * Setup the transmit descriptor. - * Since there is apparently no way to get status - * information in the TX descriptor after we issue - * it, we have to always ask for interrupts upon - * completion, so that if we get a TX error interrupt, - * we know which descriptor it applies to. - */ - - txd->txd_cmd = IEC_TXCMD_TXINT | txs->txs_flags | - (len & IEC_TXCMD_DATALEN); - - if (txs->txs_flags & IEC_TXCMD_PTR0_V) { - uint32_t r1, r2; - - /* - * The chip DMA engine can not cross 16KB boundaries. - * If our mbuf doesn't fit, use the second pointer. - */ - - r1 = IEC_DMA_BOUNDARY - - (txdaddr & (IEC_DMA_BOUNDARY - 1)); - if (r1 >= len) { - /* only one chunk is necessary */ - r1 = len; - r2 = 0; - } else - r2 = len - r1; - - txd->txd_ptr[0] = txdaddr; - if (r2 != 0) { - txs->txs_flags |= IEC_TXCMD_PTR1_V; - txd->txd_ptr[1] = txdaddr + r1; - } else - txd->txd_ptr[1] = 0; - txd->txd_len = (r1 << IECTX_BUF1_LEN_SHIFT) | - (r2 << IECTX_BUF2_LEN_SHIFT); - - /* - * Store a pointer to the packet so we can - * free it later. - */ - txs->txs_mbuf = m0; - } else { - txd->txd_len = len << IECTX_BUF0_LEN_SHIFT; - txd->txd_ptr[0] = 0; - txd->txd_ptr[1] = 0; - /* - * In this case all data are copied to buffer in txdesc, - * we can free TX mbuf here. - */ - m_freem(m0); - } - - DPRINTF(IEC_DEBUG_START, - ("iec_start: txd_cmd = 0x%08x, txd_ptr = %p\n", - txd->txd_cmd, txd->txd_ptr[0])); - DPRINTF(IEC_DEBUG_START, - ("iec_start: len = %d (0x%04x)\n", len, len)); - - /* Sync TX descriptor. */ - IEC_TXDESCSYNC(sc, nexttx, - BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - - /* Advance the TX pointer. */ - sc->sc_txpending++; - sc->sc_txlast = nexttx; - } - - if (sc->sc_txpending >= IEC_NTXDESC - 1) { - /* No more slots; notify upper layer. */ - ifq_set_oactive(&ifp->if_snd); - } - - if (sc->sc_txpending != opending) { - /* Start TX. */ - bus_space_write_4(st, sh, IOC3_ENET_TPIR, - IEC_NEXTTX(sc->sc_txlast) * IEC_TXDESCSIZE); - - /* - * If the transmitter was idle, - * reset the txdirty pointer and re-enable TX interrupt. - */ - if (opending == 0) { - sc->sc_txdirty = firstdirty; - bus_space_write_4(st, sh, IOC3_ENET_IER, - bus_space_read_4(st, sh, IOC3_ENET_IER) | - IOC3_ENET_ISR_TX_EMPTY); - (void)bus_space_read_4(st, sh, IOC3_ENET_IER); - } - - /* Set a watchdog timer in case the chip flakes out. */ - ifp->if_timer = 5; - } -} - -void -iec_stop(struct ifnet *ifp) -{ - struct iec_softc *sc = ifp->if_softc; - struct iec_txsoft *txs; - int i; - - DPRINTF(IEC_DEBUG_STOP, ("iec_stop\n")); - - ifp->if_timer = 0; - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - timeout_del(&sc->sc_tick); - mii_down(&sc->sc_mii); - - /* Disable DMA and interrupts. */ - sc->sc_mcr &= ~(IOC3_ENET_MCR_TX_DMA | IOC3_ENET_MCR_RX_DMA); - bus_space_write_4(sc->sc_st, sc->sc_sh, IOC3_ENET_MCR, sc->sc_mcr); - bus_space_write_4(sc->sc_st, sc->sc_sh, IOC3_ENET_IER, 0); - (void)bus_space_read_4(sc->sc_st, sc->sc_sh, IOC3_ENET_IER); - - /* Release any TX buffers. */ - for (i = 0; i < IEC_NTXDESC; i++) { - txs = &sc->sc_txsoft[i]; - if ((txs->txs_flags & IEC_TXCMD_PTR0_V) != 0) { - bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); - m_freem(txs->txs_mbuf); - txs->txs_mbuf = NULL; - } - } -} - -int -iec_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct iec_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - int s, error = 0; - - s = splnet(); - - switch (cmd) { - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - if (!(ifp->if_flags & IFF_RUNNING)) - iec_init(ifp); - break; - - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING) - error = ENETRESET; - else - iec_init(ifp); - } else { - if (ifp->if_flags & IFF_RUNNING) - iec_stop(ifp); - } - break; - - case SIOCSIFMEDIA: - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd); - break; - - default: - error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); - } - - if (error == ENETRESET) { - if (ifp->if_flags & IFF_RUNNING) - iec_iff(sc); - error = 0; - } - - splx(s); - return error; -} - -void -iec_watchdog(struct ifnet *ifp) -{ - struct iec_softc *sc = ifp->if_softc; - - printf("%s: device timeout\n", sc->sc_dev.dv_xname); - ifp->if_oerrors++; - - DPRINTF(IEC_DEBUG_INTR, ("iec_watchdog: ISR %08x IER %08x\n", - bus_space_read_4(sc->sc_st, sc->sc_sh, IOC3_ENET_ISR), - bus_space_read_4(sc->sc_st, sc->sc_sh, IOC3_ENET_IER))); - - iec_init(ifp); -} - -void -iec_tick(void *arg) -{ - struct iec_softc *sc = arg; - int s; - - s = splnet(); - mii_tick(&sc->sc_mii); - splx(s); - - timeout_add_sec(&sc->sc_tick, 1); -} - -void -iec_iff(struct iec_softc *sc) -{ - struct arpcom *ac = &sc->sc_ac; - struct ifnet *ifp = &sc->sc_ac.ac_if; - struct ether_multi *enm; - struct ether_multistep step; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - uint64_t mchash = 0; - uint32_t hash; - - sc->sc_mcr &= ~IOC3_ENET_MCR_PROMISC; - ifp->if_flags &= ~IFF_ALLMULTI; - - if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { - ifp->if_flags |= IFF_ALLMULTI; - if (ifp->if_flags & IFF_PROMISC) - sc->sc_mcr |= IOC3_ENET_MCR_PROMISC; - mchash = 0xffffffffffffffffULL; - } else { - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - hash = ether_crc32_be(enm->enm_addrlo, - ETHER_ADDR_LEN) >> 26; - - mchash |= 1 << hash; - - ETHER_NEXT_MULTI(step, enm); - } - } - - bus_space_write_4(st, sh, IOC3_ENET_HAR_H, mchash >> 32); - bus_space_write_4(st, sh, IOC3_ENET_HAR_L, (uint32_t)mchash); - bus_space_write_4(st, sh, IOC3_ENET_MCR, sc->sc_mcr); -} - -struct mbuf * -iec_get(struct iec_softc *sc, uint8_t *data, size_t datalen) -{ - struct mbuf *m, **mp, *head; - size_t len, pad; - - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) { - printf("%s: unable to allocate RX mbuf\n", - sc->sc_dev.dv_xname); - return NULL; - } - - m->m_pkthdr.len = datalen; - - pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header); - m->m_data += pad; - len = MHLEN - pad; - head = NULL; - mp = &head; - - while (datalen != 0) { - if (head != NULL) { - MGET(m, M_DONTWAIT, MT_DATA); - if (m == NULL) { - printf("%s: unable to allocate RX mbuf\n", - sc->sc_dev.dv_xname); - m_freem(head); - return NULL; - } - len = MHLEN; - } - if (datalen >= MINCLSIZE) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - printf("%s: unable to allocate RX cluster\n", - sc->sc_dev.dv_xname); - m_freem(head); - m_freem(m); - return NULL; - } - len = MCLBYTES; - if (head == NULL) { - m->m_data += pad; - len -= pad; - } - } - m->m_len = len = min(datalen, len); - memcpy(mtod(m, caddr_t), data, len); - data += len; - datalen -= len; - *mp = m; - mp = &m->m_next; - } - - return head; -} - -int -iec_intr(void *arg) -{ - struct iec_softc *sc = arg; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - struct ifnet *ifp = &sc->sc_ac.ac_if; - uint32_t statreg, statack; - int handled, sent; - - DPRINTF(IEC_DEBUG_INTR, ("iec_intr: called\n")); - - handled = sent = 0; - - for (;;) { - statreg = bus_space_read_4(st, sh, IOC3_ENET_ISR); - - DPRINTF(IEC_DEBUG_INTR, - ("iec_intr: INT_STAT = 0x%x\n", statreg)); - - statack = statreg & bus_space_read_4(st, sh, IOC3_ENET_IER); - if (statack == 0) - break; - bus_space_write_4(st, sh, IOC3_ENET_ISR, statack); - - handled = 1; - - if (statack & - (IOC3_ENET_ISR_RX_TIMER | IOC3_ENET_ISR_RX_THRESHOLD)) { - iec_rxintr(sc, statreg); - } - - if (statack & IOC3_ENET_ISR_TX_ALL) { - iec_txintr(sc, statreg & IOC3_ENET_ISR_TX_ALL); - sent = 1; - } - } - - if (sent) { - /* Try to get more packets going. */ - iec_start(ifp); - } - - return handled; -} - -void -iec_rxintr(struct iec_softc *sc, uint32_t stat) -{ - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - struct ifnet *ifp = &sc->sc_ac.ac_if; - struct mbuf_list ml = MBUF_LIST_INITIALIZER(); - struct mbuf *m; - struct iec_rxdesc *rxd; - uint64_t rxstat; - size_t len; - u_int packets; - uint32_t i, ci; - - /* - * Figure out how many RX descriptors are available for processing. - */ - ci = bus_space_read_4(st, sh, IOC3_ENET_RCIR) / sizeof(uint64_t); - packets = (ci + IEC_NRXDESC_MAX - sc->sc_rxci) % IEC_NRXDESC_MAX; - sc->sc_rxpi = (sc->sc_rxpi + packets) % IEC_NRXDESC_MAX; - - DPRINTF(IEC_DEBUG_RXINTR, ("iec_rxintr: rx %d-%d\n", sc->sc_rxci, ci)); - while (packets-- != 0) { - i = (sc->sc_rxci++) & (sc->sc_nrxdesc - 1); - - IEC_RXSTATSYNC(sc, i, BUS_DMASYNC_POSTREAD); - rxd = &sc->sc_rxdesc[i]; - rxstat = rxd->rxd_stat; - - DPRINTF(IEC_DEBUG_RXINTR, - ("iec_rxintr: rxstat = 0x%08x, rxerr = 0x%08x\n", - rxstat, rxd->rxd_err)); - - if ((rxstat & IEC_RXSTAT_VALID) == 0) - goto dropit; - - len = (rxstat & IEC_RXSTAT_LEN_MASK) >> IEC_RXSTAT_LEN_SHIFT; - - if (len < ETHER_MIN_LEN || - len > ETHER_MAX_LEN) { - /* Invalid length packet; drop it. */ - DPRINTF(IEC_DEBUG_RXINTR, - ("iec_rxintr: wrong packet\n")); -dropit: - ifp->if_ierrors++; - rxd->rxd_stat = 0; - IEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); - continue; - } - - if (rxd->rxd_err & (IEC_RXERR_BADPACKET | IEC_RXERR_LONGEVENT | - IEC_RXERR_INVPREAMB | IEC_RXERR_CODE | IEC_RXERR_FRAME | - IEC_RXERR_CRC)) { - printf("%s: iec_rxintr: stat = 0x%08llx err = %08x\n", - sc->sc_dev.dv_xname, rxstat, rxd->rxd_err); - goto dropit; - } - - /* - * Now allocate an mbuf (and possibly a cluster) to hold - * the received packet. - */ - len -= ETHER_CRC_LEN; - IEC_RXBUFSYNC(sc, i, len, BUS_DMASYNC_POSTREAD); - m = iec_get(sc, rxd->rxd_buf, len); - IEC_RXBUFSYNC(sc, i, ETHER_MAX_LEN, BUS_DMASYNC_PREREAD); - if (m == NULL) - goto dropit; - - rxd->rxd_stat = 0; - IEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); - - ml_enqueue(&ml, m); - } - - /* Update RX index pointers. */ - sc->sc_rxci = ci; - bus_space_write_4(st, sh, IOC3_ENET_RPIR, - (sc->sc_rxpi * sizeof(uint64_t)) | IOC3_ENET_PIR_SET); - DPRINTF(IEC_DEBUG_RXINTR, ("iec_rxintr: new rxci %d rxpi %d\n", - sc->sc_rxci, sc->sc_rxpi)); - - if_input(ifp, &ml); -} - -void -iec_txintr(struct iec_softc *sc, uint32_t stat) -{ - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - struct ifnet *ifp = &sc->sc_ac.ac_if; - struct iec_txsoft *txs; - bus_dmamap_t dmamap; - uint32_t tcir; - int i, once, last; - - ifq_clr_oactive(&ifp->if_snd); - - tcir = bus_space_read_4(st, sh, IOC3_ENET_TCIR) & ~IOC3_ENET_TCIR_IDLE; - last = (tcir / IEC_TXDESCSIZE) % IEC_NTXDESC_MAX; - - DPRINTF(IEC_DEBUG_TXINTR, ("iec_txintr: dirty %d last %d\n", - sc->sc_txdirty, last)); - once = 0; - for (i = sc->sc_txdirty; i != last && sc->sc_txpending != 0; - i = IEC_NEXTTX(i), sc->sc_txpending--) { - txs = &sc->sc_txsoft[i]; - if ((txs->txs_flags & IEC_TXCMD_PTR0_V) != 0) { - dmamap = txs->txs_dmamap; - bus_dmamap_sync(sc->sc_dmat, dmamap, 0, - dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->sc_dmat, dmamap); - m_freem(txs->txs_mbuf); - txs->txs_mbuf = NULL; - } - - if ((stat & IOC3_ENET_ISR_TX_EXPLICIT) == 0) { - if (stat == IOC3_ENET_ISR_TX_EMPTY) - continue; - if (once == 0) { - printf("%s: TX error: txstat = %08x\n", - DEVNAME(sc), stat); - once = 1; - } - ifp->if_oerrors++; - } else { - ifp->if_collisions += IOC3_ENET_TCDC_COLLISION_MASK & - bus_space_read_4(st, sh, IOC3_ENET_TCDC); - } - } - - /* Update the dirty TX buffer pointer. */ - sc->sc_txdirty = i; - DPRINTF(IEC_DEBUG_INTR, - ("iec_txintr: sc_txdirty = %2d, sc_txpending = %2d\n", - sc->sc_txdirty, sc->sc_txpending)); - - /* Cancel the watchdog timer if there are no pending TX packets. */ - if (sc->sc_txpending == 0) - ifp->if_timer = 0; - - if (stat & IOC3_ENET_ISR_TX_EMPTY) { - bus_space_write_4(st, sh, IOC3_ENET_IER, - bus_space_read_4(st, sh, IOC3_ENET_IER) & - ~IOC3_ENET_ISR_TX_EMPTY); - (void)bus_space_read_4(st, sh, IOC3_ENET_IER); - } -} - -int -iec_ssram_probe(struct iec_softc *sc) -{ - /* - * Depending on the hardware, there is either 64KB or 128KB of - * 16-bit SSRAM, which is used as internal RX buffers by the chip. - */ - - /* default to large size */ - sc->sc_mcr = IOC3_ENET_MCR_PARITY_ENABLE | IOC3_ENET_MCR_LARGE_SSRAM; - bus_space_write_4(sc->sc_st, sc->sc_sh, IOC3_ENET_MCR, sc->sc_mcr); - - bus_space_write_4(sc->sc_st, sc->sc_sh, - IOC3_SSRAM_BASE, 0x55aa); - bus_space_write_4(sc->sc_st, sc->sc_sh, - IOC3_SSRAM_BASE + IOC3_SSRAM_SMALL_SIZE, 0xffff ^ 0x55aa); - - if ((bus_space_read_4(sc->sc_st, sc->sc_sh, IOC3_SSRAM_BASE) & - IOC3_SSRAM_DATA_MASK) != 0x55aa || - (bus_space_read_4(sc->sc_st, sc->sc_sh, - IOC3_SSRAM_BASE + IOC3_SSRAM_SMALL_SIZE) != (0xffff ^ 0x55aa))) { - sc->sc_mcr &= ~IOC3_ENET_MCR_LARGE_SSRAM; - sc->sc_nrxdesc = IEC_NRXDESC_SMALL; - return IOC3_SSRAM_SMALL_SIZE / 2 / 1024; - } else { - sc->sc_nrxdesc = IEC_NRXDESC_LARGE; - return IOC3_SSRAM_LARGE_SIZE / 2 / 1024; - } -} diff --git a/sys/arch/sgi/dev/if_iecreg.h b/sys/arch/sgi/dev/if_iecreg.h deleted file mode 100644 index d9916472229..00000000000 --- a/sys/arch/sgi/dev/if_iecreg.h +++ /dev/null @@ -1,95 +0,0 @@ -/* $OpenBSD: if_iecreg.h,v 1.4 2021/03/11 11:17:00 jsg Exp $ */ - -/* - * Copyright (c) 2009 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. - */ - -/* - * Ethernet controller part of the IOC3 ASIC. - */ - -/* - * Receive buffer descriptor. - */ - -#define IEC_NRXDESC_MAX 512 - -#define IEC_RXDESCSIZE (4096) -#define IEC_RXD_BUFOFFSET (64 + 2) /* to align Ethernet header */ -#define IEC_RXD_NRXPAD (IEC_RXD_BUFOFFSET - 2 * sizeof(uint32_t)) -#define IEC_RXD_BUFSIZE (IEC_RXDESCSIZE - IEC_RXD_BUFOFFSET) - -/* - * IEC_RXDESCSIZE is the smallest multiple of 128 bytes (hardware requirement) - * able to store ETHER_MAX_DIX_LEN bytes and the rxdesc administrative data. - * - * IEC_RXD_BUFOFFSET is chosen to use a different cache line on the CPU. - * A value of 128 (IOC3 cache line) would be even better, but would not fit - * in the MCR register. - */ - -struct iec_rxdesc { - volatile uint32_t rxd_stat; -#define IEC_RXSTAT_VALID 0x80000000 /* descriptor valid */ -#define IEC_RXSTAT_LEN_MASK 0x07ff0000 -#define IEC_RXSTAT_LEN_SHIFT 16 -#define IEC_RXSTAT_CHECKSUM_MASK 0x0000ffff - uint32_t rxd_err; -#define IEC_RXERR_CRC 0x00000001 /* CRC error */ -#define IEC_RXERR_FRAME 0x00000002 /* Framing error */ -#define IEC_RXERR_CODE 0x00000004 /* Code violation */ -#define IEC_RXERR_INVPREAMB 0x00000008 /* Invalid preamble */ -#define IEC_RXERR_MULTICAST 0x04000000 /* Multicast packet */ -#define IEC_RXERR_BROADCAST 0x08000000 /* Broadcast packet */ -#define IEC_RXERR_LONGEVENT 0x10000000 /* Long packet */ -#define IEC_RXERR_BADPACKET 0x20000000 /* Bad packet */ -#define IEC_RXERR_GOODPACKET 0x40000000 -#define IEC_RXERR_CARRIER 0x80000000 /* Carrier event */ - uint8_t rxd_pad[IEC_RXD_NRXPAD]; - uint8_t rxd_buf[IEC_RXD_BUFSIZE]; -}; - -/* - * Transmit buffer descriptor. - */ - -#define IEC_NTXDESC_MAX 128 - -#define IEC_TXDESCSIZE 128 -#define IEC_NTXPTR 2 -#define IEC_TXD_BUFOFFSET \ - (2 * sizeof(uint32_t) + IEC_NTXPTR * sizeof(uint64_t)) -#define IEC_TXD_BUFSIZE (IEC_TXDESCSIZE - IEC_TXD_BUFOFFSET) - -struct iec_txdesc { - uint32_t txd_cmd; -#define IEC_TXCMD_DATALEN 0x000007ff -#define IEC_TXCMD_TXINT 0x00001000 /* interrupt after TX */ -#define IEC_TXCMD_BUF_V 0x00010000 /* txd_buf valid */ -#define IEC_TXCMD_PTR0_V 0x00020000 /* tx_ptr[0] valid */ -#define IEC_TXCMD_PTR1_V 0x00040000 /* tx_ptr[1] valid */ -#define IEC_TXCMD_HWCHECKSUM 0x00080000 /* perform hw cksum */ -#define IEC_TXCMD_CHECKSUM_POS_MASK 0x07f00000 /* hw cksum byte pos */ -#define IEC_TXCMD_CHECKSUM_POS_SHIFT 20 - uint32_t txd_len; -#define IECTX_BUF0_LEN_MASK 0x0000007f -#define IECTX_BUF0_LEN_SHIFT 0 -#define IECTX_BUF1_LEN_MASK 0x0007ff00 -#define IECTX_BUF1_LEN_SHIFT 8 -#define IECTX_BUF2_LEN_MASK 0x7ff00000 -#define IECTX_BUF2_LEN_SHIFT 20 - uint64_t txd_ptr[IEC_NTXPTR]; - uint8_t txd_buf[IEC_TXD_BUFSIZE]; -}; diff --git a/sys/arch/sgi/dev/if_mec.c b/sys/arch/sgi/dev/if_mec.c deleted file mode 100644 index f9a2e4876c1..00000000000 --- a/sys/arch/sgi/dev/if_mec.c +++ /dev/null @@ -1,1409 +0,0 @@ -/* $OpenBSD: if_mec.c,v 1.41 2020/07/10 13:26:36 patrick Exp $ */ -/* $NetBSD: if_mec_mace.c,v 1.5 2004/08/01 06:36:36 tsutsui Exp $ */ - -/* - * Copyright (c) 2004 Izumi Tsutsui. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (c) 2003 Christopher SEKIYA - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the - * NetBSD Project. See http://www.NetBSD.org/ for - * information about NetBSD. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * MACE MAC-110 Ethernet driver. - */ - -#include "bpfilter.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/timeout.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/errno.h> - -#include <net/if.h> -#include <net/if_media.h> - -#if NBPFILTER > 0 -#include <net/bpf.h> -#endif - -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include <machine/bus.h> -#include <machine/intr.h> -#include <machine/autoconf.h> - -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> - -#include <mips64/arcbios.h> -#include <sgi/dev/if_mecreg.h> - -#include <sgi/localbus/macebusvar.h> - -#ifdef MEC_DEBUG -#define MEC_DEBUG_RESET 0x01 -#define MEC_DEBUG_START 0x02 -#define MEC_DEBUG_STOP 0x04 -#define MEC_DEBUG_INTR 0x08 -#define MEC_DEBUG_RXINTR 0x10 -#define MEC_DEBUG_TXINTR 0x20 -uint32_t mec_debug = 0xff; -#define DPRINTF(x, y) if (mec_debug & (x)) printf y -#else -#define DPRINTF(x, y) /* nothing */ -#endif - -/* - * Transmit descriptor list size. - */ -#define MEC_NTXDESC 64 -#define MEC_NTXDESC_MASK (MEC_NTXDESC - 1) -#define MEC_NEXTTX(x) (((x) + 1) & MEC_NTXDESC_MASK) - -/* - * Software state for TX. - */ -struct mec_txsoft { - struct mbuf *txs_mbuf; /* Head of our mbuf chain. */ - bus_dmamap_t txs_dmamap; /* Our DMA map. */ - uint32_t txs_flags; -#define MEC_TXS_BUFLEN_MASK 0x0000007f /* Data len in txd_buf. */ -#define MEC_TXS_TXDBUF 0x00000080 /* txd_buf is used. */ -#define MEC_TXS_TXDPTR1 0x00000100 /* txd_ptr[0] is used. */ -}; - -/* - * Transmit buffer descriptor. - */ -#define MEC_TXDESCSIZE 128 -#define MEC_NTXPTR 3 -#define MEC_TXD_BUFOFFSET \ - (sizeof(uint64_t) + MEC_NTXPTR * sizeof(uint64_t)) -#define MEC_TXD_BUFSIZE (MEC_TXDESCSIZE - MEC_TXD_BUFOFFSET) -#define MEC_TXD_BUFSTART(len) (MEC_TXD_BUFSIZE - (len)) -#define MEC_TXD_ALIGN 8 -#define MEC_TXD_ROUNDUP(addr) \ - (((addr) + (MEC_TXD_ALIGN - 1)) & ~((uint64_t)MEC_TXD_ALIGN - 1)) - -struct mec_txdesc { - volatile uint64_t txd_cmd; -#define MEC_TXCMD_DATALEN 0x000000000000ffff /* Data length. */ -#define MEC_TXCMD_BUFSTART 0x00000000007f0000 /* Start byte offset. */ -#define TXCMD_BUFSTART(x) ((x) << 16) -#define MEC_TXCMD_TERMDMA 0x0000000000800000 /* Stop DMA on abort. */ -#define MEC_TXCMD_TXINT 0x0000000001000000 /* INT after TX done. */ -#define MEC_TXCMD_PTR1 0x0000000002000000 /* Valid 1st txd_ptr. */ -#define MEC_TXCMD_PTR2 0x0000000004000000 /* Valid 2nd txd_ptr. */ -#define MEC_TXCMD_PTR3 0x0000000008000000 /* Valid 3rd txd_ptr. */ -#define MEC_TXCMD_UNUSED 0xfffffffff0000000ULL /* Should be zero. */ - -#define txd_stat txd_cmd -#define MEC_TXSTAT_LEN 0x000000000000ffff /* TX length. */ -#define MEC_TXSTAT_COLCNT 0x00000000000f0000 /* Collision count. */ -#define MEC_TXSTAT_COLCNT_SHIFT 16 -#define MEC_TXSTAT_LATE_COL 0x0000000000100000 /* Late collision. */ -#define MEC_TXSTAT_CRCERROR 0x0000000000200000 /* */ -#define MEC_TXSTAT_DEFERRED 0x0000000000400000 /* */ -#define MEC_TXSTAT_SUCCESS 0x0000000000800000 /* TX complete. */ -#define MEC_TXSTAT_TOOBIG 0x0000000001000000 /* */ -#define MEC_TXSTAT_UNDERRUN 0x0000000002000000 /* */ -#define MEC_TXSTAT_COLLISIONS 0x0000000004000000 /* */ -#define MEC_TXSTAT_EXDEFERRAL 0x0000000008000000 /* */ -#define MEC_TXSTAT_COLLIDED 0x0000000010000000 /* */ -#define MEC_TXSTAT_UNUSED 0x7fffffffe0000000ULL /* Should be zero. */ -#define MEC_TXSTAT_SENT 0x8000000000000000ULL /* Packet sent. */ - - uint64_t txd_ptr[MEC_NTXPTR]; -#define MEC_TXPTR_UNUSED2 0x0000000000000007 /* Should be zero. */ -#define MEC_TXPTR_DMAADDR 0x00000000fffffff8 /* TX DMA address. */ -#define MEC_TXPTR_LEN 0x0000ffff00000000ULL /* Buffer length. */ -#define TXPTR_LEN(x) ((uint64_t)(x) << 32) -#define MEC_TXPTR_UNUSED1 0xffff000000000000ULL /* Should be zero. */ - - uint8_t txd_buf[MEC_TXD_BUFSIZE]; -}; - -/* - * Receive buffer size. - */ -#define MEC_NRXDESC 16 -#define MEC_NRXDESC_MASK (MEC_NRXDESC - 1) -#define MEC_NEXTRX(x) (((x) + 1) & MEC_NRXDESC_MASK) - -/* - * Receive buffer description. - */ -#define MEC_RXDESCSIZE 4096 /* Umm, should be 4kbyte aligned. */ -#define MEC_RXD_NRXPAD 3 -#define MEC_RXD_DMAOFFSET (1 + MEC_RXD_NRXPAD) -#define MEC_RXD_BUFOFFSET (MEC_RXD_DMAOFFSET * sizeof(uint64_t)) -#define MEC_RXD_BUFSIZE (MEC_RXDESCSIZE - MEC_RXD_BUFOFFSET) - -struct mec_rxdesc { - volatile uint64_t rxd_stat; -#define MEC_RXSTAT_LEN 0x000000000000ffff /* Data length. */ -#define MEC_RXSTAT_VIOLATION 0x0000000000010000 /* Code violation (?). */ -#define MEC_RXSTAT_UNUSED2 0x0000000000020000 /* Unknown (?). */ -#define MEC_RXSTAT_CRCERROR 0x0000000000040000 /* CRC error. */ -#define MEC_RXSTAT_MULTICAST 0x0000000000080000 /* Multicast packet. */ -#define MEC_RXSTAT_BROADCAST 0x0000000000100000 /* Broadcast packet. */ -#define MEC_RXSTAT_INVALID 0x0000000000200000 /* Invalid preamble. */ -#define MEC_RXSTAT_LONGEVENT 0x0000000000400000 /* Long packet. */ -#define MEC_RXSTAT_BADPACKET 0x0000000000800000 /* Bad packet. */ -#define MEC_RXSTAT_CAREVENT 0x0000000001000000 /* Carrier event. */ -#define MEC_RXSTAT_MATCHMCAST 0x0000000002000000 /* Match multicast. */ -#define MEC_RXSTAT_MATCHMAC 0x0000000004000000 /* Match MAC. */ -#define MEC_RXSTAT_SEQNUM 0x00000000f8000000 /* Sequence number. */ -#define MEC_RXSTAT_CKSUM 0x0000ffff00000000ULL /* IP checksum. */ -#define MEC_RXSTAT_UNUSED1 0x7fff000000000000ULL /* Should be zero. */ -#define MEC_RXSTAT_RECEIVED 0x8000000000000000ULL /* Set to 1 on RX. */ - uint64_t rxd_pad1[MEC_RXD_NRXPAD]; - uint8_t rxd_buf[MEC_RXD_BUFSIZE]; -}; - -/* - * Control structures for DMA ops. - */ -struct mec_control_data { - /* - * TX descriptors and buffers. - */ - struct mec_txdesc mcd_txdesc[MEC_NTXDESC]; - - /* - * RX descriptors and buffers. - */ - struct mec_rxdesc mcd_rxdesc[MEC_NRXDESC]; -}; - -/* - * It _seems_ there are some restrictions on descriptor address: - * - * - Base address of txdescs should be 8kbyte aligned - * - Each txdesc should be 128byte aligned - * - Each rxdesc should be 4kbyte aligned - * - * So we should specify 64k align to allocalte txdescs. - * In this case, sizeof(struct mec_txdesc) * MEC_NTXDESC is 8192 - * so rxdescs are also allocated at 4kbyte aligned. - */ -#define MEC_CONTROL_DATA_ALIGN (8 * 1024) - -#define MEC_CDOFF(x) offsetof(struct mec_control_data, x) -#define MEC_CDTXOFF(x) MEC_CDOFF(mcd_txdesc[(x)]) -#define MEC_CDRXOFF(x) MEC_CDOFF(mcd_rxdesc[(x)]) - -/* - * Software state per device. - */ -struct mec_softc { - struct device sc_dev; /* Generic device structures. */ - struct arpcom sc_ac; /* Ethernet common part. */ - - bus_space_tag_t sc_st; /* bus_space tag. */ - bus_space_handle_t sc_sh; /* bus_space handle. */ - bus_dma_tag_t sc_dmat; /* bus_dma tag. */ - - struct mii_data sc_mii; /* MII/media information. */ - struct timeout sc_tick_ch; /* Tick timeout. */ - - bus_dmamap_t sc_cddmamap; /* bus_dma map for control data. */ -#define sc_cddma sc_cddmamap->dm_segs[0].ds_addr - - /* Pointer to allocated control data. */ - struct mec_control_data *sc_control_data; -#define sc_txdesc sc_control_data->mcd_txdesc -#define sc_rxdesc sc_control_data->mcd_rxdesc - - /* Software state for TX descs. */ - struct mec_txsoft sc_txsoft[MEC_NTXDESC]; - - int sc_txpending; /* Number of TX requests pending. */ - int sc_txdirty; /* First dirty TX descriptor. */ - int sc_txlast; /* Last used TX descriptor. */ - - int sc_rxptr; /* Next ready RX buffer. */ -}; - -#define MEC_CDTXADDR(sc, x) ((sc)->sc_cddma + MEC_CDTXOFF(x)) -#define MEC_CDRXADDR(sc, x) ((sc)->sc_cddma + MEC_CDRXOFF(x)) - -#define MEC_TXDESCSYNC(sc, x, ops) \ - bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ - MEC_CDTXOFF(x), MEC_TXDESCSIZE, (ops)) -#define MEC_TXCMDSYNC(sc, x, ops) \ - bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ - MEC_CDTXOFF(x), sizeof(uint64_t), (ops)) - -#define MEC_RXSTATSYNC(sc, x, ops) \ - bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ - MEC_CDRXOFF(x), sizeof(uint64_t), (ops)) -#define MEC_RXBUFSYNC(sc, x, len, ops) \ - bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ - MEC_CDRXOFF(x) + MEC_RXD_BUFOFFSET, \ - ETHER_ALIGN + (len), (ops)) - -/* XXX these values should be moved to <net/if_ether.h> ? */ -#define ETHER_PAD_LEN (ETHER_MIN_LEN - ETHER_CRC_LEN) - -struct cfdriver mec_cd = { - NULL, "mec", DV_IFNET -}; - -int mec_match(struct device *, void *, void *); -void mec_attach(struct device *, struct device *, void *); - -struct cfattach mec_ca = { - sizeof(struct mec_softc), mec_match, mec_attach -}; - -int mec_mii_readreg(struct device *, int, int); -void mec_mii_writereg(struct device *, int, int, int); -int mec_mii_wait(struct mec_softc *); -void mec_statchg(struct device *); -void mec_mediastatus(struct ifnet *, struct ifmediareq *); -int mec_mediachange(struct ifnet *); - -int mec_init(struct ifnet * ifp); -void mec_start(struct ifnet *); -void mec_watchdog(struct ifnet *); -void mec_tick(void *); -int mec_ioctl(struct ifnet *, u_long, caddr_t); -void mec_reset(struct mec_softc *, int); -void mec_iff(struct mec_softc *); -int mec_intr(void *arg); -void mec_stop(struct ifnet *); -void mec_rxintr(struct mec_softc *, uint32_t); -void mec_txintr(struct mec_softc *, uint32_t); - -int -mec_match(struct device *parent, void *match, void *aux) -{ - return (1); -} - -void -mec_attach(struct device *parent, struct device *self, void *aux) -{ - struct mec_softc *sc = (void *)self; - struct macebus_attach_args *maa = aux; - struct ifnet *ifp = &sc->sc_ac.ac_if; - uint32_t command; - struct mii_softc *child; - bus_dma_segment_t seg; - int i, err, rseg; - - sc->sc_st = maa->maa_iot; - if (bus_space_map(sc->sc_st, maa->maa_baseaddr, MEC_NREGS, 0, - &sc->sc_sh) != 0) { - printf(": can't map i/o space\n"); - return; - } - - /* Set up DMA structures. */ - sc->sc_dmat = maa->maa_dmat; - - /* - * Allocate the control data structures, and create and load the - * DMA map for it. - */ - if ((err = bus_dmamem_alloc(sc->sc_dmat, - sizeof(struct mec_control_data), MEC_CONTROL_DATA_ALIGN, 0, - &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { - printf(": unable to allocate control data, error = %d\n", err); - goto fail_0; - } - - /* - * XXX needs re-think... - * control data structures contain whole RX data buffer, so - * BUS_DMA_COHERENT (which disables cache) may cause some performance - * issue on copying data from the RX buffer to mbuf on normal memory, - * though we have to make sure all bus_dmamap_sync(9) ops are called - * properly in that case. - */ - if ((err = bus_dmamem_map(sc->sc_dmat, &seg, rseg, - sizeof(struct mec_control_data), - (caddr_t *)&sc->sc_control_data, /*BUS_DMA_COHERENT*/ 0)) != 0) { - printf(": unable to map control data, error = %d\n", err); - goto fail_1; - } - memset(sc->sc_control_data, 0, sizeof(struct mec_control_data)); - - if ((err = bus_dmamap_create(sc->sc_dmat, - sizeof(struct mec_control_data), 1, - sizeof(struct mec_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { - printf(": unable to create control data DMA map, error = %d\n", - err); - goto fail_2; - } - if ((err = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, - sc->sc_control_data, sizeof(struct mec_control_data), NULL, - BUS_DMA_NOWAIT)) != 0) { - printf(": unable to load control data DMA map, error = %d\n", - err); - goto fail_3; - } - - /* Create TX buffer DMA maps. */ - for (i = 0; i < MEC_NTXDESC; i++) { - if ((err = bus_dmamap_create(sc->sc_dmat, - MCLBYTES, 1, MCLBYTES, 0, 0, - &sc->sc_txsoft[i].txs_dmamap)) != 0) { - printf(": unable to create tx DMA map %d, error = %d\n", - i, err); - goto fail_4; - } - } - - timeout_set(&sc->sc_tick_ch, mec_tick, sc); - - /* Use the Ethernet address from the ARCBIOS. */ - enaddr_aton(bios_enaddr, sc->sc_ac.ac_enaddr); - - /* Reset device. */ - mec_reset(sc, 1); - - command = bus_space_read_8(sc->sc_st, sc->sc_sh, MEC_MAC_CONTROL); - - printf(": MAC-110 rev %d, address %s\n", - (command & MEC_MAC_REVISION) >> MEC_MAC_REVISION_SHIFT, - ether_sprintf(sc->sc_ac.ac_enaddr)); - - /* Done, now attach everything. */ - - sc->sc_mii.mii_ifp = ifp; - sc->sc_mii.mii_readreg = mec_mii_readreg; - sc->sc_mii.mii_writereg = mec_mii_writereg; - sc->sc_mii.mii_statchg = mec_statchg; - - /* Set up PHY properties. */ - ifmedia_init(&sc->sc_mii.mii_media, 0, mec_mediachange, - mec_mediastatus); - mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, - MII_OFFSET_ANY, 0); - - child = LIST_FIRST(&sc->sc_mii.mii_phys); - if (child == NULL) { - /* No PHY attached. */ - ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL, - 0, NULL); - ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL); - } else { - ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO); - } - - bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); - ifp->if_softc = sc; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = mec_ioctl; - ifp->if_start = mec_start; - ifp->if_watchdog = mec_watchdog; - - if_attach(ifp); - ifq_set_maxlen(&ifp->if_snd, MEC_NTXDESC - 1); - ether_ifattach(ifp); - - /* Establish interrupt handler. */ - macebus_intr_establish(maa->maa_intr, maa->maa_mace_intr, - IPL_NET, mec_intr, sc, sc->sc_dev.dv_xname); - - return; - - /* - * Free any resources we've allocated during the failed attach - * attempt. Do this in reverse order and fall though. - */ - fail_4: - for (i = 0; i < MEC_NTXDESC; i++) { - if (sc->sc_txsoft[i].txs_dmamap != NULL) - bus_dmamap_destroy(sc->sc_dmat, - sc->sc_txsoft[i].txs_dmamap); - } - bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); - fail_3: - bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); - fail_2: - bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data, - sizeof(struct mec_control_data)); - fail_1: - bus_dmamem_free(sc->sc_dmat, &seg, rseg); - fail_0: - return; -} - -int -mec_mii_readreg(struct device *self, int phy, int reg) -{ - struct mec_softc *sc = (void *)self; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - uint64_t val; - int i; - - if (mec_mii_wait(sc) != 0) - return 0; - - bus_space_write_8(st, sh, MEC_PHY_ADDRESS, - (phy << MEC_PHY_ADDR_DEVSHIFT) | (reg & MEC_PHY_ADDR_REGISTER)); - bus_space_write_8(st, sh, MEC_PHY_READ_INITIATE, 1); - - for (i = 0; i < 20; i++) { - delay(25); - val = bus_space_read_8(st, sh, MEC_PHY_DATA); - - if ((val & MEC_PHY_DATA_BUSY) == 0) - return val & MEC_PHY_DATA_VALUE; - } - return 0; -} - -void -mec_mii_writereg(struct device *self, int phy, int reg, int val) -{ - struct mec_softc *sc = (void *)self; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - - if (mec_mii_wait(sc) != 0) { - printf("MII timed out writing %x: %x\n", reg, val); - return; - } - - bus_space_write_8(st, sh, MEC_PHY_ADDRESS, - (phy << MEC_PHY_ADDR_DEVSHIFT) | (reg & MEC_PHY_ADDR_REGISTER)); - bus_space_write_8(st, sh, MEC_PHY_DATA, val & MEC_PHY_DATA_VALUE); - - mec_mii_wait(sc); -} - -int -mec_mii_wait(struct mec_softc *sc) -{ - uint64_t busy; - int i; - - for (i = 0; i < 100; i++) { - busy = bus_space_read_8(sc->sc_st, sc->sc_sh, MEC_PHY_DATA); - if ((busy & MEC_PHY_DATA_BUSY) == 0) - return 0; - delay(30); - } - - printf("%s: MII timed out\n", sc->sc_dev.dv_xname); - return 1; -} - -void -mec_statchg(struct device *self) -{ - struct mec_softc *sc = (void *)self; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - uint32_t control; - - control = bus_space_read_8(st, sh, MEC_MAC_CONTROL); - control &= ~(MEC_MAC_IPGT | MEC_MAC_IPGR1 | MEC_MAC_IPGR2 | - MEC_MAC_FULL_DUPLEX | MEC_MAC_SPEED_SELECT); - - /* Must also set IPG here for duplex stuff... */ - if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0) { - control |= MEC_MAC_FULL_DUPLEX; - } else { - /* Set IPG. */ - control |= MEC_MAC_IPG_DEFAULT; - } - - bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); -} - -void -mec_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct mec_softc *sc = ifp->if_softc; - - if ((ifp->if_flags & IFF_UP) == 0) - return; - - mii_pollstat(&sc->sc_mii); - ifmr->ifm_status = sc->sc_mii.mii_media_status; - ifmr->ifm_active = sc->sc_mii.mii_media_active; -} - -int -mec_mediachange(struct ifnet *ifp) -{ - struct mec_softc *sc = ifp->if_softc; - - if ((ifp->if_flags & IFF_UP) == 0) - return 0; - - return mii_mediachg(&sc->sc_mii); -} - -int -mec_init(struct ifnet *ifp) -{ - struct mec_softc *sc = ifp->if_softc; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - struct mec_rxdesc *rxd; - int i; - - /* Cancel any pending I/O. */ - mec_stop(ifp); - - /* Reset device. */ - mec_reset(sc, 0); - - /* Setup filter for multicast or promisc mode. */ - mec_iff(sc); - - /* Set the TX ring pointer to the base address. */ - bus_space_write_8(st, sh, MEC_TX_RING_BASE, MEC_CDTXADDR(sc, 0)); - - sc->sc_txpending = 0; - sc->sc_txdirty = 0; - sc->sc_txlast = MEC_NTXDESC - 1; - - /* Put RX buffers into FIFO. */ - for (i = 0; i < MEC_NRXDESC; i++) { - rxd = &sc->sc_rxdesc[i]; - rxd->rxd_stat = 0; - MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); - MEC_RXBUFSYNC(sc, i, ETHER_MAX_LEN, BUS_DMASYNC_PREREAD); - bus_space_write_8(st, sh, MEC_MCL_RX_FIFO, MEC_CDRXADDR(sc, i)); - } - sc->sc_rxptr = 0; - -#if 0 /* XXX no info */ - bus_space_write_8(st, sh, MEC_TIMER, 0); -#endif - - /* - * MEC_DMA_TX_INT_ENABLE will be set later otherwise it causes - * spurious interrupts when TX buffers are empty. - */ - bus_space_write_8(st, sh, MEC_DMA_CONTROL, - (MEC_RXD_DMAOFFSET << MEC_DMA_RX_DMA_OFFSET_SHIFT) | - (MEC_NRXDESC << MEC_DMA_RX_INT_THRESH_SHIFT) | - MEC_DMA_TX_DMA_ENABLE | /* MEC_DMA_TX_INT_ENABLE | */ - MEC_DMA_RX_DMA_ENABLE | MEC_DMA_RX_INT_ENABLE); - - timeout_add_sec(&sc->sc_tick_ch, 1); - - ifp->if_flags |= IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - mec_start(ifp); - - mii_mediachg(&sc->sc_mii); - - return 0; -} - -void -mec_reset(struct mec_softc *sc, int firsttime) -{ - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - uint64_t address; - int i; - - /* Reset chip. */ - bus_space_write_8(st, sh, MEC_MAC_CONTROL, MEC_MAC_CORE_RESET); - delay(1000); - bus_space_write_8(st, sh, MEC_MAC_CONTROL, 0); - delay(1000); - - /* Set Ethernet address. */ - address = 0; - for (i = 0; i < ETHER_ADDR_LEN; i++) { - address = address << 8; - address += sc->sc_ac.ac_enaddr[i]; - } - bus_space_write_8(st, sh, MEC_STATION, address); - - /* Default to 100/half and let auto-negotiation work its magic. */ - bus_space_write_8(st, sh, MEC_MAC_CONTROL, - MEC_MAC_SPEED_SELECT | MEC_MAC_IPG_DEFAULT); - - bus_space_write_8(st, sh, MEC_DMA_CONTROL, 0); - - DPRINTF(MEC_DEBUG_RESET, ("mec: control now %llx\n", - bus_space_read_8(st, sh, MEC_MAC_CONTROL))); - - if (firsttime) { - /* - * After a cold boot, during the initial MII probe, the - * PHY would sometimes answer to addresses 11 or 10, only - * to settle to address 8 shortly after. - * - * Because of this, the PHY driver would attach to the wrong - * address and further link configuration would fail (with PHY - * register reads returning either 0 or FFFF), leading to - * horrible performance and no way to select a proper media. - */ - int i, reg, phyno; - for (phyno = 0; phyno < MII_NPHY; phyno++) { - reg = mec_mii_readreg(&sc->sc_dev, phyno, MII_BMSR); - /* same logic as in mii_attach() */ - if (reg == 0 || reg == 0xffff || - (reg & (BMSR_MEDIAMASK | BMSR_EXTSTAT)) == 0) - continue; - /* inline mii_phy_reset() */ - mec_mii_writereg(&sc->sc_dev, phyno, MII_BMCR, - BMCR_RESET | BMCR_ISO); - delay(500); - for (i = 0; i < 100; i++) { - reg = mec_mii_readreg(&sc->sc_dev, phyno, - MII_BMCR); - if ((reg & BMCR_RESET) == 0) { - mec_mii_writereg(&sc->sc_dev, phyno, - MII_BMCR, reg | BMCR_ISO); - break; - } - delay(1000); - } - } - } -} - -void -mec_start(struct ifnet *ifp) -{ - struct mec_softc *sc = ifp->if_softc; - struct mbuf *m0; - struct mec_txdesc *txd; - struct mec_txsoft *txs; - bus_dmamap_t dmamap; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - uint64_t txdaddr; - int error, firsttx, nexttx, opending; - int len, bufoff, buflen, unaligned, txdlen; - - if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) - return; - - /* - * Remember the previous txpending and the first transmit descriptor. - */ - opending = sc->sc_txpending; - firsttx = MEC_NEXTTX(sc->sc_txlast); - - DPRINTF(MEC_DEBUG_START, - ("mec_start: opending = %d, firsttx = %d\n", opending, firsttx)); - - for (;;) { - /* Grab a packet off the queue. */ - m0 = ifq_deq_begin(&ifp->if_snd); - if (m0 == NULL) - break; - - if (sc->sc_txpending == MEC_NTXDESC) { - ifq_deq_rollback(&ifp->if_snd, m0); - break; - } - - /* - * Get the next available transmit descriptor. - */ - nexttx = MEC_NEXTTX(sc->sc_txlast); - txd = &sc->sc_txdesc[nexttx]; - txs = &sc->sc_txsoft[nexttx]; - - buflen = 0; - bufoff = 0; - txdaddr = 0; /* XXX gcc */ - txdlen = 0; /* XXX gcc */ - - len = m0->m_pkthdr.len; - - DPRINTF(MEC_DEBUG_START, - ("mec_start: len = %d, nexttx = %d\n", len, nexttx)); - - ifq_deq_commit(&ifp->if_snd, m0); - if (len < ETHER_PAD_LEN) { - /* - * I don't know if MEC chip does auto padding, - * so if the packet is small enough, - * just copy it to the buffer in txdesc. - * Maybe this is the simple way. - */ - DPRINTF(MEC_DEBUG_START, ("mec_start: short packet\n")); - - bufoff = MEC_TXD_BUFSTART(ETHER_PAD_LEN); - m_copydata(m0, 0, m0->m_pkthdr.len, - txd->txd_buf + bufoff); - memset(txd->txd_buf + bufoff + len, 0, - ETHER_PAD_LEN - len); - len = buflen = ETHER_PAD_LEN; - - txs->txs_flags = MEC_TXS_TXDBUF | buflen; - } else { - /* - * If the packet won't fit the buffer in txdesc, - * we have to use concatenate pointer to handle it. - * While MEC can handle up to three segments to - * concatenate, MEC requires that both the second and - * third segments have to be 8 byte aligned. - * Since it's unlikely for mbuf clusters, we use - * only the first concatenate pointer. If the packet - * doesn't fit in one DMA segment, allocate new mbuf - * and copy the packet to it. - * - * Besides, if the start address of the first segments - * is not 8 byte aligned, such part have to be copied - * to the txdesc buffer. (XXX see below comments) - */ - DPRINTF(MEC_DEBUG_START, ("mec_start: long packet\n")); - - dmamap = txs->txs_dmamap; - if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, - BUS_DMA_WRITE | BUS_DMA_NOWAIT) != 0) { - struct mbuf *m; - - DPRINTF(MEC_DEBUG_START, - ("mec_start: re-allocating mbuf\n")); - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) { - printf("%s: unable to allocate " - "TX mbuf\n", sc->sc_dev.dv_xname); - break; - } - if (len > (MHLEN - ETHER_ALIGN)) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - printf("%s: unable to allocate " - "TX cluster\n", - sc->sc_dev.dv_xname); - m_freem(m); - break; - } - } - /* - * Each packet has the Ethernet header, so - * in many cases the header isn't 4-byte aligned - * and data after the header is 4-byte aligned. - * Thus adding 2-byte offset before copying to - * new mbuf avoids unaligned copy and this may - * improve performance. - * As noted above, unaligned part has to be - * copied to txdesc buffer so this may cause - * extra copy ops, but for now MEC always - * requires some data in txdesc buffer, - * so we always have to copy some data anyway. - */ - m->m_data += ETHER_ALIGN; - m_copydata(m0, 0, len, mtod(m, caddr_t)); - m->m_pkthdr.len = m->m_len = len; - m_freem(m0); - m0 = m; - error = bus_dmamap_load_mbuf(sc->sc_dmat, - dmamap, m, BUS_DMA_WRITE | BUS_DMA_NOWAIT); - if (error) { - printf("%s: unable to load TX buffer, " - "error = %d\n", - sc->sc_dev.dv_xname, error); - m_freem(m); - break; - } - } - - /* Handle unaligned part. */ - txdaddr = MEC_TXD_ROUNDUP(dmamap->dm_segs[0].ds_addr); - txs->txs_flags = MEC_TXS_TXDPTR1; - unaligned = - dmamap->dm_segs[0].ds_addr & (MEC_TXD_ALIGN - 1); - DPRINTF(MEC_DEBUG_START, - ("mec_start: ds_addr = 0x%x, unaligned = %d\n", - (u_int)dmamap->dm_segs[0].ds_addr, unaligned)); - if (unaligned != 0) { - buflen = MEC_TXD_ALIGN - unaligned; - bufoff = MEC_TXD_BUFSTART(buflen); - DPRINTF(MEC_DEBUG_START, - ("mec_start: unaligned, " - "buflen = %d, bufoff = %d\n", - buflen, bufoff)); - memcpy(txd->txd_buf + bufoff, - mtod(m0, caddr_t), buflen); - txs->txs_flags |= MEC_TXS_TXDBUF | buflen; - } -#if 1 - else { - /* - * XXX needs hardware info XXX - * It seems MEC always requires some data - * in txd_buf[] even if buffer is - * 8-byte aligned otherwise DMA abort error - * occurs later... - */ - buflen = MEC_TXD_ALIGN; - bufoff = MEC_TXD_BUFSTART(buflen); - memcpy(txd->txd_buf + bufoff, - mtod(m0, caddr_t), buflen); - DPRINTF(MEC_DEBUG_START, - ("mec_start: aligned, " - "buflen = %d, bufoff = %d\n", - buflen, bufoff)); - txs->txs_flags |= MEC_TXS_TXDBUF | buflen; - txdaddr += MEC_TXD_ALIGN; - } -#endif - txdlen = len - buflen; - DPRINTF(MEC_DEBUG_START, - ("mec_start: txdaddr = 0x%llx, txdlen = %d\n", - txdaddr, txdlen)); - - /* - * Sync the DMA map for TX mbuf. - * - * XXX unaligned part doesn't have to be sync'ed, - * but it's harmless... - */ - bus_dmamap_sync(sc->sc_dmat, dmamap, 0, - dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE); - } - -#if NBPFILTER > 0 - /* - * Pass packet to bpf if there is a listener. - */ - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT); -#endif - - /* - * Setup the transmit descriptor. - */ - - /* TXINT bit will be set later on the last packet. */ - txd->txd_cmd = (len - 1); - /* But also set TXINT bit on a half of TXDESC. */ - if (sc->sc_txpending == (MEC_NTXDESC / 2)) - txd->txd_cmd |= MEC_TXCMD_TXINT; - - if (txs->txs_flags & MEC_TXS_TXDBUF) - txd->txd_cmd |= TXCMD_BUFSTART(MEC_TXDESCSIZE - buflen); - if (txs->txs_flags & MEC_TXS_TXDPTR1) { - txd->txd_cmd |= MEC_TXCMD_PTR1; - txd->txd_ptr[0] = TXPTR_LEN(txdlen - 1) | txdaddr; - /* - * Store a pointer to the packet so we can - * free it later. - */ - txs->txs_mbuf = m0; - } else { - txd->txd_ptr[0] = 0; - /* - * In this case all data are copied to buffer in txdesc, - * we can free TX mbuf here. - */ - m_freem(m0); - } - - DPRINTF(MEC_DEBUG_START, - ("mec_start: txd_cmd = 0x%llx, txd_ptr = 0x%llx\n", - txd->txd_cmd, txd->txd_ptr[0])); - DPRINTF(MEC_DEBUG_START, - ("mec_start: len = %d (0x%04x), buflen = %d (0x%02x)\n", - len, len, buflen, buflen)); - - /* Sync TX descriptor. */ - MEC_TXDESCSYNC(sc, nexttx, - BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - - /* Advance the TX pointer. */ - sc->sc_txpending++; - sc->sc_txlast = nexttx; - } - - if (sc->sc_txpending == MEC_NTXDESC) { - /* No more slots; notify upper layer. */ - ifq_set_oactive(&ifp->if_snd); - } - - if (sc->sc_txpending != opending) { - /* - * Cause a TX interrupt to happen on the last packet - * we enqueued. - */ - sc->sc_txdesc[sc->sc_txlast].txd_cmd |= MEC_TXCMD_TXINT; - MEC_TXCMDSYNC(sc, sc->sc_txlast, - BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - - /* Start TX. */ - bus_space_write_8(st, sh, MEC_TX_RING_PTR, - MEC_NEXTTX(sc->sc_txlast)); - - /* - * If the transmitter was idle, - * reset the txdirty pointer and re-enable TX interrupt. - */ - if (opending == 0) { - sc->sc_txdirty = firsttx; - bus_space_write_8(st, sh, MEC_TX_ALIAS, - MEC_TX_ALIAS_INT_ENABLE); - } - - /* Set a watchdog timer in case the chip flakes out. */ - ifp->if_timer = 5; - } -} - -void -mec_stop(struct ifnet *ifp) -{ - struct mec_softc *sc = ifp->if_softc; - struct mec_txsoft *txs; - int i; - - DPRINTF(MEC_DEBUG_STOP, ("mec_stop\n")); - - ifp->if_timer = 0; - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - timeout_del(&sc->sc_tick_ch); - mii_down(&sc->sc_mii); - - /* Disable DMA. */ - bus_space_write_8(sc->sc_st, sc->sc_sh, MEC_DMA_CONTROL, 0); - - /* Release any TX buffers. */ - for (i = 0; i < MEC_NTXDESC; i++) { - txs = &sc->sc_txsoft[i]; - if ((txs->txs_flags & MEC_TXS_TXDPTR1) != 0) { - bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); - m_freem(txs->txs_mbuf); - txs->txs_mbuf = NULL; - } - } -} - -int -mec_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct mec_softc *sc = ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - int s, error = 0; - - s = splnet(); - - switch (cmd) { - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - if (!(ifp->if_flags & IFF_RUNNING)) - mec_init(ifp); - break; - - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING) - error = ENETRESET; - else - mec_init(ifp); - } else { - if (ifp->if_flags & IFF_RUNNING) - mec_stop(ifp); - } - break; - - case SIOCSIFMEDIA: - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd); - break; - - default: - error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); - } - - if (error == ENETRESET) { - if (ifp->if_flags & IFF_RUNNING) - mec_iff(sc); - error = 0; - } - - splx(s); - return error; -} - -void -mec_watchdog(struct ifnet *ifp) -{ - struct mec_softc *sc = ifp->if_softc; - - printf("%s: device timeout\n", sc->sc_dev.dv_xname); - ifp->if_oerrors++; - - mec_init(ifp); -} - -void -mec_tick(void *arg) -{ - struct mec_softc *sc = arg; - int s; - - s = splnet(); - mii_tick(&sc->sc_mii); - splx(s); - - timeout_add_sec(&sc->sc_tick_ch, 1); -} - -void -mec_iff(struct mec_softc *sc) -{ - struct arpcom *ac = &sc->sc_ac; - struct ifnet *ifp = &sc->sc_ac.ac_if; - struct ether_multi *enm; - struct ether_multistep step; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - uint64_t mchash = 0; - uint32_t control, hash; - - control = bus_space_read_8(st, sh, MEC_MAC_CONTROL); - control &= ~MEC_MAC_FILTER_MASK; - ifp->if_flags &= ~IFF_ALLMULTI; - - if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { - ifp->if_flags |= IFF_ALLMULTI; - if (ifp->if_flags & IFF_PROMISC) - control |= MEC_MAC_FILTER_PROMISC; - else - control |= MEC_MAC_FILTER_ALLMULTI; - mchash = 0xffffffffffffffffULL; - } else { - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - hash = ether_crc32_be(enm->enm_addrlo, - ETHER_ADDR_LEN) >> 26; - - mchash |= 1 << hash; - - ETHER_NEXT_MULTI(step, enm); - } - - if (ac->ac_multicnt > 0) - control |= MEC_MAC_FILTER_MATCHMULTI; - } - - bus_space_write_8(st, sh, MEC_MULTICAST, mchash); - bus_space_write_8(st, sh, MEC_MAC_CONTROL, control); -} - -int -mec_intr(void *arg) -{ - struct mec_softc *sc = arg; - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - struct ifnet *ifp = &sc->sc_ac.ac_if; - uint32_t statreg, statack, dmac; - int handled, sent; - - DPRINTF(MEC_DEBUG_INTR, ("mec_intr: called\n")); - - handled = sent = 0; - - for (;;) { - statreg = bus_space_read_8(st, sh, MEC_INT_STATUS); - - DPRINTF(MEC_DEBUG_INTR, - ("mec_intr: INT_STAT = 0x%x\n", statreg)); - - statack = statreg & MEC_INT_STATUS_MASK; - if (statack == 0) - break; - bus_space_write_8(st, sh, MEC_INT_STATUS, statack); - - handled = 1; - - if (statack & - (MEC_INT_RX_THRESHOLD | - MEC_INT_RX_FIFO_UNDERFLOW)) { - mec_rxintr(sc, statreg); - } - - dmac = bus_space_read_8(st, sh, MEC_DMA_CONTROL); - DPRINTF(MEC_DEBUG_INTR, - ("mec_intr: DMA_CONT = 0x%x\n", dmac)); - - if (statack & - (MEC_INT_TX_EMPTY | - MEC_INT_TX_PACKET_SENT | - MEC_INT_TX_ABORT)) { - mec_txintr(sc, statreg); - sent = 1; - } - - if (statack & - (MEC_INT_TX_LINK_FAIL | - MEC_INT_TX_MEM_ERROR | - MEC_INT_TX_ABORT | - MEC_INT_RX_DMA_UNDERFLOW)) { - printf("%s: mec_intr: interrupt status = 0x%x\n", - sc->sc_dev.dv_xname, statreg); - } - } - - if (sent) { - /* Try to get more packets going. */ - mec_start(ifp); - } - - return handled; -} - -void -mec_rxintr(struct mec_softc *sc, uint32_t stat) -{ - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - struct ifnet *ifp = &sc->sc_ac.ac_if; - struct mbuf_list ml = MBUF_LIST_INITIALIZER(); - struct mbuf *m; - struct mec_rxdesc *rxd; - uint64_t rxstat; - u_int len; - int i, last; - - DPRINTF(MEC_DEBUG_RXINTR, ("mec_rxintr: called\n")); - - bus_space_write_8(st, sh, MEC_RX_ALIAS, 0); - - last = (stat & MEC_INT_RX_MCL_FIFO_ALIAS) >> 8; - /* XXX does alias count mod 32 even if 16 descs are set up? */ - last &= MEC_NRXDESC_MASK; - - if (stat & MEC_INT_RX_FIFO_UNDERFLOW) - last = (last - 1) & MEC_NRXDESC_MASK; - - DPRINTF(MEC_DEBUG_RXINTR, ("mec_rxintr: rxptr %d last %d\n", - sc->sc_rxptr, last)); - for (i = sc->sc_rxptr; i != last; i = MEC_NEXTRX(i)) { - - MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_POSTREAD); - rxd = &sc->sc_rxdesc[i]; - rxstat = rxd->rxd_stat; - - DPRINTF(MEC_DEBUG_RXINTR, - ("mec_rxintr: rxstat = 0x%llx, rxptr = %d\n", - rxstat, i)); - DPRINTF(MEC_DEBUG_RXINTR, ("mec_rxintr: rxfifo = 0x%x\n", - (u_int)bus_space_read_8(st, sh, MEC_RX_FIFO))); - - if ((rxstat & MEC_RXSTAT_RECEIVED) == 0) { - /* Status not received but FIFO counted? Drop it! */ - goto dropit; - } - - len = rxstat & MEC_RXSTAT_LEN; - - if (len < ETHER_MIN_LEN || - len > ETHER_MAX_LEN) { - /* Invalid length packet; drop it. */ - DPRINTF(MEC_DEBUG_RXINTR, - ("mec_rxintr: wrong packet\n")); - dropit: - ifp->if_ierrors++; - rxd->rxd_stat = 0; - MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); - bus_space_write_8(st, sh, MEC_MCL_RX_FIFO, - MEC_CDRXADDR(sc, i)); - continue; - } - - if (rxstat & - (MEC_RXSTAT_BADPACKET | - MEC_RXSTAT_LONGEVENT | - MEC_RXSTAT_INVALID | - MEC_RXSTAT_CRCERROR | - MEC_RXSTAT_VIOLATION)) { - printf("%s: mec_rxintr: status = 0x%llx\n", - sc->sc_dev.dv_xname, rxstat); - goto dropit; - } - - /* - * Now allocate an mbuf (and possibly a cluster) to hold - * the received packet. - */ - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) { - printf("%s: unable to allocate RX mbuf\n", - sc->sc_dev.dv_xname); - goto dropit; - } - if (len > (MHLEN - ETHER_ALIGN)) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - printf("%s: unable to allocate RX cluster\n", - sc->sc_dev.dv_xname); - m_freem(m); - m = NULL; - goto dropit; - } - } - - /* - * Note MEC chip seems to insert 2 byte padding at the start of - * RX buffer, but we copy whole buffer to avoid unaligned copy. - */ - MEC_RXBUFSYNC(sc, i, len + ETHER_ALIGN, BUS_DMASYNC_POSTREAD); - memcpy(mtod(m, caddr_t), rxd->rxd_buf, - ETHER_ALIGN + len - ETHER_CRC_LEN); - MEC_RXBUFSYNC(sc, i, ETHER_MAX_LEN, BUS_DMASYNC_PREREAD); - m->m_data += ETHER_ALIGN; - - /* Put RX buffer into FIFO again. */ - rxd->rxd_stat = 0; - MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD); - bus_space_write_8(st, sh, MEC_MCL_RX_FIFO, MEC_CDRXADDR(sc, i)); - - m->m_pkthdr.len = m->m_len = len - ETHER_CRC_LEN; - - ml_enqueue(&ml, m); - } - - /* Update RX pointer. */ - sc->sc_rxptr = i; - - bus_space_write_8(st, sh, MEC_RX_ALIAS, - (MEC_NRXDESC << MEC_DMA_RX_INT_THRESH_SHIFT) | - MEC_DMA_RX_INT_ENABLE); - - if_input(ifp, &ml); -} - -void -mec_txintr(struct mec_softc *sc, uint32_t stat) -{ - struct ifnet *ifp = &sc->sc_ac.ac_if; - struct mec_txdesc *txd; - struct mec_txsoft *txs; - bus_dmamap_t dmamap; - uint64_t txstat; - int i, last; - u_int col; - - ifq_clr_oactive(&ifp->if_snd); - - DPRINTF(MEC_DEBUG_TXINTR, ("mec_txintr: called\n")); - - bus_space_write_8(sc->sc_st, sc->sc_sh, MEC_TX_ALIAS, 0); - last = (stat & MEC_INT_TX_RING_BUFFER_ALIAS) >> 16; - - DPRINTF(MEC_DEBUG_TXINTR, ("mec_txintr: dirty %d last %d\n", - sc->sc_txdirty, last)); - for (i = sc->sc_txdirty; i != last && sc->sc_txpending != 0; - i = MEC_NEXTTX(i), sc->sc_txpending--) { - txd = &sc->sc_txdesc[i]; - - MEC_TXDESCSYNC(sc, i, - BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - - txstat = txd->txd_stat; - DPRINTF(MEC_DEBUG_TXINTR, - ("mec_txintr: dirty = %d, txstat = 0x%llx\n", - i, txstat)); - if ((txstat & MEC_TXSTAT_SENT) == 0) { - MEC_TXCMDSYNC(sc, i, BUS_DMASYNC_PREREAD); - break; - } - - txs = &sc->sc_txsoft[i]; - if ((txs->txs_flags & MEC_TXS_TXDPTR1) != 0) { - dmamap = txs->txs_dmamap; - bus_dmamap_sync(sc->sc_dmat, dmamap, 0, - dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->sc_dmat, dmamap); - m_freem(txs->txs_mbuf); - txs->txs_mbuf = NULL; - } - - if ((txstat & MEC_TXSTAT_SUCCESS) == 0) { - printf("%s: TX error: txstat = 0x%llx\n", - sc->sc_dev.dv_xname, txstat); - ifp->if_oerrors++; - } else { - col = (txstat & MEC_TXSTAT_COLCNT) >> - MEC_TXSTAT_COLCNT_SHIFT; - ifp->if_collisions += col; - } - } - - /* Update the dirty TX buffer pointer. */ - sc->sc_txdirty = i; - DPRINTF(MEC_DEBUG_INTR, - ("mec_txintr: sc_txdirty = %2d, sc_txpending = %2d\n", - sc->sc_txdirty, sc->sc_txpending)); - - /* Cancel the watchdog timer if there are no pending TX packets. */ - if (sc->sc_txpending == 0) - ifp->if_timer = 0; - else if (!(stat & MEC_INT_TX_EMPTY)) - bus_space_write_8(sc->sc_st, sc->sc_sh, MEC_TX_ALIAS, - MEC_TX_ALIAS_INT_ENABLE); -} diff --git a/sys/arch/sgi/dev/if_mecreg.h b/sys/arch/sgi/dev/if_mecreg.h deleted file mode 100644 index 6cc7933a68d..00000000000 --- a/sys/arch/sgi/dev/if_mecreg.h +++ /dev/null @@ -1,149 +0,0 @@ -/* $OpenBSD: if_mecreg.h,v 1.3 2018/12/10 05:42:34 visa Exp $ */ -/* $NetBSD: if_mecreg.h,v 1.2 2004/07/11 03:13:04 tsutsui Exp $ */ - -/* - * Copyright (c) 2001 Christopher Sekiya - * Copyright (c) 2000 Soren S. Jorvang - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the - * NetBSD Project. See http://www.NetBSD.org/ for - * information about NetBSD. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * MACE MAC110 Ethernet register definitions - */ - -#define MEC_MAC_CONTROL 0x00 -#define MEC_MAC_CORE_RESET 0x0000000000000001 /* reset signal */ -#define MEC_MAC_FULL_DUPLEX 0x0000000000000002 /* 1 to enable */ -#define MEC_MAC_INT_LOOPBACK 0x0000000000000004 /* 0 = normal op */ -#define MEC_MAC_SPEED_SELECT 0x0000000000000008 /* 0/1 10/100 */ -#define MEC_MAC_MII_SELECT 0x0000000000000010 /* MII/SIA */ -#define MEC_MAC_FILTER_MASK 0x0000000000000060 -#define MEC_MAC_FILTER_STATION 0x0000000000000000 -#define MEC_MAC_FILTER_MATCHMULTI 0x0000000000000020 -#define MEC_MAC_FILTER_ALLMULTI 0x0000000000000040 -#define MEC_MAC_FILTER_PROMISC 0x0000000000000060 -#define MEC_MAC_LINK_FAILURE 0x0000000000000080 -#define MEC_MAC_IPGT 0x0000000000007f00 /* interpacket gap */ -#define MEC_MAC_IPGT_SHIFT 8 -#define MEC_MAC_IPGR1 0x00000000003f8000 -#define MEC_MAC_IPGR1_SHIFT 15 -#define MEC_MAC_IPGR2 0x000000001fc00000 -#define MEC_MAC_IPGR2_SHIFT 22 -#define MEC_MAC_REVISION 0x00000000e0000000 -#define MEC_MAC_REVISION_SHIFT 29 - -#define MEC_MAC_IPG_DEFAULT \ - (21 << MEC_MAC_IPGT_SHIFT) | \ - (17 << MEC_MAC_IPGR1_SHIFT) | \ - (11 << MEC_MAC_IPGR2_SHIFT) - -#define MEC_INT_STATUS 0x08 -#define MEC_INT_STATUS_MASK 0x00000000000000ff -#define MEC_INT_TX_EMPTY 0x0000000000000001 -#define MEC_INT_TX_PACKET_SENT 0x0000000000000002 -#define MEC_INT_TX_LINK_FAIL 0x0000000000000004 -#define MEC_INT_TX_MEM_ERROR 0x0000000000000008 -#define MEC_INT_TX_ABORT 0x0000000000000010 -#define MEC_INT_RX_THRESHOLD 0x0000000000000020 -#define MEC_INT_RX_FIFO_UNDERFLOW 0x0000000000000040 -#define MEC_INT_RX_DMA_UNDERFLOW 0x0000000000000080 -#define MEC_INT_RX_MCL_FIFO_ALIAS 0x0000000000001f00 -#define MEC_INT_TX_RING_BUFFER_ALIAS 0x0000000001ff0000 -#define MEC_INT_RX_SEQUENCE_NUMBER 0x000000003e000000 -#define MEC_INT_MCAST_HASH_OUTPUT 0x0000000040000000 - -#define MEC_DMA_CONTROL 0x10 -#define MEC_DMA_TX_INT_ENABLE 0x0000000000000001 -#define MEC_DMA_TX_DMA_ENABLE 0x0000000000000002 -#define MEC_DMA_TX_RING_SIZE_MASK 0x000000000000000c -#define MEC_DMA_RX_INT_THRESHOLD 0x00000000000001f0 -#define MEC_DMA_RX_INT_THRESH_SHIFT 4 -#define MEC_DMA_RX_INT_ENABLE 0x0000000000000200 -#define MEC_DMA_RX_RUNT 0x0000000000000400 -#define MEC_DMA_RX_PACKET_GATHER 0x0000000000000800 -#define MEC_DMA_RX_DMA_OFFSET 0x0000000000007000 -#define MEC_DMA_RX_DMA_OFFSET_SHIFT 12 -#define MEC_DMA_RX_DMA_ENABLE 0x0000000000008000 - -#define MEC_TIMER 0x18 -#define MEC_TX_ALIAS 0x20 -#define MEC_TX_ALIAS_INT_ENABLE 0x0000000000000001 - -#define MEC_RX_ALIAS 0x28 -#define MEC_RX_ALIAS_INT_ENABLE 0x0000000000000200 -#define MEC_RX_ALIAS_INT_THRESHOLD 0x00000000000001f0 - -#define MEC_TX_RING_PTR 0x30 -#define MEC_TX_RING_WRITE_PTR 0x00000000000001ff -#define MEC_TX_RING_READ_PTR 0x0000000001ff0000 -#define MEC_TX_RING_PTR_ALIAS 0x38 - -#define MEC_RX_FIFO 0x40 -#define MEC_RX_FIFO_ELEMENT_COUNT 0x000000000000001f -#define MEC_RX_FIFO_READ_PTR 0x0000000000000f00 -#define MEC_RX_FIFO_GEN_NUMBER 0x0000000000001000 -#define MEC_RX_FIFO_WRITE_PTR 0x00000000000f0000 -#define MEC_RX_FIFO_GEN_NUMBER_2 0x0000000000100000 - -#define MEC_RX_FIFO_ALIAS1 0x48 -#define MEC_RX_FIFO_ALIAS2 0x50 -#define MEC_TX_VECTOR 0x58 -#define MEC_IRQ_VECTOR 0x58 - -#define MEC_PHY_DATA 0x60 -#define MEC_PHY_DATA_BUSY 0x00010000 -#define MEC_PHY_DATA_VALUE 0x0000ffff - -#define MEC_PHY_ADDRESS 0x68 -#define MEC_PHY_ADDR_REGISTER 0x0000001f -#define MEC_PHY_ADDR_DEVICE 0x000003e0 -#define MEC_PHY_ADDR_DEVSHIFT 5 - -#define MEC_PHY_READ_INITIATE 0x70 -#define MEC_PHY_BACKOFF 0x78 - -#define MEC_STATION 0xa0 -#define MEC_STATION_ALT 0xa8 -#define MEC_STATION_MASK 0x0000ffffffffffffULL - -#define MEC_MULTICAST 0xb0 -#define MEC_TX_RING_BASE 0xb8 -#define MEC_TX_PKT1_CMD_1 0xc0 -#define MEC_TX_PKT1_BUFFER_1 0xc8 -#define MEC_TX_PKT1_BUFFER_2 0xd0 -#define MEC_TX_PKT1_BUFFER_3 0xd8 -#define MEC_TX_PKT2_CMD_1 0xe0 -#define MEC_TX_PKT2_BUFFER_1 0xe8 -#define MEC_TX_PKT2_BUFFER_2 0xf0 -#define MEC_TX_PKT2_BUFFER_3 0xf8 - -#define MEC_MCL_RX_FIFO 0x100 - -#define MEC_NREGS 0x200 diff --git a/sys/arch/sgi/dev/impact.c b/sys/arch/sgi/dev/impact.c deleted file mode 100644 index 9fc5243cf81..00000000000 --- a/sys/arch/sgi/dev/impact.c +++ /dev/null @@ -1,776 +0,0 @@ -/* $OpenBSD: impact.c,v 1.12 2020/06/06 10:52:30 visa Exp $ */ - -/* - * Copyright (c) 2010, 2012 Miodrag Vallat. - * Copyright (c) 2009, 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. - */ - -/* - * Driver for the SGI Impact and ImpactSR graphics board. - */ - -/* - * The details regarding the design and operation of this hardware, along with - * the necessary magic numbers, are only available thanks to the reverse - * engineering work undertaken by Stanislaw Skowronek <skylark@linux-mips.org>. - * - * Differences between ImpactSR and Impact researched by Peter Fuerst - * <post@pfrst.de>. - */ - -/* - * This driver currently lacks support for the HQ3 and HQ4 DMA engines, which - * could be used to speed up rasops `copy' operations a lot by doing - * framebuffer to memory, then memory to framebuffer operations. - * - * Of course, in an ideal world, these operations would be done with - * framebuffer to framebuffer operations, but according to Skowronek, these - * operations are not reliable and IRIX' Xsgi X server does not even try to - * use them. - * - * Thus this driver currently implements rasops `copy' operations by repainting - * affected areas with PIO routines. This is unfortunately slower than DMA, - * but this will work until I have more time to spend on this. -- miod - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/device.h> -#include <sys/malloc.h> - -#include <machine/bus.h> - -#include <sgi/dev/gl.h> -#include <sgi/dev/impactreg.h> -#include <sgi/dev/impactvar.h> - -#include <dev/wscons/wsconsio.h> -#include <dev/wscons/wsdisplayvar.h> -#include <dev/rasops/rasops.h> - -struct cfdriver impact_cd = { - NULL, "impact", DV_DULL, -}; - -#define IMPACT_WIDTH 1280 -#define IMPACT_HEIGHT 1024 -#define IMPACT_DEPTH 32 - -struct impact_screen { - struct rasops_info ri; - uint32_t defattr; - struct wsdisplay_charcell *bs; - - struct impact_softc *sc; - int has_hq4; - - bus_addr_t fifo_status; - bus_addr_t cfifo; - - bus_space_tag_t iot; - bus_space_handle_t ioh; - - struct wsscreen_descr wsd; - struct wsscreen_list wsl; - struct wsscreen_descr *scrlist[1]; -}; - -static inline void - impact_cmd_fifo_write(struct impact_screen *, uint64_t, uint32_t, int); -int impact_cmd_fifo_wait(struct impact_screen *); - -void impact_setup(struct impact_screen *, int); -int impact_init_screen(struct impact_screen *); - -/* - * Hardware acceleration (sort of) for rasops. - */ -void impact_rop(struct impact_screen *, int, int, int, int, int, u_int); -void impact_fillrect(struct impact_screen *, int, int, int, int, u_int); -int impact_do_cursor(struct rasops_info *); -int impact_putchar(void *, int, int, u_int, uint32_t); -int impact_copycols(void *, int, int, int, int); -int impact_erasecols(void *, int, int, int, uint32_t); -int impact_copyrows(void *, int, int, int); -int impact_eraserows(void *, int, int, uint32_t); - -/* - * Interfaces for wscons. - */ -int impact_ioctl(void *, u_long, caddr_t, int, struct proc *); -paddr_t impact_mmap(void *, off_t, int); -int impact_alloc_screen(void *, const struct wsscreen_descr *, void **, - int *, int *, uint32_t *); -void impact_free_screen(void *, void *); -int impact_show_screen(void *, void *, int, void (*)(void *, int, int), - void *); -int impact_load_font(void *, void *, struct wsdisplay_font *); -int impact_list_font(void *, struct wsdisplay_font *); - -static struct impact_screen impact_cons; - -struct wsdisplay_accessops impact_accessops = { - .ioctl = impact_ioctl, - .mmap = impact_mmap, - .alloc_screen = impact_alloc_screen, - .free_screen = impact_free_screen, - .show_screen = impact_show_screen, - .load_font = impact_load_font, - .list_font = impact_list_font -}; - -int -impact_attach_common(struct impact_softc *sc, bus_space_tag_t iot, - bus_space_handle_t ioh, int console, int has_hq4) -{ - struct wsemuldisplaydev_attach_args waa; - struct impact_screen *scr; - - if (console) { - /* - * Setup has already been done via impact_cnattach(). - */ - scr = &impact_cons; - scr->sc = sc; - sc->curscr = scr; - sc->console = 1; - } else { - /* - * Setup screen data. - */ - scr = malloc(sizeof(struct impact_screen), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (scr == NULL) { - printf("failed to allocate screen memory!\n"); - return ENOMEM; - } - - scr->iot = iot; - scr->ioh = ioh; - scr->sc = sc; - sc->curscr = scr; - - /* Setup hardware and clear screen. */ - impact_setup(scr, has_hq4); - if (impact_init_screen(scr) != 0) { - printf("failed to allocate memory\n"); - free(scr, M_DEVBUF, sizeof *scr); - return ENOMEM; - } - } - - scr->scrlist[0] = &scr->wsd; - scr->wsl.nscreens = 1; - scr->wsl.screens = (const struct wsscreen_descr **)scr->scrlist; - - waa.console = sc->console; - waa.scrdata = &scr->wsl; - waa.accessops = &impact_accessops; - waa.accesscookie = scr; - waa.defaultscreens = 0; - - config_found(&sc->sc_dev, &waa, wsemuldisplaydevprint); - - return 0; -} - -int -impact_init_screen(struct impact_screen *scr) -{ - struct rasops_info *ri = &scr->ri; - int i; - uint32_t c, r, g, b; - - bzero(ri, sizeof(struct rasops_info)); - - ri->ri_flg = RI_CENTER | RI_FULLCLEAR; - ri->ri_depth = IMPACT_DEPTH; - ri->ri_width = IMPACT_WIDTH; - ri->ri_height = IMPACT_HEIGHT; - ri->ri_stride = IMPACT_WIDTH * IMPACT_DEPTH / 8; - - rasops_init(ri, 160, 160); - - /* - * Allocate backing store to remember character cells, to - * be able to fulfill scrolling requests. - */ - if (scr->bs == NULL) { - scr->bs = mallocarray(ri->ri_rows, - ri->ri_cols * sizeof(struct wsdisplay_charcell), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (scr->bs == NULL) - return ENOMEM; - } - - ri->ri_hw = scr; - - ri->ri_ops.putchar = impact_putchar; - ri->ri_do_cursor = impact_do_cursor; - ri->ri_ops.copyrows = impact_copyrows; - ri->ri_ops.copycols = impact_copycols; - ri->ri_ops.eraserows = impact_eraserows; - ri->ri_ops.erasecols = impact_erasecols; - - /* - * Slightly rework the colormap. impact_putchar() will use a 4:8:4 - * colormap for the background color instead of the 8:8:8 colormap - * used everywhere else, so we need to make sure the low 4 bits of - * all red and blue entries are zero, at least for the entries - * used in emulation mode. - */ - for (i = 0; i < 16; i++) { - c = ri->ri_devcmap[i]; - /* this relies upon the default ri->ri_[bgr]{num,pos} values */ - r = c & 0x000000ff; - g = c & 0x0000ff00; - b = c & 0x00ff0000; - - if (r < (0xf0 << 0) && (r & (0x08 << 0)) != 0) - r += 0x10 << 0; - r &= 0xf0 << 0; - if (b < (0xf0 << 16) && (b & (0x08 << 16)) != 0) - b += 0x10 << 16; - b &= 0xf0 << 16; - - ri->ri_devcmap[i] = b | g | r; - } - - /* clear display */ - impact_fillrect(scr, 0, 0, ri->ri_width, ri->ri_height, - ri->ri_devcmap[WSCOL_BLACK]); - - strlcpy(scr->wsd.name, "std", sizeof(scr->wsd.name)); - scr->wsd.ncols = ri->ri_cols; - scr->wsd.nrows = ri->ri_rows; - scr->wsd.textops = &ri->ri_ops; - scr->wsd.fontwidth = ri->ri_font->fontwidth; - scr->wsd.fontheight = ri->ri_font->fontheight; - scr->wsd.capabilities = ri->ri_caps; - - return 0; -} - -/* - * Hardware initialization. - */ - -void -impact_setup(struct impact_screen *scr, int has_hq4) -{ - bus_addr_t xmap_base; - bus_addr_t vc3_base; - - scr->has_hq4 = has_hq4; - - if (has_hq4) { - xmap_base = IMPACTSR_XMAP_BASE; - vc3_base = IMPACTSR_VC3_BASE; - scr->fifo_status = IMPACTSR_FIFOSTATUS; - scr->cfifo = IMPACTSR_CFIFO; - } else { - xmap_base = IMPACT_XMAP_BASE; - vc3_base = IMPACT_VC3_BASE; - scr->fifo_status = IMPACT_FIFOSTATUS; - scr->cfifo = IMPACT_CFIFO; - } - - if (has_hq4) { - /* HQ4 initialization */ - bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_CFIFO_HW, - 0x00000047); - bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_CFIFO_LW, - 0x00000014); - bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_CFIFO_DELAY, - 0x00000064); - bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_DFIFO_HW, - 0x00000040); - bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_DFIFO_LW, - 0x00000010); - bus_space_write_4(scr->iot, scr->ioh, IMPACTSR_DFIFO_DELAY, - 0x00000000); - } else { - /* HQ3 initialization */ - bus_space_write_4(scr->iot, scr->ioh, IMPACT_CFIFO_HW, - 0x00000020); - bus_space_write_4(scr->iot, scr->ioh, IMPACT_CFIFO_LW, - 0x00000014); - bus_space_write_4(scr->iot, scr->ioh, IMPACT_CFIFO_DELAY, - 0x00000064); - bus_space_write_4(scr->iot, scr->ioh, IMPACT_DFIFO_HW, - 0x00000028); - bus_space_write_4(scr->iot, scr->ioh, IMPACT_DFIFO_LW, - 0x00000014); - bus_space_write_4(scr->iot, scr->ioh, IMPACT_DFIFO_DELAY, - 0x00000fff); - } - - /* VC3 initialization: disable hardware cursor */ - bus_space_write_4(scr->iot, scr->ioh, - vc3_base + IMPACTSR_VC3_INDEXDATA, 0x1d000100); - - /* RSS initialization */ - impact_cmd_fifo_write(scr, IMPACTSR_CMD_COLORMASKLSBSA, 0xffffff, 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_COLORMASKLSBSB, 0xffffff, 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_COLORMASKMSBS, 0, 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_XFRMASKLO, 0xffffff, 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_XFRMASKHI, 0xffffff, 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_DRBPOINTERS, 0xc8240, 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_CONFIG, 0xcac, 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_XYWIN, - IMPACTSR_YXCOORDS(0, 0x3ff), 0); - - /* XMAP initialization */ - bus_space_write_1(scr->iot, scr->ioh, - xmap_base + IMPACTSR_XMAP_PP1SELECT, 0x01); - bus_space_write_1(scr->iot, scr->ioh, - xmap_base + IMPACTSR_XMAP_INDEX, 0x00); - bus_space_write_4(scr->iot, scr->ioh, - xmap_base + IMPACTSR_XMAP_MAIN_MODE, 0x000007a4); -} - -/* - * Write to the command FIFO. - */ -static inline void -impact_cmd_fifo_write(struct impact_screen *scr, uint64_t reg, uint32_t val, - int exec) -{ - uint64_t cmd; - - cmd = IMPACTSR_CFIFO_WRITE | (reg << IMPACTSR_CFIFO_REG_SHIFT); - if (exec) - cmd |= IMPACTSR_CFIFO_EXEC; - bus_space_write_8(scr->iot, scr->ioh, scr->cfifo, cmd | val); -} - -/* - * Wait until the command FIFO is empty. - */ -int -impact_cmd_fifo_wait(struct impact_screen *scr) -{ - u_int32_t val, timeout = 1000000; -#ifdef DIAGNOSTIC - struct impact_softc *sc = scr->sc; -#endif - - val = bus_space_read_4(scr->iot, scr->ioh, scr->fifo_status); - while ((val & IMPACTSR_FIFO_MASK) != 0) { - delay(1); - if (--timeout == 0) { -#ifdef DIAGNOSTIC - if (sc != NULL && sc->console == 0) - printf("%s: timeout waiting for command fifo\n", - sc != NULL ? sc->sc_dev.dv_xname : - impact_cd.cd_name); -#endif - return ETIMEDOUT; - } - val = bus_space_read_4(scr->iot, scr->ioh, scr->fifo_status); - } - - return 0; -} - -/* - * Interfaces for wscons. - */ - -int -impact_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) -{ - struct impact_screen *scr = (struct impact_screen *)v; - struct rasops_info *ri; - struct wsdisplay_fbinfo *fb; - - switch (cmd) { - case WSDISPLAYIO_GTYPE: - *(u_int *)data = WSDISPLAY_TYPE_IMPACT; - break; - case WSDISPLAYIO_GINFO: - fb = (struct wsdisplay_fbinfo *)data; - ri = &scr->ri; - fb->height = ri->ri_height; - fb->width = ri->ri_width; - fb->depth = ri->ri_depth; - fb->cmsize = 0; - break; -#if 0 - case WSDISPLAYIO_LINEBYTES: - ri = &scr->ri; - *(u_int *)data = ri->ri_stride; - break; -#endif - default: - return -1; - } - - return 0; -} - -paddr_t -impact_mmap(void *v, off_t offset, int prot) -{ - if (offset < 0 || (offset & PAGE_MASK) != 0) - return -1; - - return -1; -} - -int -impact_alloc_screen(void *v, const struct wsscreen_descr *type, - void **cookiep, int *curxp, int *curyp, uint32_t *attrp) -{ - struct impact_screen *scr = (struct impact_screen *)v; - struct rasops_info *ri = &scr->ri; - struct impact_softc *sc = (struct impact_softc *)scr->sc; - - /* We do not allow multiple consoles at the moment. */ - if (sc->nscreens > 0) - return ENOMEM; - - sc->nscreens++; - - *cookiep = ri; - *curxp = 0; - *curyp = 0; - ri->ri_ops.pack_attr(ri, 0, 0, 0, &scr->defattr); - *attrp = scr->defattr; - - return 0; -} - -void -impact_free_screen(void *v, void *cookie) -{ - /* We do not allow multiple consoles at the moment. */ -} - -int -impact_show_screen(void *v, void *cookie, int waitok, - void (*cb)(void *, int, int), void *cbarg) -{ - /* We do not allow multiple consoles at the moment. */ - return 0; -} - -int -impact_load_font(void *v, void *emulcookie, struct wsdisplay_font *font) -{ - struct impact_screen *scr = (struct impact_screen *)v; - struct rasops_info *ri = &scr->ri; - - return rasops_load_font(ri, emulcookie, font); -} - -int -impact_list_font(void *v, struct wsdisplay_font *font) -{ - struct impact_screen *scr = (struct impact_screen *)v; - struct rasops_info *ri = &scr->ri; - - return rasops_list_font(ri, font); -} - -/* - * Hardware accelerated functions. - */ - -void -impact_rop(struct impact_screen *scr, int x, int y, int w, int h, int op, - u_int c) -{ - impact_cmd_fifo_wait(scr); - if (op == OPENGL_LOGIC_OP_COPY) - impact_cmd_fifo_write(scr, IMPACTSR_CMD_PP1FILLMODE, - IMPACTSR_PP1FILLMODE(0x6300, op), 0); - else - impact_cmd_fifo_write(scr, IMPACTSR_CMD_PP1FILLMODE, - IMPACTSR_PP1FILLMODE(0x6304, op), 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_FILLMODE, 0, 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_PACKEDCOLOR, - c /* & 0x00ffffff */, 0); /* no mask, ri_devcmap is 24 bit */ - impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYSTARTI, - IMPACTSR_XYCOORDS(x, y), 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYENDI, - IMPACTSR_XYCOORDS(x + w - 1, y + h - 1), 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_IR_ALIAS, 0x18, 1); -} - -void -impact_fillrect(struct impact_screen *scr, int x, int y, int w, int h, u_int c) -{ - impact_rop(scr, x, y, w, h, OPENGL_LOGIC_OP_COPY, c); -} - -int -impact_do_cursor(struct rasops_info *ri) -{ - struct impact_screen *scr = ri->ri_hw; - int y, x, w, h, fg, bg; - - w = ri->ri_font->fontwidth; - h = ri->ri_font->fontheight; - x = ri->ri_xorigin + ri->ri_ccol * w; - y = ri->ri_yorigin + ri->ri_crow * h; - - ri->ri_ops.unpack_attr(ri, scr->defattr, &fg, &bg, NULL); - - impact_rop(scr, x, y, w, h, OPENGL_LOGIC_OP_XOR, ri->ri_devcmap[fg]); - impact_cmd_fifo_wait(scr); - - return 0; -} - -int -impact_putchar(void *cookie, int row, int col, u_int uc, uint32_t attr) -{ - struct rasops_info *ri = cookie; - struct impact_screen *scr = ri->ri_hw; - struct wsdisplay_font *font = ri->ri_font; - int x, y, w, h, bg, fg, ul; - u_int8_t *fontbitmap; - u_int32_t bg484; - u_int chunk; - struct wsdisplay_charcell *cell; - - /* Update backing store. */ - cell = scr->bs + row * ri->ri_cols + col; - cell->uc = uc; - cell->attr = attr; - - w = font->fontwidth; - h = font->fontheight; - x = ri->ri_xorigin + col * w; - y = ri->ri_yorigin + row * h; - - ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, &ul); - - /* Handle spaces with a single fillrect. */ - if ((uc == ' ' || uc == 0) && ul == 0) { - impact_fillrect(scr, x, y, w, h, ri->ri_devcmap[bg]); - return 0; - } - - fontbitmap = (u_int8_t *)(font->data + (uc - font->firstchar) * - ri->ri_fontscale); - - /* - * 1bpp pixel expansion; fast but uses a 4:8:4 background color - * instead of the expected 8:8:8. - */ - bg484 = ri->ri_devcmap[bg]; /* 00BBGGRR */ - bg484 = ((bg484 & 0x00f000f0) >> 4) | /* 00B000R */ - (bg484 & 0x0000ff00); /* 0000GG00 */ - - impact_cmd_fifo_wait(scr); - - impact_cmd_fifo_write(scr, IMPACTSR_CMD_PP1FILLMODE, - IMPACTSR_PP1FILLMODE(0x6300, OPENGL_LOGIC_OP_COPY), 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_FILLMODE, - 0x00400018, 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_PACKEDCOLOR, - ri->ri_devcmap[fg], 0); - - impact_cmd_fifo_write(scr, IMPACTSR_CMD_BKGRD_RG, - (bg484 & 0x0000ffff) << 8, 0); /* 00 GG0R 00 */ - impact_cmd_fifo_write(scr, IMPACTSR_CMD_BKGRD_BA, - (bg484 & 0x00ff0000) >> 8, 0); /* 00 000B 00 */ - - if (w <= 8) { - impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYSTARTI, - IMPACTSR_XYCOORDS(x, y), 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYENDI, - IMPACTSR_XYCOORDS(x + w - 1, y + h - 1), 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_IR_ALIAS, 0x18, 1); - - for (; h != 0; h--) { - chunk = *fontbitmap; - fontbitmap += font->stride; - - /* Handle underline. */ - if (ul && h == 1) - chunk = 0xff; - - impact_cmd_fifo_wait(scr); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_CHAR_H, - chunk << 24, 1); - } - } else { - for (; h != 0; h--) { - chunk = *(u_int16_t *)fontbitmap; - fontbitmap += font->stride; - - /* Handle underline. */ - if (ul && h == 1) - chunk = 0xffff; - - impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYSTARTI, - IMPACTSR_XYCOORDS(x, y), 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_BLOCKXYENDI, - IMPACTSR_XYCOORDS(x + w - 1, y + 1 - 1), 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_IR_ALIAS, - 0x18, 1); - - impact_cmd_fifo_wait(scr); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_CHAR_H, - chunk << 16, 0); - impact_cmd_fifo_write(scr, IMPACTSR_CMD_CHAR_L, - chunk << 24, 1); - - y++; - } - } - - return 0; -} - -int -impact_copycols(void *cookie, int row, int src, int dst, int num) -{ - struct rasops_info *ri = cookie; - struct impact_screen *scr = ri->ri_hw; - struct wsdisplay_charcell *cell; - - /* Copy columns in backing store. */ - cell = scr->bs + row * ri->ri_cols; - memmove(cell + dst, cell + src, - num * sizeof(struct wsdisplay_charcell)); - - /* Repaint affected area */ - cell += dst; - for (; num != 0; num--, dst++, cell++) - impact_putchar(cookie, row, dst, cell->uc, cell->attr); - - return 0; -} - -int -impact_erasecols(void *cookie, int row, int col, int num, uint32_t attr) -{ - struct rasops_info *ri = cookie; - struct impact_screen *scr = ri->ri_hw; - int bg, fg, i; - struct wsdisplay_charcell *cell; - - /* Erase columns in backing store. */ - cell = scr->bs + row * ri->ri_cols + col; - for (i = num; i != 0; i--, cell++) { - cell->uc = 0; - cell->attr = attr; - } - - ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); - - row *= ri->ri_font->fontheight; - col *= ri->ri_font->fontwidth; - num *= ri->ri_font->fontwidth; - - impact_fillrect(scr, ri->ri_xorigin + col, ri->ri_yorigin + row, - num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); - - return 0; -} - -int -impact_copyrows(void *cookie, int src, int dst, int num) -{ - struct rasops_info *ri = cookie; - struct impact_screen *scr = ri->ri_hw; - struct wsdisplay_charcell *cell; - int col; - - /* Copy rows in backing store. */ - cell = scr->bs + dst * ri->ri_cols; - memmove(cell, scr->bs + src * ri->ri_cols, - num * ri->ri_cols * sizeof(struct wsdisplay_charcell)); - - /* Repaint affected area */ - for (; num != 0; num--, dst++) { - for (col = 0; col < ri->ri_cols; col++, cell++) - impact_putchar(cookie, dst, col, cell->uc, cell->attr); - } - - return 0; -} - -int -impact_eraserows(void *cookie, int row, int num, uint32_t attr) -{ - struct rasops_info *ri = cookie; - struct impact_screen *scr = ri->ri_hw; - int x, y, w, bg, fg; - struct wsdisplay_charcell *cell; - - /* Erase rows in backing store. */ - cell = scr->bs + row * ri->ri_cols; - for (x = ri->ri_cols; x != 0; x--, cell++) { - cell->uc = 0; - cell->attr = attr; - } - for (y = 1; y < num; y++) - memmove(scr->bs + (row + y) * ri->ri_cols, - scr->bs + row * ri->ri_cols, - ri->ri_cols * sizeof(struct wsdisplay_charcell)); - - ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); - - if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { - num = ri->ri_height; - x = y = 0; - w = ri->ri_width; - } else { - num *= ri->ri_font->fontheight; - x = ri->ri_xorigin; - y = ri->ri_yorigin + row * ri->ri_font->fontheight; - w = ri->ri_emuwidth; - } - - impact_fillrect(scr, x, y, w, num, ri->ri_devcmap[bg]); - impact_cmd_fifo_wait(scr); - - return 0; -} - -/* - * Console support. - */ - -/* console backing store, worst case font selection */ -static struct wsdisplay_charcell - impact_cons_bs[(IMPACT_WIDTH / 8) * (IMPACT_HEIGHT / 16)]; - -int -impact_cnattach_common(bus_space_tag_t iot, bus_space_handle_t ioh, int has_hq4) -{ - struct impact_screen *scr = &impact_cons; - struct rasops_info *ri = &scr->ri; - int rc; - - scr->iot = iot; - scr->ioh = ioh; - impact_setup(scr, has_hq4); - scr->bs = impact_cons_bs; - rc = impact_init_screen(scr); - if (rc != 0) - return rc; - - ri->ri_ops.pack_attr(ri, 0, 0, 0, &scr->defattr); - wsdisplay_cnattach(&scr->wsd, ri, 0, 0, scr->defattr); - - return 0; -} diff --git a/sys/arch/sgi/dev/impactreg.h b/sys/arch/sgi/dev/impactreg.h deleted file mode 100644 index 15b6f909b2d..00000000000 --- a/sys/arch/sgi/dev/impactreg.h +++ /dev/null @@ -1,112 +0,0 @@ -/* $OpenBSD: impactreg.h,v 1.1 2012/04/18 17:28:24 miod Exp $ */ -/* - * Copyright (c) 2010 Miodrag Vallat. - * Copyright (c) 2009, 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. - */ - -/* - * Impact and ImpactSR registers - */ - -#define IMPACTSR_STATUS 0x020000 -#define IMPACTSR_FIFOSTATUS 0x020008 -#define IMPACTSR_FIFO_MASK 0x000000ff -#define IMPACTSR_GIOSTATUS 0x020100 -#define IMPACTSR_DMABUSY 0x020200 -#define IMPACTSR_CFIFO 0x020400 - -#define IMPACT_STATUS 0x070000 -#define IMPACT_FIFOSTATUS 0x070004 -#define IMPACT_GIOSTATUS 0x070100 -#define IMPACT_DMABUSY 0x070104 -#define IMPACT_CFIFO 0x070080 - -#define IMPACTSR_CFIFO_HW 0x040000 -#define IMPACTSR_CFIFO_LW 0x040008 -#define IMPACTSR_CFIFO_DELAY 0x040010 -#define IMPACTSR_DFIFO_HW 0x040020 -#define IMPACTSR_DFIFO_LW 0x040028 -#define IMPACTSR_DFIFO_DELAY 0x040030 -#define IMPACT_CFIFO_HW 0x050020 -#define IMPACT_CFIFO_LW 0x050024 -#define IMPACT_CFIFO_DELAY 0x050028 -#define IMPACT_DFIFO_HW 0x05002c -#define IMPACT_DFIFO_LW 0x050030 -#define IMPACT_DFIFO_DELAY 0x050034 - -#define IMPACTSR_XMAP_BASE 0x071c00 -#define IMPACT_XMAP_BASE 0x061c00 - -#define IMPACTSR_XMAP_PP1SELECT 0x000008 -#define IMPACTSR_XMAP_INDEX 0x000088 -#define IMPACTSR_XMAP_CONFIG 0x000100 -#define IMPACTSR_XMAP_CONFIGB 0x000108 -#define IMPACTSR_XMAP_BUF_SELECT 0x000180 -#define IMPACTSR_XMAP_MAIN_MODE 0x000200 -#define IMPACTSR_XMAP_OVERLAY_MODE 0x000280 -#define IMPACTSR_XMAP_DIB 0x000300 -#define IMPACTSR_XMAP_DIB_DW 0x000340 -#define IMPACTSR_XMAP_RE_RAC 0x000380 - -#define IMPACTSR_VC3_BASE 0x072000 -#define IMPACT_VC3_BASE 0x062000 - -#define IMPACTSR_VC3_INDEX 0x000008 -#define IMPACTSR_VC3_INDEXDATA 0x000038 -#define IMPACTSR_VC3_DATA 0x0000b0 -#define IMPACTSR_VC3_RAM 0x000190 - -/* - * Command FIFO instruction encoding - */ - -#define IMPACTSR_CFIFO_WRITE 0x0018000400000000UL -#define IMPACTSR_CFIFO_EXEC 0x0004000000000000UL -#define IMPACTSR_CFIFO_REG_SHIFT 40 - -/* - * Command FIFO registers - */ - -#define IMPACTSR_CMD_GLINE_XSTARTF 0x0c -#define IMPACTSR_CMD_IR_ALIAS 0x45 -#define IMPACTSR_CMD_BLOCKXYSTARTI 0x46 /* XY coords */ -#define IMPACTSR_CMD_BLOCKXYENDI 0x47 /* XY coords */ -#define IMPACTSR_CMD_PACKEDCOLOR 0x5b -#define IMPACTSR_CMD_ALPHA 0x5f -#define IMPACTSR_CMD_CHAR_H 0x70 -#define IMPACTSR_CMD_CHAR_L 0x71 -#define IMPACTSR_CMD_XFRCONTROL 0x102 -#define IMPACTSR_CMD_FILLMODE 0x110 -#define IMPACTSR_CMD_CONFIG 0x112 -#define IMPACTSR_CMD_XYWIN 0x115 /* YX coords */ -#define IMPACTSR_CMD_BKGRD_RG 0x140 -#define IMPACTSR_CMD_BKGRD_BA 0x141 -#define IMPACTSR_CMD_XFRSIZE 0x153 /* YX coords */ -#define IMPACTSR_CMD_XFRMASKLO 0x156 -#define IMPACTSR_CMD_XFRMASKHI 0x157 -#define IMPACTSR_CMD_XFRCOUNTERS 0x158 /* YX coords */ -#define IMPACTSR_CMD_XFRMODE 0x159 -#define IMPACTSR_CMD_RE_TOGGLECNTX 0x15f -#define IMPACTSR_CMD_PP1FILLMODE 0x161 -#define IMPACTSR_CMD_COLORMASKMSBS 0x162 -#define IMPACTSR_CMD_COLORMASKLSBSA 0x163 -#define IMPACTSR_CMD_COLORMASKLSBSB 0x164 -#define IMPACTSR_CMD_DRBPOINTERS 0x16d - -#define IMPACTSR_XYCOORDS(x,y) (((x) << 16) | (y)) -#define IMPACTSR_YXCOORDS(x,y) (((y) << 16) | (x)) - -#define IMPACTSR_PP1FILLMODE(mode,op) ((mode) | ((op) << 26)) diff --git a/sys/arch/sgi/dev/impactvar.h b/sys/arch/sgi/dev/impactvar.h deleted file mode 100644 index cc88b38a44c..00000000000 --- a/sys/arch/sgi/dev/impactvar.h +++ /dev/null @@ -1,36 +0,0 @@ -/* $OpenBSD: impactvar.h,v 1.1 2012/04/18 17:28: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. - */ - -struct impact_screen; - -struct impact_softc { - struct device sc_dev; - struct impact_screen *curscr; - int console; - int nscreens; -}; - -int impact_attach_common(struct impact_softc *, bus_space_tag_t, - bus_space_handle_t, int, int); -int impact_cnattach_common(bus_space_tag_t, bus_space_handle_t, int); - -struct gio_attach_args; -int impact_gio_cnprobe(struct gio_attach_args *); -int impact_gio_cnattach(struct gio_attach_args *); -int impact_xbow_cnprobe(void); -int impact_xbow_cnattach(void); diff --git a/sys/arch/sgi/dev/iockbc.c b/sys/arch/sgi/dev/iockbc.c deleted file mode 100644 index 7625be05e55..00000000000 --- a/sys/arch/sgi/dev/iockbc.c +++ /dev/null @@ -1,1277 +0,0 @@ -/* $OpenBSD: iockbc.c,v 1.12 2019/10/17 13:42:15 cheloha Exp $ */ -/* - * Copyright (c) 2013, Miodrag Vallat - * Copyright (c) 2006, 2007, 2009 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. - */ - -/* - * Derived from sys/dev/ic/pckbc.c under the following terms: - * $NetBSD: pckbc.c,v 1.5 2000/06/09 04:58:35 soda Exp $ */ - -/* - * Copyright (c) 1998 - * Matthias Drochner. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Driver for IOC3 and IOC4 PS/2 Controllers (iockbc) - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/malloc.h> -#include <sys/timeout.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/signalvar.h> -#include <sys/errno.h> -#include <sys/queue.h> - -#include <machine/autoconf.h> -#include <machine/bus.h> - -#include <mips64/archtype.h> - -#include <sgi/pci/iocreg.h> -#include <sgi/pci/iocvar.h> -#include <sgi/pci/iofreg.h> -#include <sgi/pci/iofvar.h> - -#include <dev/ic/i8042reg.h> -#include <dev/ic/pckbcvar.h> -#include <dev/pckbc/pckbdreg.h> -#define KBC_DEVCMD_ACK KBR_ACK -#define KBC_DEVCMD_RESEND KBR_RESEND -#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" }; - -/* #define IOCKBC_DEBUG */ -#ifdef IOCKBC_DEBUG -#define DPRINTF(x...) do { printf(x); } while(0) -#else -#define DPRINTF(x...) -#endif - -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 *); -void iockbc_ioc_attach(struct device *, struct device *, void *); -void iockbc_iof_attach(struct device *, struct device *, void *); - -#if NIOCKBC_IOC > 0 -struct cfattach iockbc_ioc_ca = { - sizeof(struct iockbc_softc), iockbc_match, iockbc_ioc_attach -}; -#endif -#if NIOCKBC_IOF > 0 -struct cfattach iockbc_iof_ca = { - sizeof(struct iockbc_softc), iockbc_match, iockbc_iof_attach -}; -#endif - -struct cfdriver iockbc_cd = { - NULL, "iockbc", DV_DULL -}; - -/* Descriptor for one device command. */ -struct pckbc_devcmd { - TAILQ_ENTRY(pckbc_devcmd) next; - int flags; -#define KBC_CMDFLAG_SYNC 1 /* Give descriptor back to caller. */ -#define KBC_CMDFLAG_SLOW 2 - u_char cmd[4]; - int cmdlen, cmdidx, retries; - u_char response[4]; - int status, responselen, responseidx; -}; - -/* Data per slave device. */ -struct pckbc_slotdata { - int polling; /* Don't read data port in interrupt handler. */ - TAILQ_HEAD(, pckbc_devcmd) cmdqueue; /* Active commands. */ - TAILQ_HEAD(, pckbc_devcmd) freequeue; /* Free commands. */ -#define NCMD 5 - 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) - -enum iockbc_slottype { EMPTY, KBD, MOUSE }; - -static struct pckbc_internal iockbc_consdata; -static struct pckbc_slotdata iockbc_cons_slotdata; - -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, - const struct iockbc_reginfo *, const struct iockbc_reginfo *); -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 *, - const struct iockbc_reginfo *); -int iockbc_submatch(struct device *, void *, void *); -int iockbcprint(void *, const char *); -int iockbcintr(void *); -int iockbcintr_internal(struct pckbc_internal *, struct pckbc_softc *); -void iockbc_cleanqueue(struct pckbc_slotdata *); -void iockbc_cleanup(void *); -void iockbc_poll(void *); -int iockbc_cmdresponse(struct pckbc_internal *, pckbc_slot_t, u_char); -int iockbc_poll_read(struct pckbc_internal *, pckbc_slot_t); -int iockbc_poll_write(struct pckbc_internal *, pckbc_slot_t, int); -void iockbc_process_input(struct pckbc_softc *, struct pckbc_internal *, - int, uint); -enum iockbc_slottype - iockbc_probe_slot(struct pckbc_internal *, pckbc_slot_t); - -int -iockbc_match(struct device *parent, void *cf, void *aux) -{ - /* - * 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[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) -{ - struct iockbc_softc *isc = (void*)self; - struct ioc_attach_args *iaa = aux; - - /* Setup bus space mapping. */ - isc->iot = iaa->iaa_memt; - isc->ioh = iaa->iaa_memh; - - /* Establish interrupt handler. */ - if (ioc_intr_establish(parent, iaa->iaa_dev, IPL_TTY, iockbcintr, - (void *)isc, self->dv_xname)) - printf("\n"); - else - printf(": unable to establish interrupt\n"); - - iockbc_attach_common(isc, iaa->iaa_base, iockbc_is_ioc_console(iaa), - iockbc_ioc, iockbc_ioc_inverted); -} -#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 - } -}; - -const struct iockbc_reginfo iockbc_iof_inverted[PCKBC_NSLOTS] = { - [PCKBC_KBD_SLOT] = { - .rx = IOC4_KBC_AUX_RX, - .tx = IOC4_KBC_AUX_TX, - .cs = IOC4_KBC_CTRL_STATUS, - .busy = IOC3_KBC_STATUS_AUX_WRITE_PENDING - }, - [PCKBC_AUX_SLOT] = { - .rx = IOC4_KBC_KBD_RX, - .tx = IOC4_KBC_KBD_TX, - .cs = IOC4_KBC_CTRL_STATUS, - .busy = IOC3_KBC_STATUS_KBD_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; - - /* Setup bus space mapping. */ - isc->iot = iaa->iaa_memt; - isc->ioh = iaa->iaa_memh; - - /* Establish interrupt handler. */ - if (iof_intr_establish(parent, iaa->iaa_dev, IPL_TTY, iockbcintr, - (void *)isc, self->dv_xname)) - printf("\n"); - else - printf(": unable to establish interrupt\n"); - - iockbc_attach_common(isc, iaa->iaa_base, iockbc_is_iof_console(iaa), - iockbc_iof, iockbc_iof_inverted); -} -#endif - -void -iockbc_init_slotdata(struct pckbc_slotdata *q, - const struct iockbc_reginfo *reginfo) -{ - int i; - TAILQ_INIT(&q->cmdqueue); - TAILQ_INIT(&q->freequeue); - - for (i = 0; i < NCMD; i++) - TAILQ_INSERT_TAIL(&q->freequeue, &(q->cmds[i]), next); - - q->polling = 0; - q->rx_index = -1; - - q->reginfo = reginfo; -} - -int -iockbcprint(void *aux, const char *pnp) -{ - struct pckbc_attach_args *pa = aux; - - if (!pnp) - printf(" (%s slot)", iockbc_slot_names[pa->pa_slot]); - - return (QUIET); -} - -int -iockbc_submatch(struct device *parent, void *match, void *aux) -{ - struct cfdata *cf = match; - struct pckbc_attach_args *pa = aux; - - if (cf->cf_loc[PCKBCCF_SLOT] != PCKBCCF_SLOT_DEFAULT && - cf->cf_loc[PCKBCCF_SLOT] != pa->pa_slot) - return (0); - - return ((*cf->cf_attach->ca_match)(parent, cf, pa)); -} - -/* - * Figure out what kind of device is connected to the given slot, if any. - */ -enum iockbc_slottype -iockbc_probe_slot(struct pckbc_internal *t, pckbc_slot_t slot) -{ - int rc, i, tries; - - /* reset device */ - pckbc_flush(t, slot); - for (tries = 0; tries < 5; tries++) { - rc = iockbc_poll_write(t, slot, KBC_RESET); - if (rc < 0) { - DPRINTF(("%s: slot %d write failed\n", __func__, slot)); - return EMPTY; - } - for (i = 10; i != 0; i--) { - rc = iockbc_poll_read(t, slot); - if (rc >= 0) - break; - } - if (rc < 0) { - DPRINTF(("%s: slot %d no answer to reset\n", - __func__, slot)); - return EMPTY; - } - if (rc == KBC_DEVCMD_ACK) - break; - if (rc == KBC_DEVCMD_RESEND) - continue; - DPRINTF(("%s: slot %d bogus reset ack %02x\n", - __func__, slot, rc)); - return EMPTY; - } - - /* get answer byte */ - for (i = 10; i != 0; i--) { - rc = iockbc_poll_read(t, slot); - if (rc >= 0) - break; - } - if (rc < 0) { - DPRINTF(("%s: slot %d no answer to reset after ack\n", - __func__, slot)); - return EMPTY; - } - if (rc != KBR_RSTDONE) { - DPRINTF(("%s: slot %d bogus reset answer %02x\n", - __func__, slot, rc)); - return EMPTY; - } - /* mice send an extra byte */ - (void)iockbc_poll_read(t, slot); - - /* ask for device id */ - for (tries = 0; tries < 5; tries++) { - rc = iockbc_poll_write(t, slot, KBC_READID); - if (rc == -1) { - DPRINTF(("%s: slot %d write failed\n", __func__, slot)); - return EMPTY; - } - for (i = 10; i != 0; i--) { - rc = iockbc_poll_read(t, slot); - if (rc >= 0) - break; - } - if (rc < 0) { - DPRINTF(("%s: slot %d no answer to command\n", - __func__, slot)); - return EMPTY; - } - if (rc == KBC_DEVCMD_ACK) - break; - if (rc == KBC_DEVCMD_RESEND) - continue; - DPRINTF(("%s: slot %d bogus command ack %02x\n", - __func__, slot, rc)); - return EMPTY; - } - - /* get first answer byte */ - for (i = 10; i != 0; i--) { - rc = iockbc_poll_read(t, slot); - if (rc >= 0) - break; - } - if (rc < 0) { - DPRINTF(("%s: slot %d no answer to command after ack\n", - __func__, slot)); - return EMPTY; - } - - switch (rc) { - case KCID_KBD1: /* keyboard */ - /* get second answer byte */ - rc = iockbc_poll_read(t, slot); - if (rc < 0) { - DPRINTF(("%s: slot %d truncated keyboard answer\n", - __func__, slot)); - return EMPTY; - } - if (rc != KCID_KBD2) { - DPRINTF(("%s: slot %d unexpected keyboard answer" - " 0x%02x 0x%02x\n", __func__, slot, KCID_KBD1, rc)); - /* return EMPTY; */ - } - return KBD; - case KCID_MOUSE: /* mouse */ - return MOUSE; - default: - DPRINTF(("%s: slot %d unknown device answer 0x%02x\n", - __func__, slot, rc)); - return EMPTY; - } -} - -int -iockbc_attach_slot(struct iockbc_softc *isc, pckbc_slot_t slot) -{ - struct pckbc_softc *sc = &isc->sc_pckbc; - struct pckbc_internal *t = sc->id; - struct pckbc_attach_args pa; - int found; - - iockbc_init_slotdata(t->t_slotdata[slot], &isc->reginfo[slot]); - - pa.pa_tag = t; - pa.pa_slot = slot; - - found = (config_found_sm((struct device *)sc, &pa, - iockbcprint, iockbc_submatch) != NULL); - - return (found); -} - -void -iockbc_attach_common(struct iockbc_softc *isc, bus_addr_t addr, int console, - const struct iockbc_reginfo *reginfo, - const struct iockbc_reginfo *reginfo_inverted) -{ - struct pckbc_softc *sc = &isc->sc_pckbc; - struct pckbc_internal *t; - bus_addr_t cs; - uint32_t csr; - pckbc_slot_t slot; - - if (console) { - iockbc_consdata.t_sc = sc; - sc->id = t = &iockbc_consdata; - isc->console = 1; - if (®info[PCKBC_KBD_SLOT] == iockbc_cons_slotdata.reginfo) - isc->reginfo = reginfo; - else - isc->reginfo = reginfo_inverted; - } else { - /* - * Setup up controller: do not force pull clock and data lines - * low, clamp clocks after one byte received. - */ - cs = reginfo[PCKBC_KBD_SLOT].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_3 | IOC3_KBC_CTRL_AUX_CLAMP_3); - csr |= IOC3_KBC_CTRL_KBD_CLAMP_1 | IOC3_KBC_CTRL_AUX_CLAMP_1; - 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); - - isc->reginfo = reginfo; - } - - for (slot = 0; slot < PCKBC_NSLOTS; slot++) { - if (t->t_slotdata[slot] == NULL) { - t->t_slotdata[slot] = - malloc(sizeof(struct pckbc_slotdata), - M_DEVBUF, M_WAITOK); - } - } - - if (!console) { - enum iockbc_slottype slottype; - int mouse_on_main = 0; - - /* - * Probe for a keyboard. If none is found at the regular - * keyboard port, but one is found at the mouse port, then - * it is likely that this particular system has both ports - * inverted (or incorrect labels on the chassis), unless - * this is a human error. In any case, try to get the - * keyboard to attach to the `keyboard' port and the - * pointing device to the `mouse' port. - */ - - for (slot = 0; slot < PCKBC_NSLOTS; slot++) { - iockbc_init_slotdata(t->t_slotdata[slot], - &isc->reginfo[slot]); - slottype = iockbc_probe_slot(t, slot); - if (slottype == KBD) - break; - if (slottype == MOUSE) - mouse_on_main = slot == PCKBC_KBD_SLOT; - } - if (slot == PCKBC_NSLOTS) { - /* - * We could not identify a keyboard. Let's assume - * none is connected; if a mouse has been found on - * the keyboard port and none on the aux port, the - * ports are likely to be inverted. - */ - if (mouse_on_main) - slot = PCKBC_AUX_SLOT; - else - slot = PCKBC_KBD_SLOT; - } - if (slot == PCKBC_AUX_SLOT) { - /* - * Either human error or inverted wiring; use - * the inverted port settings. - * iockbc_attach_slot() below will call - * iockbc_init_slotdata() again. - */ - isc->reginfo = reginfo_inverted; - } - } - - /* - * Attach "slots". - */ - iockbc_attach_slot(isc, PCKBC_KBD_SLOT); - iockbc_attach_slot(isc, PCKBC_AUX_SLOT); -} - -void -iockbc_poll(void *self) -{ - struct pckbc_internal *t = self; - int s; - - s = spltty(); - (void)iockbcintr_internal(t, t->t_sc); - timeout_add_sec(&t->t_poll, 1); - splx(s); -} - -int -iockbcintr(void *vsc) -{ - struct iockbc_softc *isc = (struct iockbc_softc *)vsc; - struct pckbc_softc *sc = &isc->sc_pckbc; - struct pckbc_internal *t = sc->id; - - return iockbcintr_internal(t, sc); -} - -int -iockbcintr_internal(struct pckbc_internal *t, struct pckbc_softc *sc) -{ - pckbc_slot_t slot; - struct pckbc_slotdata *q; - int served = 0; - uint32_t data; - uint32_t val; - - /* Reschedule timeout further into the idle times. */ - if (timeout_pending(&t->t_poll)) - timeout_add_sec(&t->t_poll, 1); - - /* - * Need to check both "slots" since interrupt could be from - * either controller. - */ - for (slot = 0; slot < PCKBC_NSLOTS; slot++) { - q = t->t_slotdata[slot]; - - for (;;) { - if (!q) { - DPRINTF("iockbcintr: no slot%d data!\n", slot); - break; - } - - if (q->polling) { - served = 1; - break; /* pckbc_poll_data() will get it */ - } - - val = bus_space_read_4(t->t_iot, t->t_ioh_d, - q->reginfo->rx); - if ((val & IOC3_KBC_DATA_VALID) == 0) - break; - - served = 1; - - /* Process received data. */ - if (val & IOC3_KBC_DATA_0_VALID) { - data = (val & IOC3_KBC_DATA_0_MASK) >> - IOC3_KBC_DATA_0_SHIFT; - iockbc_process_input(sc, t, slot, data); - } - - if (val & IOC3_KBC_DATA_1_VALID) { - data = (val & IOC3_KBC_DATA_1_MASK) >> - IOC3_KBC_DATA_1_SHIFT; - iockbc_process_input(sc, t, slot, data); - } - - if (val & IOC3_KBC_DATA_2_VALID) { - data = (val & IOC3_KBC_DATA_2_MASK) >> - IOC3_KBC_DATA_2_SHIFT; - iockbc_process_input(sc, t, slot, data); - } - } - } - - return (served); -} - -void -iockbc_process_input(struct pckbc_softc *sc, struct pckbc_internal *t, - int slot, uint data) -{ - struct pckbc_slotdata *q; - - q = t->t_slotdata[slot]; - if (CMD_IN_QUEUE(q) && iockbc_cmdresponse(t, slot, data)) - return; - - if (sc->inputhandler[slot]) - (*sc->inputhandler[slot])(sc->inputarg[slot], data); - else - DPRINTF("iockbcintr: slot %d lost %d\n", slot, data); -} - -int -iockbc_poll_write(struct pckbc_internal *t, pckbc_slot_t slot, int val) -{ - 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; - int timeout = 10000; - - /* Attempt to write a value to the controller. */ - while (timeout--) { - 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); - } - - DPRINTF("iockbc_poll_write: timeout, sts %08x\n", stat); - return -1; -} - -int -iockbc_poll_read(struct pckbc_internal *t, pckbc_slot_t slot) -{ - struct pckbc_slotdata *q = t->t_slotdata[slot]; - int timeout = 10000; - u_int32_t val; - - /* See if we already have bytes queued. */ - if (q->rx_index >= 0) - return q->rx_queue[q->rx_index--]; - - /* Poll input from controller. */ - while (timeout--) { - val = bus_space_read_4(t->t_iot, t->t_ioh_d, q->reginfo->rx); - if (val & IOC3_KBC_DATA_VALID) - break; - delay(50); - } - if ((val & IOC3_KBC_DATA_VALID) == 0) { - DPRINTF("iockbc_poll_read: timeout, wx %08x\n", val); - return -1; - } - - /* Process received data. */ - if (val & IOC3_KBC_DATA_2_VALID) - q->rx_queue[++q->rx_index] = - (val & IOC3_KBC_DATA_2_MASK) >> IOC3_KBC_DATA_2_SHIFT; - - if (val & IOC3_KBC_DATA_1_VALID) - q->rx_queue[++q->rx_index] = - (val & IOC3_KBC_DATA_1_MASK) >> IOC3_KBC_DATA_1_SHIFT; - - if (val & IOC3_KBC_DATA_0_VALID) - q->rx_queue[++q->rx_index] = - (val & IOC3_KBC_DATA_0_MASK) >> IOC3_KBC_DATA_0_SHIFT; - - if (q->rx_index >= 0) - return q->rx_queue[q->rx_index--]; - else - return -1; -} - -/* - * Pass command to device, poll for ACK and data. - * to be called at spltty() - */ -static void -iockbc_poll_cmd(struct pckbc_internal *t, pckbc_slot_t slot, - struct pckbc_devcmd *cmd) -{ - int i, c = 0; - - while (cmd->cmdidx < cmd->cmdlen) { - if (iockbc_poll_write(t, slot, cmd->cmd[cmd->cmdidx]) == -1) { - DPRINTF("iockbc_poll_cmd: send error\n"); - cmd->status = EIO; - return; - } - for (i = 10; i; i--) { /* 1s ??? */ - c = iockbc_poll_read(t, slot); - if (c != -1) - break; - } - if (c == KBC_DEVCMD_ACK) { - cmd->cmdidx++; - continue; - } - if (c == KBC_DEVCMD_RESEND) { - DPRINTF("iockbc_cmd: RESEND\n"); - if (cmd->retries++ < 5) - continue; - else { - DPRINTF("iockbc: cmd failed\n"); - cmd->status = EIO; - return; - } - } - if (c == -1) { - DPRINTF("iockbc_cmd: timeout\n"); - cmd->status = EIO; - return; - } - DPRINTF("iockbc_cmd: lost 0x%x\n", c); - } - - while (cmd->responseidx < cmd->responselen) { - if (cmd->flags & KBC_CMDFLAG_SLOW) - i = 100; /* 10s ??? */ - else - i = 10; /* 1s ??? */ - while (i--) { - c = iockbc_poll_read(t, slot); - if (c != -1) - break; - } - if (c == -1) { - DPRINTF("iockbc_poll_cmd: no data\n"); - cmd->status = ETIMEDOUT; - return; - } else - cmd->response[cmd->responseidx++] = c; - } -} - -/* - * Clean up a command queue, throw away everything. - */ -void -iockbc_cleanqueue(struct pckbc_slotdata *q) -{ - struct pckbc_devcmd *cmd; -#ifdef IOCKBC_DEBUG - int i; -#endif - - while ((cmd = TAILQ_FIRST(&q->cmdqueue))) { - TAILQ_REMOVE(&q->cmdqueue, cmd, next); -#ifdef IOCKBC_DEBUG - printf("iockbc_cleanqueue: removing"); - for (i = 0; i < cmd->cmdlen; i++) - printf(" %02x", cmd->cmd[i]); - printf("\n"); -#endif - TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); - } -} - -/* - * Timeout error handler: clean queues and data port. - * XXX could be less invasive. - */ -void -iockbc_cleanup(void *self) -{ - struct pckbc_internal *t = self; - int s; - - printf("iockbc: command timeout\n"); - - s = spltty(); - - if (t->t_slotdata[PCKBC_KBD_SLOT]) - iockbc_cleanqueue(t->t_slotdata[PCKBC_KBD_SLOT]); - if (t->t_slotdata[PCKBC_AUX_SLOT]) - iockbc_cleanqueue(t->t_slotdata[PCKBC_AUX_SLOT]); - - while (iockbc_poll_read(t, PCKBC_KBD_SLOT) - != -1) ; - while (iockbc_poll_read(t, PCKBC_AUX_SLOT) - != -1) ; - - /* Reset KBC? */ - - splx(s); -} - -/* - * Pass command to device during normal operation. - * to be called at spltty() - */ -void -iockbc_start(struct pckbc_internal *t, pckbc_slot_t slot) -{ - struct pckbc_slotdata *q = t->t_slotdata[slot]; - struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue); - - if (q->polling) { - do { - iockbc_poll_cmd(t, slot, cmd); - if (cmd->status) - printf("iockbc_start: command error\n"); - - TAILQ_REMOVE(&q->cmdqueue, cmd, next); - if (cmd->flags & KBC_CMDFLAG_SYNC) - wakeup(cmd); - else { - timeout_del(&t->t_cleanup); - TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); - } - cmd = TAILQ_FIRST(&q->cmdqueue); - } while (cmd); - return; - } - - if (iockbc_poll_write(t, slot, cmd->cmd[cmd->cmdidx])) { - printf("iockbc_start: send error\n"); - /* XXX what now? */ - return; - } -} - -/* - * Handle command responses coming in asynchronously, - * return nonzero if valid response. - * to be called at spltty() - */ -int -iockbc_cmdresponse(struct pckbc_internal *t, pckbc_slot_t slot, u_char data) -{ - struct pckbc_slotdata *q = t->t_slotdata[slot]; - struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue); -#ifdef DIAGNOSTIC - if (!cmd) - panic("iockbc_cmdresponse: no active command"); -#endif - if (cmd->cmdidx < cmd->cmdlen) { - if (data != KBC_DEVCMD_ACK && data != KBC_DEVCMD_RESEND) - return (0); - - if (data == KBC_DEVCMD_RESEND) { - if (cmd->retries++ < 5) { - /* try again last command */ - goto restart; - } else { - DPRINTF("iockbc: cmd failed\n"); - cmd->status = EIO; - /* dequeue */ - } - } else { - if (++cmd->cmdidx < cmd->cmdlen) - goto restart; - if (cmd->responselen) - return (1); - /* else dequeue */ - } - } else if (cmd->responseidx < cmd->responselen) { - cmd->response[cmd->responseidx++] = data; - if (cmd->responseidx < cmd->responselen) - return (1); - /* else dequeue */ - } else - return (0); - - /* dequeue: */ - TAILQ_REMOVE(&q->cmdqueue, cmd, next); - if (cmd->flags & KBC_CMDFLAG_SYNC) - wakeup(cmd); - else { - timeout_del(&t->t_cleanup); - TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); - } - if (!CMD_IN_QUEUE(q)) - return (1); -restart: - iockbc_start(t, slot); - return (1); -} - -/* - * Interfaces to act like pckbc(4). - */ - -int -pckbc_xt_translation(pckbc_tag_t self) -{ - /* Translation isn't supported... */ - return (-1); -} - -/* For use in autoconfiguration. */ -int -pckbc_poll_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len, - int responselen, u_char *respbuf, int slow) -{ - struct pckbc_devcmd nc; - int s; - - if ((len > 4) || (responselen > 4)) - return (EINVAL); - - bzero(&nc, sizeof(nc)); - bcopy(cmd, nc.cmd, len); - nc.cmdlen = len; - nc.responselen = responselen; - nc.flags = (slow ? KBC_CMDFLAG_SLOW : 0); - - s = spltty(); - iockbc_poll_cmd(self, slot, &nc); - splx(s); - - if (nc.status == 0 && respbuf) - bcopy(nc.response, respbuf, responselen); - - return (nc.status); -} - -void -pckbc_flush(pckbc_tag_t self, pckbc_slot_t slot) -{ - /* Read any data and discard. */ - struct pckbc_internal *t = self; - (void) iockbc_poll_read(t, slot); -} - -/* - * Put command into the device's command queue, return zero or errno. - */ -int -pckbc_enqueue_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len, - int responselen, int sync, u_char *respbuf) -{ - struct pckbc_internal *t = self; - struct pckbc_slotdata *q = t->t_slotdata[slot]; - struct pckbc_devcmd *nc; - int s, isactive, res = 0; - - if ((len > 4) || (responselen > 4)) - return (EINVAL); - s = spltty(); - nc = TAILQ_FIRST(&q->freequeue); - if (nc) - TAILQ_REMOVE(&q->freequeue, nc, next); - splx(s); - if (!nc) - return (ENOMEM); - - bzero(nc, sizeof(*nc)); - bcopy(cmd, nc->cmd, len); - nc->cmdlen = len; - nc->responselen = responselen; - nc->flags = (sync ? KBC_CMDFLAG_SYNC : 0); - - s = spltty(); - - if (q->polling && sync) { - /* - * XXX We should poll until the queue is empty. - * But we don't come here normally, so make - * it simple and throw away everything. - */ - iockbc_cleanqueue(q); - } - - isactive = CMD_IN_QUEUE(q); - TAILQ_INSERT_TAIL(&q->cmdqueue, nc, next); - if (!isactive) - iockbc_start(t, slot); - - if (q->polling) - res = (sync ? nc->status : 0); - else if (sync) { - if ((res = tsleep_nsec(nc, 0, "kbccmd", SEC_TO_NSEC(1)))) { - TAILQ_REMOVE(&q->cmdqueue, nc, next); - iockbc_cleanup(t); - } else - res = nc->status; - } else - timeout_add_sec(&t->t_cleanup, 1); - - if (sync) { - if (respbuf) - bcopy(nc->response, respbuf, responselen); - TAILQ_INSERT_TAIL(&q->freequeue, nc, next); - } - - splx(s); - - return (res); -} - -int -pckbc_poll_data(pckbc_tag_t self, pckbc_slot_t slot) -{ - struct pckbc_internal *t = self; - struct pckbc_slotdata *q = t->t_slotdata[slot]; - int c; - - c = iockbc_poll_read(t, slot); - if (c != -1 && q && CMD_IN_QUEUE(q)) { - /* We jumped into a running command - try to deliver the - response. */ - if (iockbc_cmdresponse(t, slot, c)) - return (-1); - } - return (c); -} - -void -pckbc_set_inputhandler(pckbc_tag_t self, pckbc_slot_t slot, pckbc_inputfcn func, - void *arg, char *name) -{ - 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); - - sc->inputhandler[slot] = func; - sc->inputarg[slot] = arg; - sc->subname[slot] = name; - - if ((isc == NULL || isc->console) && slot == PCKBC_KBD_SLOT) - timeout_add_sec(&t->t_poll, 1); -} - -void -pckbc_slot_enable(pckbc_tag_t self, pckbc_slot_t slot, int on) -{ - struct pckbc_internal *t = (struct pckbc_internal *)self; - - if (slot == PCKBC_KBD_SLOT) { - if (on) - timeout_add_sec(&t->t_poll, 1); - else - timeout_del(&t->t_poll); - } -} - -void -pckbc_set_poll(pckbc_tag_t self, pckbc_slot_t slot, int on) -{ - struct pckbc_internal *t = (struct pckbc_internal *)self; - - t->t_slotdata[slot]->polling = on; - - if (!on) { - int s; - - /* - * If disabling polling on a device that's been configured, - * make sure there are no bytes left in the FIFO, holding up - * the interrupt line. Otherwise we won't get any further - * interrupts. - */ - if (t->t_sc) { - s = spltty(); - iockbcintr(t->t_sc); - splx(s); - } - } -} - -/* - * Console support. - */ - -static int iockbc_console; - -int -iockbc_cnattach() -{ - 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, *reginfo_inverted; - enum iockbc_slottype slottype; - pckbc_slot_t slot; - uint32_t csr; - int is_ioc; - int rc; - - is_ioc = console_input.specific == - PCI_ID_CODE(PCI_VENDOR_SGI, PCI_PRODUCT_SGI_IOC3); - if (is_ioc) { -#if NIOCKBC_IOC > 0 - reginfo = iockbc_ioc; - reginfo_inverted = iockbc_ioc_inverted; -#endif - } else { -#if NIOCKBC_IOF > 0 - reginfo = iockbc_iof; - reginfo_inverted = iockbc_iof_inverted; -#endif - } - if (reginfo == NULL) - return ENXIO; - - /* - * Setup up controller: do not force pull clock and data lines - * low, clamp clocks after one byte 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_3 | IOC3_KBC_CTRL_AUX_CLAMP_3); - csr |= IOC3_KBC_CTRL_KBD_CLAMP_1 | IOC3_KBC_CTRL_AUX_CLAMP_1; - 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); - - /* - * Probe for a keyboard. There must be one connected, for the PROM - * would not have advertized glass console if none had been - * detected. - */ - - for (slot = 0; slot < PCKBC_NSLOTS; slot++) { - iockbc_init_slotdata(&iockbc_cons_slotdata, ®info[slot]); - t->t_slotdata[slot] = &iockbc_cons_slotdata; - slottype = iockbc_probe_slot(t, slot); - t->t_slotdata[slot] = NULL; - if (slottype == KBD) - break; - } - if (slot == PCKBC_NSLOTS) { - /* - * We could not identify a keyboard, but the PROM did; - * let's assume it's a fluke and assume it exists and - * is connected to the first connector. - */ - slot = PCKBC_KBD_SLOT; - /* - * For some reason keyboard and mouse ports are inverted on - * Fuel. They also are inverted on some IO9 boards, but - * we can't tell both IO9 flavour apart, yet. - */ - if (is_ioc && sys_config.system_type == SGI_IP35) - slot = PCKBC_AUX_SLOT; - } - - if (slot == PCKBC_AUX_SLOT) { - /* - * Either human error when plugging the keyboard, or the - * physical connectors on the chassis are inverted. - * Compensate by switching in software (pckbd relies upon - * being at PCKBC_KBD_SLOT). - */ - reginfo = reginfo_inverted; - } - - iockbc_init_slotdata(&iockbc_cons_slotdata, ®info[PCKBC_KBD_SLOT]); - t->t_slotdata[PCKBC_KBD_SLOT] = &iockbc_cons_slotdata; - - rc = pckbd_cnattach(t); - if (rc == 0) - iockbc_console = 1; - - return rc; -} - -#if NIOCKBC_IOC > 0 -int -iockbc_is_ioc_console(struct ioc_attach_args *iaa) -{ - if (iockbc_console == 0) - return 0; - - return location_match(&iaa->iaa_location, &console_input); -} -#endif - -#if NIOCKBC_IOF > 0 -int -iockbc_is_iof_console(struct iof_attach_args *iaa) -{ - if (iockbc_console == 0) - return 0; - - return location_match(&iaa->iaa_location, &console_input); -} -#endif diff --git a/sys/arch/sgi/dev/iockbcreg.h b/sys/arch/sgi/dev/iockbcreg.h deleted file mode 100644 index ecd31c81bcb..00000000000 --- a/sys/arch/sgi/dev/iockbcreg.h +++ /dev/null @@ -1,51 +0,0 @@ -/* $OpenBSD: iockbcreg.h,v 1.1 2009/11/18 19:03:27 miod Exp $ */ - -/* - * Copyright (c) 2008 Joel Sing. - * - * 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. - */ - -/* - * Register definitions for the PS/2 controller part of SGI IOC3 and IOC4 ASICS. - */ - -/* bits in KBC_CTRL_STATUS */ -#define IOC3_KBC_STATUS_KBD_WRITE_PENDING 0x00000001 -#define IOC3_KBC_STATUS_AUX_WRITE_PENDING 0x00000002 -#define IOC3_KBC_STATUS_KBD_DATA 0x00000010 -#define IOC3_KBC_STATUS_KBD_CLOCK 0x00000020 -#define IOC3_KBC_CTRL_KBD_PULL_DATA_LOW 0x00000040 -#define IOC3_KBC_CTRL_KBD_PULL_CLOCK_LOW 0x00000080 -#define IOC3_KBC_STATUS_AUX_DATA 0x00000100 -#define IOC3_KBC_STATUS_AUX_CLOCK 0x00000200 -#define IOC3_KBC_CTRL_AUX_PULL_DATA_LOW 0x00000400 -#define IOC3_KBC_CTRL_AUX_PULL_CLOCK_LOW 0x00000800 -#define IOC3_KBC_CTRL_KBD_CLAMP_1 0x00100000 -#define IOC3_KBC_CTRL_AUX_CLAMP_1 0x00200000 -#define IOC3_KBC_CTRL_KBD_CLAMP_3 0x00400000 -#define IOC3_KBC_CTRL_AUX_CLAMP_3 0x00800000 - -/* bits in KBC_*_RX */ -#define IOC3_KBC_DATA_0_VALID 0x80000000 -#define IOC3_KBC_DATA_1_VALID 0x40000000 -#define IOC3_KBC_DATA_2_VALID 0x20000000 -#define IOC3_KBC_DATA_VALID (IOC3_KBC_DATA_0_VALID | \ - IOC3_KBC_DATA_1_VALID | \ - IOC3_KBC_DATA_2_VALID) -#define IOC3_KBC_DATA_0_MASK 0x00ff0000 -#define IOC3_KBC_DATA_0_SHIFT 16 -#define IOC3_KBC_DATA_1_MASK 0x0000ff00 -#define IOC3_KBC_DATA_1_SHIFT 8 -#define IOC3_KBC_DATA_2_MASK 0x000000ff -#define IOC3_KBC_DATA_2_SHIFT 0 diff --git a/sys/arch/sgi/dev/iockbcvar.h b/sys/arch/sgi/dev/iockbcvar.h deleted file mode 100644 index 5c58581eaed..00000000000 --- a/sys/arch/sgi/dev/iockbcvar.h +++ /dev/null @@ -1,19 +0,0 @@ -/* $OpenBSD: iockbcvar.h,v 1.4 2010/12/04 11:23:43 jsing 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(void); diff --git a/sys/arch/sgi/dev/mavb.c b/sys/arch/sgi/dev/mavb.c deleted file mode 100644 index e62d908ff38..00000000000 --- a/sys/arch/sgi/dev/mavb.c +++ /dev/null @@ -1,1201 +0,0 @@ -/* $OpenBSD: mavb.c,v 1.22 2021/03/11 11:17:00 jsg Exp $ */ - -/* - * Copyright (c) 2005 Mark Kettenis - * - * 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. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/kernel.h> -#include <sys/timeout.h> - -#include <machine/bus.h> -#include <machine/intr.h> - -#include <sys/audioio.h> -#include <dev/audio_if.h> - -#include <sgi/localbus/macebus.h> -#include <sgi/localbus/macebusvar.h> -#include <sgi/dev/mavbreg.h> - -#include <dev/ic/ad1843reg.h> - -#undef MAVB_DEBUG - -#ifdef MAVB_DEBUG -#define DPRINTF(l,x) do { if (mavb_debug & (l)) printf x; } while (0) -#define MAVB_DEBUG_INTR 0x0100 -int mavb_debug = ~MAVB_DEBUG_INTR; -#else -#define DPRINTF(l,x) /* nothing */ -#endif - -/* Repeat delays for volume buttons. */ -#define MAVB_VOLUME_BUTTON_REPEAT_DEL1 400 /* 400ms to start repeating */ -#define MAVB_VOLUME_BUTTON_REPEAT_DELN 100 /* 100ms between repeats */ - -/* XXX We need access to some of the MACE ISA registers. */ -#define MAVB_ISA_NREGS 0x20 - -#define MAVB_ISA_RING_SIZE 0x4000 /* Mace ISA DMA ring size. */ -#define MAVB_CHAN_RING_SIZE 0x1000 /* DMA buffer size per channel. */ -#define MAVB_CHAN_INTR_SIZE 0x0800 /* Interrupt on 50% buffer transfer. */ -#define MAVB_CHAN_CHUNK_SIZE 0x0400 /* Move data in 25% buffer chunks. */ - - -/* - * AD1843 Mixer. - */ - -enum { - AD1843_RECORD_CLASS, - AD1843_ADC_SOURCE, /* ADC Source Select */ - AD1843_ADC_GAIN, /* ADC Input Gain */ - AD1843_ADC_MIC_GAIN, /* ADC Mic Input Gain */ - - AD1843_INPUT_CLASS, - AD1843_DAC1_GAIN, /* DAC1 Analog/Digital Gain/Attenuation */ - AD1843_DAC1_MUTE, /* DAC1 Analog Mute */ - AD1843_DAC2_GAIN, /* DAC2 Mix Gain */ - AD1843_AUX1_GAIN, /* Auxiliary 1 Mix Gain */ - AD1843_AUX2_GAIN, /* Auxiliary 2 Mix Gain */ - AD1843_AUX3_GAIN, /* Auxiliary 3 Mix Gain */ - AD1843_MIC_GAIN, /* Microphone Mix Gain */ - AD1843_MONO_GAIN, /* Mono Mix Gain */ - AD1843_DAC2_MUTE, /* DAC2 Mix Mute */ - AD1843_AUX1_MUTE, /* Auxiliary 1 Mix Mute */ - AD1843_AUX2_MUTE, /* Auxiliary 2 Mix Mute */ - AD1843_AUX3_MUTE, /* Auxiliary 3 Mix Mute */ - AD1843_MIC_MUTE, /* Microphone Mix Mute */ - AD1843_MONO_MUTE, /* Mono Mix Mute */ - AD1843_SUM_MUTE, /* Sum Mute */ - - AD1843_OUTPUT_CLASS, - AD1843_MNO_MUTE, /* Mono Output Mute */ - AD1843_HPO_MUTE /* Headphone Output Mute */ -}; - -/* ADC Source Select. The order matches the hardware bits. */ -const char *ad1843_source[] = { - AudioNline, - AudioNmicrophone, - AudioNaux "1", - AudioNaux "2", - AudioNaux "3", - AudioNmono, - AudioNdac "1", - AudioNdac "2" -}; - -/* Mix Control. The order matches the hardware register numbering. */ -const char *ad1843_input[] = { - AudioNdac "2", /* AD1843_DAC2__TO_MIXER */ - AudioNaux "1", - AudioNaux "2", - AudioNaux "3", - AudioNmicrophone, - AudioNmono /* AD1843_MISC_SETTINGS */ -}; - -struct mavb_chan { - caddr_t hw_start; - caddr_t sw_start; - caddr_t sw_end; - caddr_t sw_cur; - void (*intr)(void *); - void *intrarg; - u_long rate; - u_int format; - int blksize; -}; - -struct mavb_softc { - struct device sc_dev; - bus_space_tag_t sc_st; - bus_space_handle_t sc_sh; - bus_dma_tag_t sc_dmat; - bus_dmamap_t sc_dmamap; - - /* XXX We need access to some of the MACE ISA registers. */ - bus_space_handle_t sc_isash; - - caddr_t sc_ring; - - struct mavb_chan play; - struct mavb_chan rec; - - struct timeout sc_volume_button_to; -}; - -typedef u_long ad1843_addr_t; - -u_int16_t ad1843_reg_read(struct mavb_softc *, ad1843_addr_t); -u_int16_t ad1843_reg_write(struct mavb_softc *, ad1843_addr_t, u_int16_t); -void ad1843_dump_regs(struct mavb_softc *); - -int mavb_match(struct device *, void *, void *); -void mavb_attach(struct device *, struct device *, void *); - -struct cfattach mavb_ca = { - sizeof(struct mavb_softc), mavb_match, mavb_attach -}; - -struct cfdriver mavb_cd = { - NULL, "mavb", DV_DULL -}; - -int mavb_open(void *, int); -void mavb_close(void *); -int mavb_set_params(void *, int, int, struct audio_params *, - struct audio_params *); -int mavb_round_blocksize(void *hdl, int bs); -int mavb_halt_output(void *); -int mavb_halt_input(void *); -int mavb_set_port(void *, struct mixer_ctrl *); -int mavb_get_port(void *, struct mixer_ctrl *); -int mavb_query_devinfo(void *, struct mixer_devinfo *); -int mavb_get_props(void *); -int mavb_trigger_output(void *, void *, void *, int, void (*)(void *), - void *, struct audio_params *); -int mavb_trigger_input(void *, void *, void *, int, void (*)(void *), - void *, struct audio_params *); - -struct audio_hw_if mavb_sa_hw_if = { - mavb_open, - mavb_close, - mavb_set_params, - mavb_round_blocksize, - 0, - 0, - 0, - 0, - 0, - mavb_halt_output, - mavb_halt_input, - 0, - 0, - mavb_set_port, - mavb_get_port, - mavb_query_devinfo, - 0, - 0, - 0, - mavb_get_props, - mavb_trigger_output, - mavb_trigger_input -}; - -int -mavb_open(void *hdl, int flags) -{ - return (0); -} - -void -mavb_close(void *hdl) -{ -} - -static int -mavb_set_play_rate(struct mavb_softc *sc, u_long sample_rate) -{ - if (sample_rate < 4000 || sample_rate > 48000) - return (EINVAL); - - if (sc->play.rate != sample_rate) { - ad1843_reg_write(sc, AD1843_CLOCK2_SAMPLE_RATE, sample_rate); - sc->play.rate = sample_rate; - } - return (0); -} - -static int -mavb_set_rec_rate(struct mavb_softc *sc, u_long sample_rate) -{ - if (sample_rate < 4000 || sample_rate > 48000) - return (EINVAL); - - if (sc->rec.rate != sample_rate) { - ad1843_reg_write(sc, AD1843_CLOCK1_SAMPLE_RATE, sample_rate); - sc->rec.rate = sample_rate; - } - return (0); -} - -static int -mavb_get_format(u_int encoding, u_int *format) -{ - switch(encoding) { - case AUDIO_ENCODING_ULINEAR_BE: - *format = AD1843_PCM8; - break; - case AUDIO_ENCODING_SLINEAR_BE: - *format = AD1843_PCM16; - break; - case AUDIO_ENCODING_ULAW: - *format = AD1843_ULAW; - break; - case AUDIO_ENCODING_ALAW: - *format = AD1843_ALAW; - break; - default: - return (EINVAL); - } - return (0); -} - -static int -mavb_set_play_format(struct mavb_softc *sc, u_int encoding) -{ - u_int16_t value; - u_int format; - int err; - - err = mavb_get_format(encoding, &format); - if (err) - return (err); - - if (sc->play.format != format) { - value = ad1843_reg_read(sc, AD1843_SERIAL_INTERFACE); - value &= ~AD1843_DA1F_MASK; - value |= (format << AD1843_DA1F_SHIFT); - ad1843_reg_write(sc, AD1843_SERIAL_INTERFACE, value); - sc->play.format = format; - } - return (0); -} - -static int -mavb_set_rec_format(struct mavb_softc *sc, u_int encoding) -{ - u_int16_t value; - u_int format; - int err; - - err = mavb_get_format(encoding, &format); - if (err) - return (err); - - if (sc->rec.format != format) { - value = ad1843_reg_read(sc, AD1843_SERIAL_INTERFACE); - value &= ~(AD1843_ADRF_MASK | AD1843_ADLF_MASK); - value |= (format << AD1843_ADRF_SHIFT) | - (format << AD1843_ADLF_SHIFT); - ad1843_reg_write(sc, AD1843_SERIAL_INTERFACE, value); - sc->rec.format = format; - } - return (0); -} - -int -mavb_set_params(void *hdl, int setmode, int usemode, - struct audio_params *play, struct audio_params *rec) -{ - struct mavb_softc *sc = (struct mavb_softc *)hdl; - int error; - - DPRINTF(1, ("%s: mavb_set_params: sample=%ld precision=%d " - "channels=%d\n", sc->sc_dev.dv_xname, play->sample_rate, - play->precision, play->channels)); - - if (setmode & AUMODE_PLAY) { - play->encoding = AUDIO_ENCODING_SLINEAR_BE; - play->channels = 2; - play->precision = 24; - play->bps = AUDIO_BPS(play->precision); - play->msb = 0; - error = mavb_set_play_rate(sc, play->sample_rate); - if (error) - return (error); - - error = mavb_set_play_format(sc, play->encoding); - if (error) - return (error); - - } - - if (setmode & AUMODE_RECORD) { - rec->encoding = AUDIO_ENCODING_SLINEAR_BE; - rec->channels = 2; - rec->precision = 24; - rec->bps = AUDIO_BPS(rec->precision); - rec->msb = 0; - - error = mavb_set_rec_rate(sc, rec->sample_rate); - if (error) - return (error); - - error = mavb_set_rec_format(sc, rec->encoding); - if (error) - return (error); - } - - return (0); -} - -int -mavb_round_blocksize(void *hdl, int bs) -{ - if (bs == 0) - bs = MAVB_CHAN_INTR_SIZE; - else - bs = (bs + MAVB_CHAN_INTR_SIZE - 1) & - ~(MAVB_CHAN_INTR_SIZE - 1); - return (bs); -} - -int -mavb_halt_output(void *hdl) -{ - struct mavb_softc *sc = (struct mavb_softc *)hdl; - - DPRINTF(1, ("%s: mavb_halt_output called\n", sc->sc_dev.dv_xname)); - mtx_enter(&audio_lock); - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0); - mtx_leave(&audio_lock); - return (0); -} - -int -mavb_halt_input(void *hdl) -{ - struct mavb_softc *sc = (struct mavb_softc *)hdl; - - DPRINTF(1, ("%s: mavb_halt_input called\n", sc->sc_dev.dv_xname)); - mtx_enter(&audio_lock); - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL1_CONTROL, 0); - mtx_leave(&audio_lock); - return (0); -} - -int -mavb_set_port(void *hdl, struct mixer_ctrl *mc) -{ - struct mavb_softc *sc = (struct mavb_softc *)hdl; - u_char left, right; - ad1843_addr_t reg; - u_int16_t value; - - DPRINTF(1, ("%s: mavb_set_port: dev=%d\n", sc->sc_dev.dv_xname, - mc->dev)); - - switch (mc->dev) { - case AD1843_ADC_SOURCE: - value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN); - value &= ~(AD1843_LSS_MASK | AD1843_RSS_MASK); - value |= ((mc->un.ord << AD1843_LSS_SHIFT) & AD1843_LSS_MASK); - value |= ((mc->un.ord << AD1843_RSS_SHIFT) & AD1843_RSS_MASK); - ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value); - break; - case AD1843_ADC_GAIN: - left = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; - right = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; - value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN); - value &= ~(AD1843_LIG_MASK | AD1843_RIG_MASK); - value |= ((left >> 4) << AD1843_LIG_SHIFT); - value |= ((right >> 4) << AD1843_RIG_SHIFT); - ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value); - break; - case AD1843_ADC_MIC_GAIN: - value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN); - if (mc->un.ord == 0) - value &= ~(AD1843_LMGE | AD1843_RMGE); - else - value |= (AD1843_LMGE | AD1843_RMGE); - ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value); - break; - - case AD1843_DAC1_GAIN: - left = AUDIO_MAX_GAIN - - mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; - right = AUDIO_MAX_GAIN - - mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; - value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); - value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK); - value |= ((left >> 2) << AD1843_LDA1G_SHIFT); - value |= ((right >> 2) << AD1843_RDA1G_SHIFT); - ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value); - break; - case AD1843_DAC1_MUTE: - value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); - if (mc->un.ord == 0) - value &= ~(AD1843_LDA1GM | AD1843_RDA1GM); - else - value |= (AD1843_LDA1GM | AD1843_RDA1GM); - ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value); - break; - - case AD1843_DAC2_GAIN: - case AD1843_AUX1_GAIN: - case AD1843_AUX2_GAIN: - case AD1843_AUX3_GAIN: - case AD1843_MIC_GAIN: - left = AUDIO_MAX_GAIN - - mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; - right = AUDIO_MAX_GAIN - - mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; - reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN; - value = ad1843_reg_read(sc, reg); - value &= ~(AD1843_LD2M_MASK | AD1843_RD2M_MASK); - value |= ((left >> 3) << AD1843_LD2M_SHIFT); - value |= ((right >> 3) << AD1843_RD2M_SHIFT); - ad1843_reg_write(sc, reg, value); - break; - case AD1843_MONO_GAIN: - left = AUDIO_MAX_GAIN - - mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; - value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); - value &= ~AD1843_MNM_MASK; - value |= ((left >> 3) << AD1843_MNM_SHIFT); - ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value); - break; - case AD1843_DAC2_MUTE: - case AD1843_AUX1_MUTE: - case AD1843_AUX2_MUTE: - case AD1843_AUX3_MUTE: - case AD1843_MIC_MUTE: - case AD1843_MONO_MUTE: /* matches left channel */ - reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE; - value = ad1843_reg_read(sc, reg); - if (mc->un.ord == 0) - value &= ~(AD1843_LD2MM | AD1843_RD2MM); - else - value |= (AD1843_LD2MM | AD1843_RD2MM); - ad1843_reg_write(sc, reg, value); - break; - - case AD1843_SUM_MUTE: - value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); - if (mc->un.ord == 0) - value &= ~AD1843_SUMM; - else - value |= AD1843_SUMM; - ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value); - break; - - case AD1843_MNO_MUTE: - value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); - if (mc->un.ord == 0) - value &= ~AD1843_MNOM; - else - value |= AD1843_MNOM; - ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value); - break; - - case AD1843_HPO_MUTE: - value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); - if (mc->un.ord == 0) - value &= ~AD1843_HPOM; - else - value |= AD1843_HPOM; - ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value); - value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); - break; - - default: - return (EINVAL); - } - - return (0); -} - -int -mavb_get_port(void *hdl, struct mixer_ctrl *mc) -{ - struct mavb_softc *sc = (struct mavb_softc *)hdl; - u_char left, right; - ad1843_addr_t reg; - u_int16_t value; - - DPRINTF(1, ("%s: mavb_get_port: dev=%d\n", sc->sc_dev.dv_xname, - mc->dev)); - - switch (mc->dev) { - case AD1843_ADC_SOURCE: - value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN); - mc->un.ord = (value & AD1843_LSS_MASK) >> AD1843_LSS_SHIFT; - break; - case AD1843_ADC_GAIN: - value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN); - left = (value & AD1843_LIG_MASK) >> AD1843_LIG_SHIFT; - right = (value & AD1843_RIG_MASK) >> AD1843_RIG_SHIFT; - mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = - (left << 4) | left; - mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = - (right << 4) | right; - break; - case AD1843_ADC_MIC_GAIN: - value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN); - mc->un.ord = (value & AD1843_LMGE) ? 1 : 0; - break; - - case AD1843_DAC1_GAIN: - value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); - left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT; - right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT; - mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = - AUDIO_MAX_GAIN - (left << 2); - mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = - AUDIO_MAX_GAIN - (right << 2); - break; - case AD1843_DAC1_MUTE: - value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); - mc->un.ord = (value & AD1843_LDA1GM) ? 1 : 0; - break; - - case AD1843_DAC2_GAIN: - case AD1843_AUX1_GAIN: - case AD1843_AUX2_GAIN: - case AD1843_AUX3_GAIN: - case AD1843_MIC_GAIN: - reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN; - value = ad1843_reg_read(sc, reg); - left = (value & AD1843_LD2M_MASK) >> AD1843_LD2M_SHIFT; - right = (value & AD1843_RD2M_MASK) >> AD1843_RD2M_SHIFT; - mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = - AUDIO_MAX_GAIN - (left << 3); - mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = - AUDIO_MAX_GAIN - (right << 3); - break; - case AD1843_MONO_GAIN: - if (mc->un.value.num_channels != 1) - return (EINVAL); - - value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); - left = (value & AD1843_MNM_MASK) >> AD1843_MNM_SHIFT; - mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = - AUDIO_MAX_GAIN - (left << 3); - break; - case AD1843_DAC2_MUTE: - case AD1843_AUX1_MUTE: - case AD1843_AUX2_MUTE: - case AD1843_AUX3_MUTE: - case AD1843_MIC_MUTE: - case AD1843_MONO_MUTE: /* matches left channel */ - reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE; - value = ad1843_reg_read(sc, reg); - mc->un.ord = (value & AD1843_LD2MM) ? 1 : 0; - break; - - case AD1843_SUM_MUTE: - value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); - mc->un.ord = (value & AD1843_SUMM) ? 1 : 0; - break; - - case AD1843_MNO_MUTE: - value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); - mc->un.ord = (value & AD1843_MNOM) ? 1 : 0; - break; - - case AD1843_HPO_MUTE: - value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); - mc->un.ord = (value & AD1843_HPOM) ? 1 : 0; - break; - - default: - return (EINVAL); - } - - return (0); -} - -int -mavb_query_devinfo(void *hdl, struct mixer_devinfo *di) -{ - int i; - - di->prev = di->next = AUDIO_MIXER_LAST; - - switch (di->index) { - case AD1843_RECORD_CLASS: - di->type = AUDIO_MIXER_CLASS; - di->mixer_class = AD1843_RECORD_CLASS; - strlcpy(di->label.name, AudioCrecord, sizeof di->label.name); - break; - - case AD1843_ADC_SOURCE: - di->type = AUDIO_MIXER_ENUM; - di->mixer_class = AD1843_RECORD_CLASS; - di->next = AD1843_ADC_GAIN; - strlcpy(di->label.name, AudioNsource, sizeof di->label.name); - di->un.e.num_mem = - sizeof ad1843_source / sizeof ad1843_source[1]; - for (i = 0; i < di->un.e.num_mem; i++) { - strlcpy(di->un.e.member[i].label.name, - ad1843_source[i], - sizeof di->un.e.member[0].label.name); - di->un.e.member[i].ord = i; - } - break; - case AD1843_ADC_GAIN: - di->type = AUDIO_MIXER_VALUE; - di->mixer_class = AD1843_RECORD_CLASS; - di->prev = AD1843_ADC_SOURCE; - strlcpy(di->label.name, AudioNvolume, sizeof di->label.name); - di->un.v.num_channels = 2; - strlcpy(di->un.v.units.name, AudioNvolume, - sizeof di->un.v.units.name); - break; - case AD1843_ADC_MIC_GAIN: - di->type = AUDIO_MIXER_ENUM; - di->mixer_class = AD1843_RECORD_CLASS; - strlcpy(di->label.name, AudioNmicrophone "." AudioNpreamp, - sizeof di->label.name); - di->un.e.num_mem = 2; - strlcpy(di->un.e.member[0].label.name, AudioNoff, - sizeof di->un.e.member[0].label.name); - di->un.e.member[0].ord = 0; - strlcpy(di->un.e.member[1].label.name, AudioNon, - sizeof di->un.e.member[1].label.name); - di->un.e.member[1].ord = 1; - break; - - case AD1843_INPUT_CLASS: - di->type = AUDIO_MIXER_CLASS; - di->mixer_class = AD1843_INPUT_CLASS; - strlcpy(di->label.name, AudioCinputs, sizeof di->label.name); - break; - - case AD1843_DAC1_GAIN: - di->type = AUDIO_MIXER_VALUE; - di->mixer_class = AD1843_INPUT_CLASS; - di->next = AD1843_DAC1_MUTE; - strlcpy(di->label.name, AudioNdac "1", sizeof di->label.name); - di->un.v.num_channels = 2; - strlcpy(di->un.v.units.name, AudioNvolume, - sizeof di->un.v.units.name); - break; - case AD1843_DAC1_MUTE: - di->type = AUDIO_MIXER_ENUM; - di->mixer_class = AD1843_INPUT_CLASS; - di->prev = AD1843_DAC1_GAIN; - strlcpy(di->label.name, AudioNmute, sizeof di->label.name); - di->un.e.num_mem = 2; - strlcpy(di->un.e.member[0].label.name, AudioNoff, - sizeof di->un.e.member[0].label.name); - di->un.e.member[0].ord = 0; - strlcpy(di->un.e.member[1].label.name, AudioNon, - sizeof di->un.e.member[1].label.name); - di->un.e.member[1].ord = 1; - break; - - case AD1843_DAC2_GAIN: - case AD1843_AUX1_GAIN: - case AD1843_AUX2_GAIN: - case AD1843_AUX3_GAIN: - case AD1843_MIC_GAIN: - case AD1843_MONO_GAIN: - di->type = AUDIO_MIXER_VALUE; - di->mixer_class = AD1843_INPUT_CLASS; - di->next = di->index + AD1843_DAC2_MUTE - AD1843_DAC2_GAIN; - strlcpy(di->label.name, - ad1843_input[di->index - AD1843_DAC2_GAIN], - sizeof di->label.name); - if (di->index == AD1843_MONO_GAIN) - di->un.v.num_channels = 1; - else - di->un.v.num_channels = 2; - strlcpy(di->un.v.units.name, AudioNvolume, - sizeof di->un.v.units.name); - break; - case AD1843_DAC2_MUTE: - case AD1843_AUX1_MUTE: - case AD1843_AUX2_MUTE: - case AD1843_AUX3_MUTE: - case AD1843_MIC_MUTE: - case AD1843_MONO_MUTE: - di->type = AUDIO_MIXER_ENUM; - di->mixer_class = AD1843_INPUT_CLASS; - di->prev = di->index + AD1843_DAC2_GAIN - AD1843_DAC2_MUTE; - strlcpy(di->label.name, AudioNmute, sizeof di->label.name); - di->un.e.num_mem = 2; - strlcpy(di->un.e.member[0].label.name, AudioNoff, - sizeof di->un.e.member[0].label.name); - di->un.e.member[0].ord = 0; - strlcpy(di->un.e.member[1].label.name, AudioNon, - sizeof di->un.e.member[1].label.name); - di->un.e.member[1].ord = 1; - break; - - case AD1843_SUM_MUTE: - di->type = AUDIO_MIXER_ENUM; - di->mixer_class = AD1843_INPUT_CLASS; - strlcpy(di->label.name, "sum." AudioNmute, - sizeof di->label.name); - di->un.e.num_mem = 2; - strlcpy(di->un.e.member[0].label.name, AudioNoff, - sizeof di->un.e.member[0].label.name); - di->un.e.member[0].ord = 0; - strlcpy(di->un.e.member[1].label.name, AudioNon, - sizeof di->un.e.member[1].label.name); - di->un.e.member[1].ord = 1; - break; - - case AD1843_OUTPUT_CLASS: - di->type = AUDIO_MIXER_CLASS; - di->mixer_class = AD1843_OUTPUT_CLASS; - strlcpy(di->label.name, AudioCoutputs, sizeof di->label.name); - break; - - case AD1843_MNO_MUTE: - di->type = AUDIO_MIXER_ENUM; - di->mixer_class = AD1843_OUTPUT_CLASS; - strlcpy(di->label.name, AudioNmono "." AudioNmute, - sizeof di->label.name); - di->un.e.num_mem = 2; - strlcpy(di->un.e.member[0].label.name, AudioNoff, - sizeof di->un.e.member[0].label.name); - di->un.e.member[0].ord = 0; - strlcpy(di->un.e.member[1].label.name, AudioNon, - sizeof di->un.e.member[1].label.name); - di->un.e.member[1].ord = 1; - break; - - case AD1843_HPO_MUTE: - di->type = AUDIO_MIXER_ENUM; - di->mixer_class = AD1843_OUTPUT_CLASS; - strlcpy(di->label.name, AudioNheadphone "." AudioNmute, - sizeof di->label.name); - di->un.e.num_mem = 2; - strlcpy(di->un.e.member[0].label.name, AudioNoff, - sizeof di->un.e.member[0].label.name); - di->un.e.member[0].ord = 0; - strlcpy(di->un.e.member[1].label.name, AudioNon, - sizeof di->un.e.member[1].label.name); - di->un.e.member[1].ord = 1; - break; - - default: - return (EINVAL); - } - - return (0); -} - -int -mavb_get_props(void *hdl) -{ - return (AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT); -} - -static void -mavb_dma_output(struct mavb_softc *sc) -{ - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - u_int64_t write_ptr; - caddr_t src, dst, end; - int count; - - write_ptr = bus_space_read_8(st, sh, MAVB_CHANNEL2_WRITE_PTR); - - end = sc->play.hw_start + MAVB_CHAN_RING_SIZE; - dst = sc->play.hw_start + write_ptr; - src = sc->play.sw_cur; - - if (write_ptr % MAVB_CHAN_CHUNK_SIZE) { - printf("%s: write_ptr=%lld\n", sc->sc_dev.dv_xname, write_ptr); - return; - } - if ((src - sc->play.sw_start) % MAVB_CHAN_CHUNK_SIZE) { - printf("%s: src=%ld\n", sc->sc_dev.dv_xname, - src - sc->play.sw_start); - return; - } - - count = MAVB_CHAN_INTR_SIZE / MAVB_CHAN_CHUNK_SIZE; - while (--count >= 0) { - memcpy(dst, src, MAVB_CHAN_CHUNK_SIZE); - dst += MAVB_CHAN_CHUNK_SIZE; - src += MAVB_CHAN_CHUNK_SIZE; - if (dst >= end) - dst = sc->play.hw_start; - if (src >= sc->play.sw_end) - src = sc->play.sw_start; - if (!((src - sc->play.sw_start) % sc->play.blksize)) { - if (sc->play.intr) - sc->play.intr(sc->play.intrarg); - } - } - write_ptr = dst - sc->play.hw_start; - bus_space_write_8(st, sh, MAVB_CHANNEL2_WRITE_PTR, write_ptr); - sc->play.sw_cur = src; -} - -static void -mavb_dma_input(struct mavb_softc *sc) -{ - bus_space_tag_t st = sc->sc_st; - bus_space_handle_t sh = sc->sc_sh; - u_int64_t read_ptr; - caddr_t src, dst, end; - int count; - - read_ptr = bus_space_read_8(st, sh, MAVB_CHANNEL1_READ_PTR); - - end = sc->rec.hw_start + MAVB_CHAN_RING_SIZE; - src = sc->rec.hw_start + read_ptr; - dst = sc->rec.sw_cur; - - if (read_ptr % MAVB_CHAN_CHUNK_SIZE) { - printf("%s: read_ptr=%lld\n", sc->sc_dev.dv_xname, read_ptr); - return; - } - if ((dst - sc->rec.sw_start) % MAVB_CHAN_CHUNK_SIZE) { - printf("%s: dst=%ld\n", sc->sc_dev.dv_xname, - dst - sc->rec.sw_start); - return; - } - - count = MAVB_CHAN_INTR_SIZE / MAVB_CHAN_CHUNK_SIZE; - while (--count >= 0) { - memcpy(dst, src, MAVB_CHAN_CHUNK_SIZE); - dst += MAVB_CHAN_CHUNK_SIZE; - src += MAVB_CHAN_CHUNK_SIZE; - if (src >= end) - src = sc->rec.hw_start; - if (dst >= sc->rec.sw_end) - dst = sc->rec.sw_start; - if (!((dst - sc->rec.sw_start) % sc->rec.blksize)) { - if (sc->rec.intr) - sc->rec.intr(sc->rec.intrarg); - } - } - read_ptr = src - sc->rec.hw_start; - bus_space_write_8(st, sh, MAVB_CHANNEL1_READ_PTR, read_ptr); - sc->rec.sw_cur = dst; -} - -int -mavb_trigger_output(void *hdl, void *start, void *end, int blksize, - void (*intr)(void *), void *intrarg, struct audio_params *param) -{ - struct mavb_softc *sc = (struct mavb_softc *)hdl; - - DPRINTF(1, ("%s: mavb_trigger_output: start=%p end=%p " - "blksize=%d intr=%p(%p)\n", sc->sc_dev.dv_xname, - start, end, blksize, intr, intrarg)); - - mtx_enter(&audio_lock); - sc->play.blksize = blksize; - sc->play.intr = intr; - sc->play.intrarg = intrarg; - - sc->play.sw_start = sc->play.sw_cur = start; - sc->play.sw_end = end; - - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, - MAVB_CHANNEL_RESET); - delay(1000); - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0); - - /* Fill first 25% of buffer with silence. */ - bzero(sc->play.hw_start, MAVB_CHAN_CHUNK_SIZE); - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_WRITE_PTR, - MAVB_CHAN_CHUNK_SIZE); - - /* Fill next 50% of buffer with audio data. */ - mavb_dma_output(sc); - - /* The buffer is now 75% full. Start DMA and get interrupts - * when the buffer is 25% full. The interrupt handler fills - * in 50% of the buffer size, putting it back to 75% full. - */ - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, - MAVB_CHANNEL_DMA_ENABLE | MAVB_CHANNEL_INT_25); - mtx_leave(&audio_lock); - return (0); -} - -int -mavb_trigger_input(void *hdl, void *start, void *end, int blksize, - void (*intr)(void *), void *intrarg, struct audio_params *param) -{ - struct mavb_softc *sc = (struct mavb_softc *)hdl; - - DPRINTF(1, ("%s: mavb_trigger_output: start=%p end=%p " - "blksize=%d intr=%p(%p)\n", sc->sc_dev.dv_xname, - start, end, blksize, intr, intrarg)); - - mtx_enter(&audio_lock); - sc->rec.blksize = blksize; - sc->rec.intr = intr; - sc->rec.intrarg = intrarg; - - sc->rec.sw_start = sc->rec.sw_cur = start; - sc->rec.sw_end = end; - - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL1_CONTROL, - MAVB_CHANNEL_RESET); - delay(1000); - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL1_CONTROL, 0); - - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL1_CONTROL, - MAVB_CHANNEL_DMA_ENABLE | MAVB_CHANNEL_INT_50); - mtx_leave(&audio_lock); - return (0); -} - -static void -mavb_button_repeat(void *hdl) -{ - struct mavb_softc *sc = (struct mavb_softc *)hdl; - u_int64_t intmask, control; - u_int16_t value, left, right; - - DPRINTF(1, ("%s: mavb_repeat called\n", sc->sc_dev.dv_xname)); - -#define MAVB_CONTROL_VOLUME_BUTTONS \ - (MAVB_CONTROL_VOLUME_BUTTON_UP | MAVB_CONTROL_VOLUME_BUTTON_DOWN) - - control = bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL); - if (control & MAVB_CONTROL_VOLUME_BUTTONS) { - value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); - left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT; - right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT; - if (control & MAVB_CONTROL_VOLUME_BUTTON_UP) { - control &= ~MAVB_CONTROL_VOLUME_BUTTON_UP; - if (left > 0) - left--; /* attenuation! */ - if (right > 0) - right--; - } - if (control & MAVB_CONTROL_VOLUME_BUTTON_DOWN) { - control &= ~MAVB_CONTROL_VOLUME_BUTTON_DOWN; - if (left < 63) - left++; - if (right < 63) - right++; - } - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, control); - - value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK); - value |= (left << AD1843_LDA1G_SHIFT); - value |= (right << AD1843_RDA1G_SHIFT); - ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value); - - timeout_add_msec(&sc->sc_volume_button_to, - MAVB_VOLUME_BUTTON_REPEAT_DELN); - } else { - /* Enable volume button interrupts again. */ - intmask = bus_space_read_8(sc->sc_st, sc->sc_isash, - MACE_ISA_INT_MASK); - bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK, - intmask | MACE_ISA_INT_AUDIO_SC); - } -} - -static int -mavb_intr(void *arg) -{ - struct mavb_softc *sc = arg; - u_int64_t intstat, intmask; - - mtx_enter(&audio_lock); - intstat = bus_space_read_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_STAT); - DPRINTF(MAVB_DEBUG_INTR, ("%s: mavb_intr: intstat = 0x%lx\n", - sc->sc_dev.dv_xname, intstat)); - - if (intstat & MACE_ISA_INT_AUDIO_SC) { - /* Disable volume button interrupts. */ - intmask = bus_space_read_8(sc->sc_st, sc->sc_isash, - MACE_ISA_INT_MASK); - bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK, - intmask & ~MACE_ISA_INT_AUDIO_SC); - - timeout_add_msec(&sc->sc_volume_button_to, - MAVB_VOLUME_BUTTON_REPEAT_DEL1); - } - - if (intstat & MACE_ISA_INT_AUDIO_DMA1) - mavb_dma_input(sc); - - if (intstat & MACE_ISA_INT_AUDIO_DMA2) - mavb_dma_output(sc); - mtx_leave(&audio_lock); - return 1; -} - -int -mavb_match(struct device *parent, void *match, void *aux) -{ - struct macebus_attach_args *maa = aux; - bus_space_handle_t ioh; - u_int64_t control; - - if (bus_space_map(maa->maa_iot, maa->maa_baseaddr, MAVB_NREGS, 0, - &ioh) != 0) - return (0); - control = bus_space_read_8(maa->maa_iot, ioh, MAVB_CONTROL); - bus_space_unmap(maa->maa_iot, ioh, MAVB_NREGS); - - return ((control & MAVB_CONTROL_CODEC_PRESENT) != 0); -} - -void -mavb_attach(struct device *parent, struct device *self, void *aux) -{ - struct mavb_softc *sc = (void *)self; - struct macebus_attach_args *maa = aux; - bus_dma_segment_t seg; - u_int16_t value; - int rseg; - - sc->sc_st = maa->maa_iot; - if (bus_space_map(sc->sc_st, maa->maa_baseaddr, MAVB_NREGS, 0, - &sc->sc_sh) != 0) { - printf(": can't map i/o space\n"); - return; - } - - /* XXX We need access to some of the MACE ISA registers. */ - extern bus_space_handle_t mace_h; - bus_space_subregion(sc->sc_st, mace_h, 0, MAVB_ISA_NREGS, - &sc->sc_isash); - - /* Set up DMA structures. */ - sc->sc_dmat = maa->maa_dmat; - if (bus_dmamap_create(sc->sc_dmat, MAVB_ISA_RING_SIZE, 1, - MAVB_ISA_RING_SIZE, 0, 0, &sc->sc_dmamap)) { - printf(": can't create MACE ISA DMA map\n"); - return; - } - - if (bus_dmamem_alloc(sc->sc_dmat, MAVB_ISA_RING_SIZE, - MACE_ISA_RING_ALIGN, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { - printf(": can't allocate ring buffer\n"); - return; - } - - if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, MAVB_ISA_RING_SIZE, - &sc->sc_ring, BUS_DMA_COHERENT)) { - printf(": can't map ring buffer\n"); - return; - } - - if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_ring, - MAVB_ISA_RING_SIZE, NULL, BUS_DMA_NOWAIT)) { - printf(": can't load MACE ISA DMA map\n"); - return; - } - - sc->rec.hw_start = sc->sc_ring; - sc->play.hw_start = sc->sc_ring + MAVB_CHAN_RING_SIZE; - - bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_RING_BASE, - sc->sc_dmamap->dm_segs[0].ds_addr); - - /* Establish interrupt. */ - macebus_intr_establish(maa->maa_intr, maa->maa_mace_intr, - IPL_AUDIO, mavb_intr, sc, sc->sc_dev.dv_xname); - - /* 2. Assert the RESET signal. */ - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, - MAVB_CONTROL_RESET); - delay(1); /* at least 100 ns */ - - /* 3. Deassert the RESET signal and enter a wait period to - allow the AD1843 internal clocks and the external - crystal oscillator to stabilize. */ - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, 0); - delay(800); /* typically 400 us to 800 us */ - if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_INIT) { - printf(": codec not ready\n"); - return; - } - - /* 4. Put the conversion sources into standby. */ - value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS); - ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS, - value & ~AD1843_PDNI); - delay (500000); /* approximately 474 ms */ - if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_PDNO) { - printf(": can't power up conversion resources\n"); - return; - } - - /* 5. Power up the clock generators and enable clock output pins. */ - value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS); - ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS, - value | AD1843_C1EN | AD1843_C2EN); - - /* 6. Configure conversion resources while they are in standby. */ - value = ad1843_reg_read(sc, AD1843_SERIAL_INTERFACE); - ad1843_reg_write(sc, AD1843_SERIAL_INTERFACE, value | AD1843_ADTLK); - value = ad1843_reg_read(sc, AD1843_CHANNEL_SAMPLE_RATE); - ad1843_reg_write(sc, AD1843_CHANNEL_SAMPLE_RATE, - value | (2 << AD1843_DA1C_SHIFT) | - (1 << AD1843_ADRC_SHIFT) | (1 << AD1843_ADLC_SHIFT)); - - /* 7. Enable conversion resources. */ - value = ad1843_reg_read(sc, AD1843_CHANNEL_POWER_DOWN); - ad1843_reg_write(sc, AD1843_CHANNEL_POWER_DOWN, - value | (AD1843_DA1EN | AD1843_ANAEN | AD1843_AAMEN | - AD1843_ADREN | AD1843_ADLEN)); - - /* 8. Configure conversion resources while they are enabled. */ - value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN); - ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, - value & ~(AD1843_LDA1GM | AD1843_RDA1GM)); - value = ad1843_reg_read(sc, AD1843_DAC1_DIGITAL_GAIN); - ad1843_reg_write(sc, AD1843_DAC1_DIGITAL_GAIN, - value & ~(AD1843_LDA1AM | AD1843_RDA1AM)); - value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS); - ad1843_reg_write(sc, AD1843_MISC_SETTINGS, - value & ~(AD1843_HPOM | AD1843_MNOM)); - - value = ad1843_reg_read(sc, AD1843_CODEC_STATUS); - printf(": AD1843 rev %d\n", (u_int)value & AD1843_REVISION_MASK); - - sc->play.rate = sc->rec.rate = 48000; - sc->play.format = sc->rec.format = AD1843_PCM8; - - timeout_set(&sc->sc_volume_button_to, mavb_button_repeat, sc); - - audio_attach_mi(&mavb_sa_hw_if, sc, &sc->sc_dev); - - return; -} - -u_int16_t -ad1843_reg_read(struct mavb_softc *sc, ad1843_addr_t addr) -{ - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL, - (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT | - MAVB_CODEC_READ); - delay(200); - return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS); -} - -u_int16_t -ad1843_reg_write(struct mavb_softc *sc, ad1843_addr_t addr, u_int16_t value) -{ - bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL, - (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT | - (value & MAVB_CODEC_WORD_MASK) << MAVB_CODEC_WORD_SHIFT); - delay(200); - return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS); -} - -void -ad1843_dump_regs(struct mavb_softc *sc) -{ - u_int16_t addr; - - for (addr = 0; addr < AD1843_NREGS; addr++) - printf("%d: 0x%04x\n", addr, ad1843_reg_read(sc, addr)); -} diff --git a/sys/arch/sgi/dev/mavbreg.h b/sys/arch/sgi/dev/mavbreg.h deleted file mode 100644 index 37379806a6f..00000000000 --- a/sys/arch/sgi/dev/mavbreg.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $OpenBSD: mavbreg.h,v 1.1 2005/01/02 19:25:41 kettenis Exp $ */ - -/* - * Copyright (c) 2005 Mark Kettenis - * - * 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. - */ - -/* - * MACE Moosehead A/V Board register definitions. - */ - -#define MAVB_CONTROL 0x00 -#define MAVB_CONTROL_RESET 0x0000000000000001 -#define MAVB_CONTROL_CODEC_PRESENT 0x0000000000000002 -#define MAVB_CONTROL_VOLUME_BUTTON_UP 0x0000000001000000 -#define MAVB_CONTROL_VOLUME_BUTTON_DOWN 0x0000000000800000 - -#define MAVB_CODEC_CONTROL 0x08 -#define MAVB_CODEC_READ 0x0000000000010000 -#define MAVB_CODEC_WORD_SHIFT 0 -#define MAVB_CODEC_WORD_MASK 0x000000000000ffff -#define MAVB_CODEC_ADDRESS_SHIFT 17 -#define MAVB_CODEC_ADDRESS_MASK 0x000000000000001f - -#define MAVB_CODEC_STATUS 0x18 -#define MAVB_CHANNEL1_CONTROL 0x20 -#define MAVB_CHANNEL2_CONTROL 0x40 -#define MAVB_CHANNEL3_CONTROL 0x60 -#define MAVB_CHANNEL_RESET 0x0000000000000400 -#define MAVB_CHANNEL_DMA_ENABLE 0x0000000000000200 -#define MAVB_CHANNEL_INT_DISABLED 0x0000000000000000 -#define MAVB_CHANNEL_INT_25 0x0000000000000020 -#define MAVB_CHANNEL_INT_50 0x0000000000000040 -#define MAVB_CHANNEL_INT_75 0x0000000000000060 -#define MAVB_CHANNEL_INT_EMPTY 0x0000000000000080 -#define MAVB_CHANNEL_INT_NOT_EMPTY 0x00000000000000a0 -#define MAVB_CHANNEL_INT_FULL 0x00000000000000c0 -#define MAVB_CHANNEL_INT_NOT_FULL 0x00000000000000e0 - -#define MAVB_CHANNEL1_READ_PTR 0x28 -#define MAVB_CHANNEL1_WRITE_PTR 0x30 -#define MAVB_CHANNEL1_DEPTH 0x38 -#define MAVB_CHANNEL2_READ_PTR 0x48 -#define MAVB_CHANNEL2_WRITE_PTR 0x50 -#define MAVB_CHANNEL2_DEPTH 0x58 - -#define MAVB_NREGS 0x80 diff --git a/sys/arch/sgi/dev/mkbc.c b/sys/arch/sgi/dev/mkbc.c deleted file mode 100644 index c4bbb622e19..00000000000 --- a/sys/arch/sgi/dev/mkbc.c +++ /dev/null @@ -1,927 +0,0 @@ -/* $OpenBSD: mkbc.c,v 1.15 2019/10/17 13:42:15 cheloha Exp $ */ - -/* - * Copyright (c) 2006, 2007, Joel Sing - * All rights reserved - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF MIND, - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Derived from sys/dev/ic/pckbc.c under the following terms: - * $NetBSD: pckbc.c,v 1.5 2000/06/09 04:58:35 soda Exp $ */ - -/* - * Copyright (c) 1998 - * Matthias Drochner. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Driver for Moosehead PS/2 Controllers (mkbc) - * - * There are actually two separate controllers attached to the macebus. - * However in the interest of reusing code, we want to act like a pckbc(4) - * so that we can directly attach pckbd(4) and pms(4). As a result, we make - * each controller look like a "slot" and combine them into a single device. - * - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/malloc.h> -#include <sys/timeout.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/signalvar.h> -#include <sys/errno.h> -#include <sys/queue.h> - -#include <machine/autoconf.h> -#include <machine/bus.h> - -#include <mips64/archtype.h> - -#include <sgi/localbus/crimebus.h> -#include <sgi/localbus/macebusvar.h> - -#include <dev/ic/pckbcvar.h> -#include <dev/pckbc/pckbdvar.h> - -#include "mkbcreg.h" - -const char *mkbc_slot_names[] = { "kbd", "mouse" }; - -#define KBC_DEVCMD_ACK 0xfa -#define KBC_DEVCMD_RESEND 0xfe - -#define KBD_DELAY DELAY(8) - -struct mkbc_softc { - struct pckbc_softc sc_pckbc; - bus_space_tag_t iot; - bus_space_handle_t ioh; -}; - -int mkbc_match(struct device *, void *, void *); -void mkbc_attach(struct device *, struct device *, void *); - -struct cfattach mkbc_ca = { - sizeof(struct mkbc_softc), mkbc_match, mkbc_attach -}; - -struct cfdriver mkbc_cd = { - NULL, "mkbc", DV_DULL -}; - -/* Descriptor for one device command. */ -struct pckbc_devcmd { - TAILQ_ENTRY(pckbc_devcmd) next; - int flags; -#define KBC_CMDFLAG_SYNC 1 /* Give descriptor back to caller. */ -#define KBC_CMDFLAG_SLOW 2 - u_char cmd[4]; - int cmdlen, cmdidx, retries; - u_char response[4]; - int status, responselen, responseidx; -}; - -/* Data per slave device. */ -struct pckbc_slotdata { - int polling; /* Don't read data port in interrupt handler. */ - TAILQ_HEAD(, pckbc_devcmd) cmdqueue; /* Active commands. */ - TAILQ_HEAD(, pckbc_devcmd) freequeue; /* Free commands. */ -#define NCMD 5 - struct pckbc_devcmd cmds[NCMD]; - bus_space_handle_t ioh; -}; - -#define CMD_IN_QUEUE(q) (TAILQ_FIRST(&(q)->cmdqueue) != NULL) - -static int mkbc_console; -static struct pckbc_slotdata mkbc_cons_slotdata; -struct pckbc_internal mkbc_consdata; - -void mkbc_start(struct pckbc_internal *, pckbc_slot_t); -int mkbc_attach_slot(struct mkbc_softc *, pckbc_slot_t); -void mkbc_init_slotdata(struct pckbc_slotdata *); -int mkbc_submatch(struct device *, void *, void *); -int mkbcprint(void *, const char *); -int mkbcintr(void *); -int mkbcintr_internal(struct pckbc_internal *, struct pckbc_softc *); -void mkbc_cleanqueue(struct pckbc_slotdata *); -void mkbc_cleanup(void *); -void mkbc_poll(void *); -int mkbc_cmdresponse(struct pckbc_internal *, pckbc_slot_t, u_char); -int mkbc_poll_read(bus_space_tag_t, bus_space_handle_t); -int mkbc_poll_write(bus_space_tag_t, bus_space_handle_t, int); - -int -mkbc_match(struct device *parent, void *cf, void *aux) -{ - return 1; -} - -void -mkbc_init_slotdata(struct pckbc_slotdata *q) -{ - int i; - TAILQ_INIT(&q->cmdqueue); - TAILQ_INIT(&q->freequeue); - - for (i = 0; i < NCMD; i++) { - TAILQ_INSERT_TAIL(&q->freequeue, &(q->cmds[i]), next); - } - q->polling = 0; -} - -int -mkbcprint(void *aux, const char *pnp) -{ - struct pckbc_attach_args *pa = aux; - - if (!pnp) - printf(" (%s slot)", mkbc_slot_names[pa->pa_slot]); - - return (QUIET); -} - -int -mkbc_submatch(struct device *parent, void *match, void *aux) -{ - struct cfdata *cf = match; - struct pckbc_attach_args *pa = aux; - - if (cf->cf_loc[PCKBCCF_SLOT] != PCKBCCF_SLOT_DEFAULT && - cf->cf_loc[PCKBCCF_SLOT] != pa->pa_slot) - return (0); - return ((*cf->cf_attach->ca_match)(parent, cf, aux)); -} - -int -mkbc_attach_slot(struct mkbc_softc *msc, pckbc_slot_t slot) -{ - struct pckbc_softc *sc = &msc->sc_pckbc; - struct pckbc_internal *t = sc->id; - struct pckbc_attach_args pa; - bus_space_handle_t ioh; - int found; - - if (!t->t_slotdata[slot]) { - - t->t_slotdata[slot] = malloc(sizeof(struct pckbc_slotdata), - M_DEVBUF, M_NOWAIT); - - if (t->t_slotdata[slot] == NULL) { - printf("Failed to allocate slot data!\n"); - return 0; - } - mkbc_init_slotdata(t->t_slotdata[slot]); - - /* Map subregion of bus space for this "slot". */ - if (bus_space_subregion(msc->iot, msc->ioh, - MKBC_PORTSIZE * slot, MKBC_PORTSIZE, &ioh)) { - printf("Unable to map slot subregion!\n"); - return 0; - } - t->t_slotdata[slot]->ioh = ioh; - - /* Initialise controller. */ - bus_space_write_8(msc->iot, ioh, MKBC_CONTROL, - MKBC_CONTROL_TX_CLOCK_DISABLE | MKBC_CONTROL_RESET); - delay(100); /* 100us */ - - /* Enable controller. */ - bus_space_write_8(t->t_iot, t->t_slotdata[slot]->ioh, - MKBC_CONTROL, - MKBC_CONTROL_RX_CLOCK_ENABLE | MKBC_CONTROL_TX_ENABLE); - - } - - pa.pa_tag = t; - pa.pa_slot = slot; - found = (config_found_sm((struct device *)msc, &pa, - mkbcprint, mkbc_submatch) != NULL); - - return (found); -} - -void -mkbc_attach(struct device *parent, struct device *self, void *aux) -{ - struct mkbc_softc *msc = (void*)self; - struct macebus_attach_args *maa = aux; - struct pckbc_softc *sc = &msc->sc_pckbc; - struct pckbc_internal *t; - - if (mkbc_console == 0) { - - /* Setup bus space mapping. */ - msc->iot = maa->maa_iot; - if (bus_space_map(msc->iot, maa->maa_baseaddr, - MKBC_PORTSIZE * 2, 0, &msc->ioh)) { - printf(": unable to map bus space!\n"); - return; - } - - /* Setup pckbc_internal structure. */ - t = malloc(sizeof(struct pckbc_internal), M_DEVBUF, - M_WAITOK | M_ZERO); - t->t_iot = msc->iot; - t->t_ioh_d = 0; - t->t_ioh_c = 0; - t->t_addr = maa->maa_baseaddr; - t->t_sc = (struct pckbc_softc *)msc; - sc->id = t; - - timeout_set(&t->t_cleanup, mkbc_cleanup, t); - timeout_set(&t->t_poll, mkbc_poll, t); - - } else { - - /* Things have already been setup in mkbc_cnattach. */ - msc->iot = mkbc_consdata.t_iot; - msc->ioh = mkbc_consdata.t_ioh_d; - mkbc_consdata.t_sc = (struct pckbc_softc *)msc; - sc->id = &mkbc_consdata; - - } - - /* Establish interrupt handler. */ - if (macebus_intr_establish(maa->maa_intr, maa->maa_mace_intr, - IPL_TTY, mkbcintr, msc, sc->sc_dv.dv_xname)) - printf("\n"); - else - printf(": unable to establish interrupt\n"); - - /* - * Attach "slots" - technically these are separate controllers - * in the same bus space, however we want to act like pckbc(4) so - * that we can attach pckbd(4) and pms(4). - */ - mkbc_attach_slot(msc, PCKBC_KBD_SLOT); - mkbc_attach_slot(msc, PCKBC_AUX_SLOT); -} - -int -mkbcintr(void *vsc) -{ - struct mkbc_softc *msc = (struct mkbc_softc *)vsc; - struct pckbc_softc *sc = &msc->sc_pckbc; - struct pckbc_internal *t = sc->id; - - return mkbcintr_internal(t, sc); -} - -int -mkbcintr_internal(struct pckbc_internal *t, struct pckbc_softc *sc) -{ - pckbc_slot_t slot; - struct pckbc_slotdata *q; - int served = 0; - u_int64_t stat; - u_int64_t data; - - /* Reschedule timeout further into the idle times. */ - if (timeout_pending(&t->t_poll)) - timeout_add_sec(&t->t_poll, 1); - - /* - * Need to check both "slots" since interrupt could be from - * either controller. - */ - slot = PCKBC_KBD_SLOT; - q = t->t_slotdata[slot]; - for(;;) { - - if (!q) { - printf("mkbcintr: no kbd slot data!\n"); - break; - } - - stat = bus_space_read_8(t->t_iot, q->ioh, MKBC_STATUS); - if (!(stat & MKBC_STATUS_RX_FULL)) - break; - - served = 1; - - if (q->polling) - break; /* pckbc_poll_data() will get it */ - - KBD_DELAY; - data = bus_space_read_8(t->t_iot, q->ioh, MKBC_RX_PORT) & 0xff; - if (CMD_IN_QUEUE(q) && mkbc_cmdresponse(t, slot, data)) - continue; - - if (sc->inputhandler[slot]) - (*sc->inputhandler[slot])(sc->inputarg[slot], data); -#ifdef MKBCDEBUG - else - printf("mkbcintr: slot %d lost %d\n", slot, data); -#endif - } - - /* Mouse controller/slot. */ - slot = PCKBC_AUX_SLOT; - q = t->t_slotdata[slot]; - for(;;) { - - if (!q) { - printf("mkbcintr: no mouse slot data!\n"); - break; - } - - stat = bus_space_read_8(t->t_iot, q->ioh, MKBC_STATUS); - if (!(stat & MKBC_STATUS_RX_FULL)) - break; - - served = 1; - - if (q->polling) - break; /* pckbc_poll_data() will get it. */ - - KBD_DELAY; - data = bus_space_read_8(t->t_iot, q->ioh, MKBC_RX_PORT) & 0xff; - if (CMD_IN_QUEUE(q) && mkbc_cmdresponse(t, slot, data)) - continue; - - if (sc->inputhandler[slot]) - (*sc->inputhandler[slot])(sc->inputarg[slot], data); -#ifdef MKBCDEBUG - else - printf("mkbcintr: slot %d lost %d\n", slot, data); -#endif - } - - return (served); -} - -int -mkbc_poll_write(bus_space_tag_t iot, bus_space_handle_t ioh, int val) -{ - int timeout = 10000; - u_int64_t stat; - - /* Attempt to write a value to the controller. */ - while (timeout--) { - stat = bus_space_read_8(iot, ioh, MKBC_STATUS); - if (stat & MKBC_STATUS_TX_EMPTY) { - bus_space_write_8(iot, ioh, MKBC_TX_PORT, val & 0xff); - return 0; - } - delay(50); - } - return -1; -} - -int -mkbc_poll_read(bus_space_tag_t iot, bus_space_handle_t ioh) -{ - int timeout = 10000; - u_int64_t stat, val; - - /* Poll input from controller. */ - while (timeout--) { - stat = bus_space_read_8(iot, ioh, MKBC_STATUS); - if (stat & MKBC_STATUS_RX_FULL) { - val = bus_space_read_8(iot, ioh, MKBC_RX_PORT); - return val & 0xff; - } - delay(50); - } - return -1; -} - -/* - * Pass command to device, poll for ACK and data. - * to be called at spltty() - */ -static void -mkbc_poll_cmd(struct pckbc_internal *t, pckbc_slot_t slot, - struct pckbc_devcmd *cmd) -{ - bus_space_tag_t iot = t->t_iot; - bus_space_handle_t ioh = t->t_slotdata[slot]->ioh; - - int i, c = 0; - - while (cmd->cmdidx < cmd->cmdlen) { - if (mkbc_poll_write(iot, ioh, cmd->cmd[cmd->cmdidx]) == -1) { - printf("mkbc_poll_cmd: send error\n"); - cmd->status = EIO; - return; - } - for (i = 10; i; i--) { /* 1s ??? */ - c = mkbc_poll_read(iot, ioh); - if (c != -1) - break; - } - - if (c == KBC_DEVCMD_ACK) { - cmd->cmdidx++; - continue; - } - if (c == KBC_DEVCMD_RESEND) { -#ifdef MKBCDEBUG - printf("mkbc_cmd: RESEND\n"); -#endif - if (cmd->retries++ < 5) - continue; - else { -#ifdef MKBCDEBUG - printf("mkbc: cmd failed\n"); -#endif - cmd->status = EIO; - return; - } - } - if (c == -1) { -#ifdef MKBCDEBUG - printf("mkbc_cmd: timeout\n"); -#endif - cmd->status = EIO; - return; - } -#ifdef MKBCDEBUG - printf("mkbc_cmd: lost 0x%x\n", c); -#endif - } - - while (cmd->responseidx < cmd->responselen) { - if (cmd->flags & KBC_CMDFLAG_SLOW) - i = 100; /* 10s ??? */ - else - i = 10; /* 1s ??? */ - while (i--) { - c = mkbc_poll_read(iot, ioh); - if (c != -1) - break; - } - if (c == -1) { -#ifdef MKBCDEBUG - printf("mkbc_poll_cmd: no data\n"); -#endif - cmd->status = ETIMEDOUT; - return; - } else - cmd->response[cmd->responseidx++] = c; - } -} - -/* - * Clean up a command queue, throw away everything. - */ -void -mkbc_cleanqueue(struct pckbc_slotdata *q) -{ - struct pckbc_devcmd *cmd; -#ifdef MKBCDEBUG - int i; -#endif - - while ((cmd = TAILQ_FIRST(&q->cmdqueue))) { - TAILQ_REMOVE(&q->cmdqueue, cmd, next); -#ifdef MKBCDEBUG - printf("mkbc_cleanqueue: removing"); - for (i = 0; i < cmd->cmdlen; i++) - printf(" %02x", cmd->cmd[i]); - printf("\n"); -#endif - TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); - } -} - -/* - * Timeout error handler: clean queues and data port. - * XXX could be less invasive. - */ -void -mkbc_cleanup(void *self) -{ - struct pckbc_internal *t = self; - int s; - - printf("mkbc: command timeout\n"); - - s = spltty(); - - if (t->t_slotdata[PCKBC_KBD_SLOT]) - mkbc_cleanqueue(t->t_slotdata[PCKBC_KBD_SLOT]); - if (t->t_slotdata[PCKBC_AUX_SLOT]) - mkbc_cleanqueue(t->t_slotdata[PCKBC_AUX_SLOT]); - - while (mkbc_poll_read(t->t_iot, t->t_slotdata[PCKBC_KBD_SLOT]->ioh) - != -1) ; - while (mkbc_poll_read(t->t_iot, t->t_slotdata[PCKBC_AUX_SLOT]->ioh) - != -1) ; - - /* Reset KBC? */ - - splx(s); -} - -/* - * Pass command to device during normal operation. - * to be called at spltty() - */ -void -mkbc_start(struct pckbc_internal *t, pckbc_slot_t slot) -{ - struct pckbc_slotdata *q = t->t_slotdata[slot]; - struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue); - - if (q->polling) { - do { - mkbc_poll_cmd(t, slot, cmd); - if (cmd->status) - printf("mkbc_start: command error\n"); - - TAILQ_REMOVE(&q->cmdqueue, cmd, next); - if (cmd->flags & KBC_CMDFLAG_SYNC) - wakeup(cmd); - else { - timeout_del(&t->t_cleanup); - TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); - } - cmd = TAILQ_FIRST(&q->cmdqueue); - } while (cmd); - return; - } - - if (mkbc_poll_write(t->t_iot, t->t_slotdata[slot]->ioh, - cmd->cmd[cmd->cmdidx])) { - printf("mkbc_start: send error\n"); - /* XXX what now? */ - return; - } -} - -/* - * Handle command responses coming in asynchronously, - * return nonzero if valid response. - * to be called at spltty() - */ -int -mkbc_cmdresponse(struct pckbc_internal *t, pckbc_slot_t slot, u_char data) -{ - struct pckbc_slotdata *q = t->t_slotdata[slot]; - struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue); -#ifdef DIAGNOSTIC - if (!cmd) - panic("mkbc_cmdresponse: no active command"); -#endif - if (cmd->cmdidx < cmd->cmdlen) { - if (data != KBC_DEVCMD_ACK && data != KBC_DEVCMD_RESEND) - return (0); - - if (data == KBC_DEVCMD_RESEND) { - if (cmd->retries++ < 5) { - /* try again last command */ - goto restart; - } else { -#ifdef MKBCDEBUG - printf("mkbc: cmd failed\n"); -#endif - cmd->status = EIO; - /* dequeue */ - } - } else { - if (++cmd->cmdidx < cmd->cmdlen) - goto restart; - if (cmd->responselen) - return (1); - /* else dequeue */ - } - } else if (cmd->responseidx < cmd->responselen) { - cmd->response[cmd->responseidx++] = data; - if (cmd->responseidx < cmd->responselen) - return (1); - /* else dequeue */ - } else - return (0); - - /* dequeue: */ - TAILQ_REMOVE(&q->cmdqueue, cmd, next); - if (cmd->flags & KBC_CMDFLAG_SYNC) - wakeup(cmd); - else { - timeout_del(&t->t_cleanup); - TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); - } - if (!CMD_IN_QUEUE(q)) - return (1); -restart: - mkbc_start(t, slot); - return (1); -} - -/* - * Interfaces to act like pckbc(4). - */ - -int -pckbc_xt_translation(pckbc_tag_t self) -{ - /* Translation isn't supported... */ - return (-1); -} - -/* For use in autoconfiguration. */ -int -pckbc_poll_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len, - int responselen, u_char *respbuf, int slow) -{ - struct pckbc_devcmd nc; - int s; - - if ((len > 4) || (responselen > 4)) - return (EINVAL); - - bzero(&nc, sizeof(nc)); - bcopy(cmd, nc.cmd, len); - nc.cmdlen = len; - nc.responselen = responselen; - nc.flags = (slow ? KBC_CMDFLAG_SLOW : 0); - - s = spltty(); - mkbc_poll_cmd(self, slot, &nc); - splx(s); - - if (nc.status == 0 && respbuf) - bcopy(nc.response, respbuf, responselen); - - return (nc.status); -} - -void -pckbc_flush(pckbc_tag_t self, pckbc_slot_t slot) -{ - /* Read any data and discard. */ - struct pckbc_internal *t = self; - (void) mkbc_poll_read(t->t_iot, t->t_slotdata[slot]->ioh); -} - -/* - * Put command into the device's command queue, return zero or errno. - */ -int -pckbc_enqueue_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len, - int responselen, int sync, u_char *respbuf) -{ - struct pckbc_internal *t = self; - struct pckbc_slotdata *q = t->t_slotdata[slot]; - struct pckbc_devcmd *nc; - int s, isactive, res = 0; - - if ((len > 4) || (responselen > 4)) - return (EINVAL); - s = spltty(); - nc = TAILQ_FIRST(&q->freequeue); - if (nc) { - TAILQ_REMOVE(&q->freequeue, nc, next); - } - splx(s); - if (!nc) - return (ENOMEM); - - bzero(nc, sizeof(*nc)); - bcopy(cmd, nc->cmd, len); - nc->cmdlen = len; - nc->responselen = responselen; - nc->flags = (sync ? KBC_CMDFLAG_SYNC : 0); - - s = spltty(); - - if (q->polling && sync) { - /* - * XXX We should poll until the queue is empty. - * But we don't come here normally, so make - * it simple and throw away everything. - */ - mkbc_cleanqueue(q); - } - - isactive = CMD_IN_QUEUE(q); - TAILQ_INSERT_TAIL(&q->cmdqueue, nc, next); - if (!isactive) - mkbc_start(t, slot); - - if (q->polling) - res = (sync ? nc->status : 0); - else if (sync) { - if ((res = tsleep_nsec(nc, 0, "kbccmd", SEC_TO_NSEC(1)))) { - TAILQ_REMOVE(&q->cmdqueue, nc, next); - mkbc_cleanup(t); - } else - res = nc->status; - } else - timeout_add_sec(&t->t_cleanup, 1); - - if (sync) { - if (respbuf) - bcopy(nc->response, respbuf, responselen); - TAILQ_INSERT_TAIL(&q->freequeue, nc, next); - } - - splx(s); - - return (res); -} - -int -pckbc_poll_data(pckbc_tag_t self, pckbc_slot_t slot) -{ - struct pckbc_internal *t = self; - struct pckbc_slotdata *q = t->t_slotdata[slot]; - int c; - - c = mkbc_poll_read(t->t_iot, q->ioh); - if (c != -1 && q && CMD_IN_QUEUE(q)) { - /* We jumped into a running command - try to deliver the - response. */ - if (mkbc_cmdresponse(t, slot, c)) - return (-1); - } - return (c); -} - -void -pckbc_set_inputhandler(pckbc_tag_t self, pckbc_slot_t slot, pckbc_inputfcn func, - void *arg, char *name) -{ - struct pckbc_internal *t = (struct pckbc_internal *)self; - struct pckbc_softc *sc = t->t_sc; - - if (slot >= PCKBC_NSLOTS) - panic("mkbc_set_inputhandler: bad slot %d", slot); - - sc->inputhandler[slot] = func; - sc->inputarg[slot] = arg; - sc->subname[slot] = name; - - if (mkbc_console && slot == PCKBC_KBD_SLOT) - timeout_add_sec(&t->t_poll, 1); -} - -void -pckbc_slot_enable(pckbc_tag_t self, pckbc_slot_t slot, int on) -{ - struct pckbc_internal *t = (struct pckbc_internal *)self; - - /* - * Should we also enable/disable the controller?? - * If we did then none of the poll_ functions would work... - */ - - if (on) { - - /* Enable controller interrupts. */ - bus_space_write_8(t->t_iot, t->t_slotdata[slot]->ioh, - MKBC_CONTROL, - MKBC_CONTROL_RX_CLOCK_ENABLE | MKBC_CONTROL_TX_ENABLE - | MKBC_CONTROL_RX_INT_ENABLE); - - } else { - - /* Disable controller interrupts. */ - bus_space_write_8(t->t_iot, t->t_slotdata[slot]->ioh, - MKBC_CONTROL, - MKBC_CONTROL_RX_CLOCK_ENABLE | MKBC_CONTROL_TX_ENABLE); - - } - - if (slot == PCKBC_KBD_SLOT) { - if (on) - timeout_add_sec(&t->t_poll, 1); - else - timeout_del(&t->t_poll); - } -} - -void -pckbc_set_poll(pckbc_tag_t self, pckbc_slot_t slot, int on) -{ - struct pckbc_internal *t = (struct pckbc_internal *)self; - - t->t_slotdata[slot]->polling = on; - - if (!on) { - int s; - - /* - * If disabling polling on a device that's been configured, - * make sure there are no bytes left in the FIFO, holding up - * the interrupt line. Otherwise we won't get any further - * interrupts. - */ - if (t->t_sc) { - s = spltty(); - mkbcintr(t->t_sc); - splx(s); - } - } -} - -int -mkbc_cnattach(bus_space_tag_t iot, bus_addr_t addr) -{ - bus_space_handle_t ioh, slot_ioh; - int res = 0; - - /* Ensure that we're on an O2. */ - if (sys_config.system_type != SGI_O2) - return (ENXIO); - - if (bus_space_map(iot, addr, MKBC_PORTSIZE * 2, 0, &ioh)) - return (ENXIO); - - mkbc_consdata.t_addr = addr; - mkbc_consdata.t_iot = iot; - mkbc_consdata.t_ioh_d = ioh; - - /* Map subregion of bus space for this "slot". */ - if (bus_space_subregion(iot, ioh, 0, MKBC_PORTSIZE, &slot_ioh)) { - bus_space_unmap(iot, ioh, MKBC_PORTSIZE * 2); - return (ENXIO); - } - - mkbc_cons_slotdata.ioh = slot_ioh; - mkbc_init_slotdata(&mkbc_cons_slotdata); - mkbc_consdata.t_slotdata[PCKBC_KBD_SLOT] = &mkbc_cons_slotdata; - - /* Initialise controller. */ - bus_space_write_8(iot, slot_ioh, MKBC_CONTROL, - MKBC_CONTROL_TX_CLOCK_DISABLE | MKBC_CONTROL_RESET); - delay(100); /* 100us */ - - /* Enable controller. */ - bus_space_write_8(iot, slot_ioh, MKBC_CONTROL, - MKBC_CONTROL_RX_CLOCK_ENABLE | MKBC_CONTROL_TX_ENABLE - | MKBC_CONTROL_RX_INT_ENABLE); - - timeout_set(&mkbc_consdata.t_cleanup, mkbc_cleanup, &mkbc_consdata); - timeout_set(&mkbc_consdata.t_poll, mkbc_poll, &mkbc_consdata); - - /* Flush input buffer. */ - (void) mkbc_poll_read(iot, slot_ioh); - - res = pckbd_cnattach(&mkbc_consdata); - - if (res) { - bus_space_unmap(iot, ioh, MKBC_PORTSIZE * 2); - } else { - mkbc_console = 1; - } - - return (res); -} - -void -mkbc_poll(void *self) -{ - struct pckbc_internal *t = self; - int s; - - s = spltty(); - (void)mkbcintr_internal(t, t->t_sc); - timeout_add_sec(&t->t_poll, 1); - splx(s); -} diff --git a/sys/arch/sgi/dev/mkbcreg.h b/sys/arch/sgi/dev/mkbcreg.h deleted file mode 100644 index d15e98a8149..00000000000 --- a/sys/arch/sgi/dev/mkbcreg.h +++ /dev/null @@ -1,54 +0,0 @@ -/* $OpenBSD: mkbcreg.h,v 1.3 2010/12/03 18:29:56 shadchin Exp $ */ - -/* - * Copyright (c) 2006, 2007, Joel Sing - * - * 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. - */ - -#include <dev/ic/pckbcvar.h> - -/* - * MACE PS/2 controller register definitions. - */ - -#define MKBC_PORTSIZE 0x20 - -#define MKBC_TX_PORT 0x00 -#define MKBC_RX_PORT 0x08 -#define MKBC_CONTROL 0x10 -#define MKBC_STATUS 0x18 - -/* - * Controller status flags - */ -#define MKBC_STATUS_CLOCK_SIGNAL 0x01 -#define MKBC_STATUS_CLOCK_INHIBIT 0x02 -#define MKBC_STATUS_TX_INPROGRESS 0x04 -#define MKBC_STATUS_TX_EMPTY 0x08 -#define MKBC_STATUS_RX_FULL 0x10 -#define MKBC_STATUS_RX_INPROGRESS 0x20 -#define MKBC_STATUS_ERROR_PARITY 0x40 -#define MKBC_STATUS_ERROR_FRAMING 0x80 - -/* - * Control bits - */ -#define MKBC_CONTROL_TX_CLOCK_DISABLE 0x01 -#define MKBC_CONTROL_TX_ENABLE 0x02 -#define MKBC_CONTROL_TX_INT_ENABLE 0x04 -#define MKBC_CONTROL_RX_INT_ENABLE 0x08 -#define MKBC_CONTROL_RX_CLOCK_ENABLE 0x10 -#define MKBC_CONTROL_RESET 0x20 - -int mkbc_cnattach(bus_space_tag_t, bus_addr_t); diff --git a/sys/arch/sgi/dev/owmac.c b/sys/arch/sgi/dev/owmac.c deleted file mode 100644 index 90e65e3407c..00000000000 --- a/sys/arch/sgi/dev/owmac.c +++ /dev/null @@ -1,194 +0,0 @@ -/* $OpenBSD: owmac.c,v 1.3 2019/01/15 18:33:30 visa Exp $ */ - -/* - * Copyright (c) 2008 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. - */ - -/* - * DS1981/1982/2502 1-Wire Add-only memory driver, for SGI machines. - * - * SGI uses DS1981 (or compatibles) to store the Ethernet address - * on IOC boards. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/kernel.h> -#include <sys/proc.h> - -#include <dev/onewire/onewiredevs.h> -#include <dev/onewire/onewirereg.h> -#include <dev/onewire/onewirevar.h> - -#include <sgi/dev/owmem_subr.h> -#include <sgi/dev/owmacvar.h> - -int owmac_match(struct device *, void *, void *); -void owmac_attach(struct device *, struct device *, void *); - -struct cfattach owmac_ca = { - sizeof(struct owmac_softc), owmac_match, owmac_attach, -}; - -struct cfdriver owmac_cd = { - NULL, "owmac", DV_DULL -}; - -#define EEPROM_NPAGES 4 - -int owmac_read_page(struct owmac_softc *, int, uint8_t *); -int owmac_read_redirect(struct owmac_softc *); - -void owmac_read_mac(struct owmac_softc *); - -int -owmac_match(struct device *parent, void *match, void *aux) -{ - struct onewire_attach_args *oa = aux; - - if (ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom) == ONEWIRE_FAMILY_DS1982) - return 1; - - /* - * Also match on UniqueWare devices with specific 0x91 family code. - */ - if ((ONEWIRE_ROM_SN(oa->oa_rom) >> (48 - 12)) == 0x5e7 && - ONEWIRE_ROM_FAMILY_CUSTOM(oa->oa_rom) && - ONEWIRE_ROM_FAMILY(oa->oa_rom) == 0x91) - return 1; - - return 0; -} - -void -owmac_attach(struct device *parent, struct device *self, void *aux) -{ - struct owmac_softc *sc = (struct owmac_softc *)self; - struct onewire_attach_args *oa = aux; - - sc->sc_onewire = oa->oa_onewire; - sc->sc_rom = oa->oa_rom; - - /* - * Read the redirection table. - */ - if (owmac_read_redirect(sc) != 0) { - printf(": unable to read redirection data\n"); - return; - } - - printf("\n"); - - /* - * Read the data. - */ - owmac_read_mac(sc); -} - -int -owmac_read_redirect(struct owmac_softc *sc) -{ - int rc = 0; - int status_offset; - - status_offset = 0x0001; /* 1..4 */ - - onewire_lock(sc->sc_onewire, 0); - if ((rc = onewire_reset(sc->sc_onewire)) != 0) - goto unlock; - - onewire_matchrom(sc->sc_onewire, sc->sc_rom); - - /* - * Start reading the EEPROM status block, at the page redirection - * offset. - */ - onewire_write_byte(sc->sc_onewire, ONEWIRE_CMD_READ_STATUS); - onewire_write_byte(sc->sc_onewire, status_offset & 0xff); - onewire_write_byte(sc->sc_onewire, status_offset >> 8); - /* XXX should verify this crc value */ - (void)onewire_read_byte(sc->sc_onewire); - - onewire_read_block(sc->sc_onewire, &sc->sc_redir, EEPROM_NPAGES); - - onewire_reset(sc->sc_onewire); -unlock: - onewire_unlock(sc->sc_onewire); - - return rc; -} - -int -owmac_read_page(struct owmac_softc *sc, int page, uint8_t *buf) -{ - int rc = 0; - int pg; - - /* - * Follow the redirection information. - */ - if ((pg = owmem_redirect(sc->sc_redir, EEPROM_NPAGES, page)) < 0) - return EINVAL; - - pg = page * EEPROM_PAGE_SIZE; - - onewire_lock(sc->sc_onewire, 0); - if ((rc = onewire_reset(sc->sc_onewire)) != 0) - goto unlock; - - onewire_matchrom(sc->sc_onewire, sc->sc_rom); - - /* - * Start reading the EEPROM data. - */ - onewire_write_byte(sc->sc_onewire, ONEWIRE_CMD_READ_MEMORY); - onewire_write_byte(sc->sc_onewire, pg & 0xff); - onewire_write_byte(sc->sc_onewire, 0); - /* XXX should verify this crc value */ - (void)onewire_read_byte(sc->sc_onewire); - - onewire_read_block(sc->sc_onewire, buf, EEPROM_PAGE_SIZE); - - onewire_reset(sc->sc_onewire); -unlock: - onewire_unlock(sc->sc_onewire); - - return rc; -} - -void -owmac_read_mac(struct owmac_softc *sc) -{ - uint8_t buf[EEPROM_PAGE_SIZE]; - - if (owmac_read_page(sc, 0, buf) != 0) - return; - - if (buf[0] != 0x0a) - return; - - sc->sc_enaddr[0] = buf[10]; - sc->sc_enaddr[1] = buf[9]; - sc->sc_enaddr[2] = buf[8]; - sc->sc_enaddr[3] = buf[7]; - sc->sc_enaddr[4] = buf[6]; - sc->sc_enaddr[5] = buf[5]; - - printf("%s: Ethernet Address %02x:%02x:%02x:%02x:%02x:%02x\n", - sc->sc_dev.dv_xname, - sc->sc_enaddr[0], sc->sc_enaddr[1], sc->sc_enaddr[2], - sc->sc_enaddr[3], sc->sc_enaddr[4], sc->sc_enaddr[5]); -} diff --git a/sys/arch/sgi/dev/owmacvar.h b/sys/arch/sgi/dev/owmacvar.h deleted file mode 100644 index 14b6456dcb5..00000000000 --- a/sys/arch/sgi/dev/owmacvar.h +++ /dev/null @@ -1,35 +0,0 @@ -/* $OpenBSD: owmacvar.h,v 1.1 2008/04/07 22:55:57 miod Exp $ */ - -/* - * Copyright (c) 2008 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. - */ - -/* - * DS1981/1982/2502 1-Wire Add-only memory driver, for SGI machines. - * - * SGI uses DS1981 (or compatibles) to store the Ethernet address - * on IOC boards. - */ - -struct owmac_softc { - struct device sc_dev; - - void *sc_onewire; - uint64_t sc_rom; - - uint8_t sc_redir[4]; /* redirection table */ - - uint8_t sc_enaddr[6]; -}; diff --git a/sys/arch/sgi/dev/owmem_subr.c b/sys/arch/sgi/dev/owmem_subr.c deleted file mode 100644 index 3ae3ca89c52..00000000000 --- a/sys/arch/sgi/dev/owmem_subr.c +++ /dev/null @@ -1,46 +0,0 @@ -/* $OpenBSD: owmem_subr.c,v 1.1 2008/04/07 22:55:57 miod Exp $ */ - -/* - * Copyright (c) 2008 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. - */ - -/* - * Common routines to owmac and owserial drivers. - */ - -#include <sys/param.h> - -#include <sgi/dev/owmem_subr.h> - -int -owmem_redirect(uint8_t *redir, u_int npages, u_int page) -{ - int skips = 0; - - /* - * Follow the redirecting table until we end up in our final - * position. We have to be careful not to loop if the table - * is wrong. - */ - while (redir[page] != 0xff) { - if (++skips >= npages) - return -1; - page = 0xff ^ redir[page]; - if (page >= npages) - return -1; - } - - return page; -} diff --git a/sys/arch/sgi/dev/owmem_subr.h b/sys/arch/sgi/dev/owmem_subr.h deleted file mode 100644 index 2e955c89f25..00000000000 --- a/sys/arch/sgi/dev/owmem_subr.h +++ /dev/null @@ -1,25 +0,0 @@ -/* $OpenBSD: owmem_subr.h,v 1.1 2008/04/07 22:55:57 miod Exp $ */ - -/* - * Copyright (c) 2008 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. - */ - -/* - * Common routines to owmac and owserial drivers. - */ - -#define EEPROM_PAGE_SIZE (256 / NBBY) /* 256 bits per page */ - -int owmem_redirect(uint8_t *, u_int, u_int); diff --git a/sys/arch/sgi/dev/owserial.c b/sys/arch/sgi/dev/owserial.c deleted file mode 100644 index 333e6073d02..00000000000 --- a/sys/arch/sgi/dev/owserial.c +++ /dev/null @@ -1,244 +0,0 @@ -/* $OpenBSD: owserial.c,v 1.2 2009/04/19 18:33:53 miod Exp $ */ - -/* - * Copyright (c) 2008 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. - */ - -/* - * DS2505 1-Wire Add-only memory driver, for SGI machines. - * - * SGI seems to use DS2505 (or compatibles) to store serial numbers. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/kernel.h> -#include <sys/proc.h> - -#include <dev/onewire/onewiredevs.h> -#include <dev/onewire/onewirereg.h> -#include <dev/onewire/onewirevar.h> - -#include <sgi/dev/owmem_subr.h> -#include <sgi/dev/owserialvar.h> - -int owserial_match(struct device *, void *, void *); -void owserial_attach(struct device *, struct device *, void *); - -struct cfattach owserial_ca = { - sizeof(struct owserial_softc), owserial_match, owserial_attach, -}; - -struct cfdriver owserial_cd = { - NULL, "owserial", DV_DULL -}; - -#define EEPROM_PAGE_SIZE (256 / NBBY) /* 256 bits per page */ - -static const struct onewire_matchfam owserial_fams[] = { - { ONEWIRE_FAMILY_DS2505 }, - { ONEWIRE_FAMILY_DS2506 } -}; - -int owserial_read_page(struct owserial_softc *, int, uint8_t *); -int owserial_read_redirect(struct owserial_softc *); - -void owserial_read_serial(struct owserial_softc *); - -int -owserial_match(struct device *parent, void *match, void *aux) -{ - return (onewire_matchbyfam(aux, owserial_fams, - sizeof(owserial_fams) /sizeof(owserial_fams[0]))); -} - -void -owserial_attach(struct device *parent, struct device *self, void *aux) -{ - struct owserial_softc *sc = (struct owserial_softc *)self; - struct onewire_attach_args *oa = aux; - - sc->sc_onewire = oa->oa_onewire; - sc->sc_rom = oa->oa_rom; - - /* - * Decide how many pages of 256 bits we have. - */ - - if (ONEWIRE_ROM_FAMILY_TYPE(sc->sc_rom) == ONEWIRE_FAMILY_DS2506) - sc->sc_npages = 256; - else - sc->sc_npages = 64; - - /* - * Read the redirection table. - */ - if (owserial_read_redirect(sc) != 0) { - printf(": unable to read redirection data\n"); - return; - } - - printf("\n"); - - /* - * Read the data. - */ - owserial_read_serial(sc); -} - -int -owserial_read_redirect(struct owserial_softc *sc) -{ - int rc = 0; - int status_offset, pos; - - status_offset = 0x0100; /* 100..13f or 100..1ff */ - pos = 0; - - onewire_lock(sc->sc_onewire, 0); - if ((rc = onewire_reset(sc->sc_onewire)) != 0) - goto unlock; - - onewire_matchrom(sc->sc_onewire, sc->sc_rom); - - /* - * Start reading the EEPROM status block, at the page redirection - * offset. - */ - onewire_write_byte(sc->sc_onewire, ONEWIRE_CMD_READ_STATUS); - onewire_write_byte(sc->sc_onewire, status_offset & 0xff); - onewire_write_byte(sc->sc_onewire, status_offset >> 8); - - for (pos = 0; pos < sc->sc_npages; pos += 8) { - onewire_read_block(sc->sc_onewire, sc->sc_redir + pos, 8); - /* XXX check crc */ - (void)onewire_read_byte(sc->sc_onewire); - (void)onewire_read_byte(sc->sc_onewire); - } - - onewire_reset(sc->sc_onewire); -unlock: - onewire_unlock(sc->sc_onewire); - - return rc; -} - -int -owserial_read_page(struct owserial_softc *sc, int page, uint8_t *buf) -{ - int rc = 0; - int pg; - - /* - * Follow the redirection information. - */ - if ((pg = owmem_redirect(sc->sc_redir, sc->sc_npages, page)) < 0) - return EINVAL; - - pg = page * EEPROM_PAGE_SIZE; - - onewire_lock(sc->sc_onewire, 0); - if ((rc = onewire_reset(sc->sc_onewire)) != 0) - goto unlock; - - onewire_matchrom(sc->sc_onewire, sc->sc_rom); - - /* - * Start reading the EEPROM data. - */ - onewire_write_byte(sc->sc_onewire, ONEWIRE_CMD_READ_MEMORY); - onewire_write_byte(sc->sc_onewire, pg & 0xff); - onewire_write_byte(sc->sc_onewire, pg >> 8); - - onewire_read_block(sc->sc_onewire, buf, EEPROM_PAGE_SIZE); - - onewire_reset(sc->sc_onewire); -unlock: - onewire_unlock(sc->sc_onewire); - - return rc; -} - -void -owserial_read_serial(struct owserial_softc *sc) -{ - uint8_t buf[EEPROM_PAGE_SIZE * 2]; - char name[1 + OWSERIAL_NAME_LEN]; - char product[1 + OWSERIAL_PRODUCT_LEN]; - char serial[1 + OWSERIAL_SERIAL_LEN]; - char *s, *e; - int pg; - int i; - - pg = owmem_redirect(sc->sc_redir, sc->sc_npages, 0); - if (pg < 0 || owserial_read_page(sc, pg, buf) != 0) - return; - - pg = owmem_redirect(sc->sc_redir, sc->sc_npages, 1); - if (pg < 0 || owserial_read_page(sc, pg, buf + EEPROM_PAGE_SIZE) != 0) - return; - - /* minimal sanity check */ - if (buf[0] != 0x01) - return; - for (i = EEPROM_PAGE_SIZE + 10; i < EEPROM_PAGE_SIZE + 16; i++) - if (buf[i] != 0xff) - return; - - bcopy(buf + 21, product, 9); - bcopy(buf + EEPROM_PAGE_SIZE + 3, product + 9, 3); - product[OWSERIAL_PRODUCT_LEN] = '\0'; - for (i = 0; i < OWSERIAL_PRODUCT_LEN; i++) - if (product[i] != '-' && (product[i] < '0' || product[i] > '9')) - return; - - bcopy(buf + EEPROM_PAGE_SIZE + 16, name, OWSERIAL_NAME_LEN); - name[OWSERIAL_NAME_LEN] = '\0'; - for (i = 0; i < OWSERIAL_NAME_LEN; i++) - if (name[i] < ' ' || name[i] > '~') - return; - - bcopy(buf + 1, serial, OWSERIAL_SERIAL_LEN); - serial[OWSERIAL_SERIAL_LEN] = '\0'; - for (i = 0; i < OWSERIAL_SERIAL_LEN; i++) - if (serial[i] < ' ' || serial[i] > '~') - return; - - /* - * Trim leading and trailing spaces from name and serial # - */ - - strlcpy(sc->sc_product, product, sizeof sc->sc_product); - - s = name; - while (*s == ' ') - s++; - e = name + OWSERIAL_NAME_LEN - 1; - while (*e == ' ' && e >= s) - *e-- = '\0'; - strlcpy(sc->sc_name, s, sizeof sc->sc_name); - - s = serial; - while (*s == ' ') - s++; - e = serial + OWSERIAL_SERIAL_LEN - 1; - while (*e == ' ' && e >= s) - *e-- = '\0'; - strlcpy(sc->sc_serial, s, sizeof sc->sc_serial); - - printf("%s: \"%s\" p/n %s, serial %s\n", - sc->sc_dev.dv_xname, sc->sc_name, sc->sc_product, sc->sc_serial); -} diff --git a/sys/arch/sgi/dev/owserialvar.h b/sys/arch/sgi/dev/owserialvar.h deleted file mode 100644 index 41002b5c808..00000000000 --- a/sys/arch/sgi/dev/owserialvar.h +++ /dev/null @@ -1,41 +0,0 @@ -/* $OpenBSD: owserialvar.h,v 1.2 2009/04/19 18:33:53 miod Exp $ */ - -/* - * Copyright (c) 2008 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. - */ - -/* - * DS2505 1-Wire Add-only memory driver, for SGI machines. - * - * SGI seems to use DS2505 (or compatibles) to store serial numbers. - */ - -#define OWSERIAL_NAME_LEN 14 -#define OWSERIAL_PRODUCT_LEN 12 -#define OWSERIAL_SERIAL_LEN 20 - -struct owserial_softc { - struct device sc_dev; - - void *sc_onewire; - uint64_t sc_rom; - - int sc_npages; /* number of pages */ - uint8_t sc_redir[256]; /* redirection table */ - - char sc_name[1 + OWSERIAL_NAME_LEN]; - char sc_product[1 + OWSERIAL_PRODUCT_LEN]; - char sc_serial[1 + OWSERIAL_SERIAL_LEN]; -}; diff --git a/sys/arch/sgi/dev/power.c b/sys/arch/sgi/dev/power.c deleted file mode 100644 index 8b38f7a20cb..00000000000 --- a/sys/arch/sgi/dev/power.c +++ /dev/null @@ -1,149 +0,0 @@ -/* $OpenBSD: power.c,v 1.16 2018/12/03 13:46:30 visa Exp $ */ - -/* - * Copyright (c) 2007 Jasper Lievisse Adriaanse <jasper@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. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/proc.h> -#include <sys/signalvar.h> - -#include <machine/autoconf.h> -#include <mips64/archtype.h> - -#include <dev/ic/ds1687reg.h> -#include <sgi/dev/dsrtcvar.h> - -#include "power.h" - -/* - * Power button driver for the SGI O2 and Octane. - */ - -int power_intr(void *); - -struct cfdriver power_cd = { - NULL, "power", DV_DULL -}; - -#if NPOWER_MACEBUS > 0 - -#include <sgi/localbus/macebusvar.h> - -void power_macebus_attach(struct device *, struct device *, void *); -int power_macebus_match(struct device *, void *, void *); - -struct cfattach power_macebus_ca = { - sizeof(struct device), power_macebus_match, power_macebus_attach -}; - -int -power_macebus_match(struct device *parent, void *match, void *aux) -{ - return (1); -} - -void -power_macebus_attach(struct device *parent, struct device *self, void *aux) -{ - struct macebus_attach_args *maa = aux; - - /* Establish interrupt handler. */ - if (macebus_intr_establish(maa->maa_intr, maa->maa_mace_intr, - IPL_TTY, power_intr, self, self->dv_xname)) - printf("\n"); - else - printf(": unable to establish interrupt!\n"); -} - -#endif - -#if NPOWER_MAINBUS > 0 - -#include <sgi/xbow/xbow.h> -#include <sgi/xbow/xheartreg.h> - -void power_mainbus_attach(struct device *, struct device *, void *); -int power_mainbus_match(struct device *, void *, void *); -int power_mainbus_intr(void *); - -struct cfattach power_mainbus_ca = { - sizeof(struct device), power_mainbus_match, power_mainbus_attach -}; - -int -power_mainbus_match(struct device *parent, void *match, void *aux) -{ - struct mainbus_attach_args *maa = aux; - - if (strcmp(maa->maa_name, power_cd.cd_name) != 0) - return 0; - - return sys_config.system_type == SGI_OCTANE ? 1 : 0; -} - -void -power_mainbus_attach(struct device *parent, struct device *self, void *aux) -{ - /* Establish interrupt handler. */ - if (xbow_intr_establish(power_mainbus_intr, self, HEART_ISR_POWER, - IPL_TTY, self->dv_xname, NULL) != 0) { - printf(": unable to establish interrupt!\n"); - return; - } - - printf("\n"); -} - -int -power_mainbus_intr(void *v) -{ - /* - * Clear interrupt condition; debouncing the kickstart bit will not - * suffice. - */ - xbow_intr_clear(HEART_ISR_POWER); - - return power_intr(v); -} - -#endif - -int -power_intr(void *unused) -{ - extern int allowpowerdown; - int val; - - /* - * Prevent further interrupts by clearing the kickstart flag - * in the DS1687's extended control register. - */ - val = dsrtc_register_read(DS1687_EXT_CTRL); - if (val == -1) - return 1; /* no rtc attached */ - - /* debounce condition */ - dsrtc_register_write(DS1687_EXT_CTRL, val & ~DS1687_KICKSTART); - - if (allowpowerdown == 1) { - allowpowerdown = 0; - prsignal(initprocess, SIGUSR2); - } - - return 1; -} diff --git a/sys/arch/sgi/dev/spdmem_mainbus.c b/sys/arch/sgi/dev/spdmem_mainbus.c deleted file mode 100644 index 3d37c202e87..00000000000 --- a/sys/arch/sgi/dev/spdmem_mainbus.c +++ /dev/null @@ -1,107 +0,0 @@ -/* $OpenBSD: spdmem_mainbus.c,v 1.3 2015/09/08 10:21:50 deraadt 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. - */ - -/* - * Display SPD memory information obtained from an IP35 brick L1 controller. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> -#include <sys/malloc.h> - -#include <dev/spdmemvar.h> - -#include <mips64/archtype.h> - -#include <machine/autoconf.h> - -#include <sgi/sgi/l1.h> - -struct spdmem_mainbus_softc { - struct spdmem_softc sc_base; - uint8_t *sc_spd; - size_t sc_spdlen; -}; - -int spdmem_mainbus_match(struct device *, void *, void *); -void spdmem_mainbus_attach(struct device *, struct device *, void *); -uint8_t spdmem_mainbus_read(struct spdmem_softc *, uint8_t); - -struct cfattach spdmem_mainbus_ca = { - sizeof(struct spdmem_mainbus_softc), - spdmem_mainbus_match, spdmem_mainbus_attach -}; - -int -spdmem_mainbus_match(struct device *parent, void *vcf, void *aux) -{ - struct spdmem_attach_args *saa = (struct spdmem_attach_args *)aux; - extern struct cfdriver spdmem_cd; - int rc; - uint8_t *spd; - size_t spdlen; - - if (sys_config.system_type != SGI_IP35) - return 0; - - if (strcmp(saa->maa.maa_name, spdmem_cd.cd_name) != 0) - return 0; - - rc = l1_get_brick_spd_record(saa->maa.maa_nasid, saa->dimm, - &spd, &spdlen); - if (rc == 0) { - free(spd, M_DEVBUF, spdlen); - return 1; - } else - return 0; -} - -void -spdmem_mainbus_attach(struct device *parent, struct device *self, void *aux) -{ - struct spdmem_mainbus_softc *sc = (struct spdmem_mainbus_softc *)self; - struct spdmem_attach_args *saa = (struct spdmem_attach_args *)aux; - int rc; - - printf(" dimm %d:", saa->dimm); - - rc = l1_get_brick_spd_record(saa->maa.maa_nasid, saa->dimm, - &sc->sc_spd, &sc->sc_spdlen); - if (rc != 0) { - printf(" can't get SPD record from L1, error %d\n", rc); - return; - } - - sc->sc_base.sc_read = spdmem_mainbus_read; - spdmem_attach_common(&sc->sc_base); - /* free record, as it won't be accessed anymore */ - free(sc->sc_spd, M_DEVBUF, sc->sc_spdlen); - sc->sc_spdlen = 0; -} - -uint8_t -spdmem_mainbus_read(struct spdmem_softc *v, uint8_t reg) -{ - struct spdmem_mainbus_softc *sc = (struct spdmem_mainbus_softc *)v; - - if (reg < sc->sc_spdlen) - return sc->sc_spd[reg]; - else - return 0; -} |