Date: Sun, 9 May 2004 17:14:44 +0200 From: Joerg Wunsch <j@ida.interface-business.de> To: sparc64@freebsd.org Subject: ebus resource allocation error? Message-ID: <20040509171444.B63877@ida.interface-business.de>
next in thread | raw e-mail | index | archive | help
--Q68bSM7Ycu6FN28Q Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit I'm currently investigating the chances of writing a driver for the SUNW,envctrl device of my E450. Supposedly, this is an I²C bus, so it's my hope to eventually setup the driver as a glue interface between the Sun hardware and iicbus/smbus. This hardware has the curious (for me at least) situation that it gets two IRQs assigned: SUNW,envctrl0: <EBus SUNW,envctrl> addr 0x1400600000-0x1400600003 irq 2021,2024 on ebus0 However, when trying to bus_alloc_resource the second IRQ, I always get a resource allocation error. Since the code used for resource allocation is basically the same as I've successfully been using to allocate multiple IO port ranges in my auxio driver, I rather suspect a problem in the ebus code itself. Below are the current probe messages, attached is the source code. (Please do not redistribute by now, it's really only a stub driver.) SUNW,envctrl0: <EBus SUNW,envctrl> addr 0x1400600000-0x1400600003 irq 2021,2024 on ebus0 SUNW,envctrl0: Got IRQ rid 0, start 0x7e8, count 0x1 SUNW,envctrl0: Got IRQ rid 1, start 0x7e5, count 0x1 SUNW,envctrl0: could not allocate resources: 2nd IRQ device_probe_and_attach: SUNW,envctrl0 attach returned 6 -- J"org Wunsch Unix support engineer joerg_wunsch@interface-systems.de http://www.interface-systems.de/~j/ --Q68bSM7Ycu6FN28Q Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="envctrl.c" /* * Copyright 2004, Joerg Wunsch */ #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> #include <sys/conf.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/resource.h> #include <sys/uio.h> #include <machine/bus.h> #include <machine/resource.h> #include <sys/rman.h> #include <dev/ofw/openfirm.h> #include <sparc64/ebus/ebusvar.h> static int envctrl_probe(device_t); static int envctrl_attach(device_t); static int envctrl_detach(device_t); static device_method_t envctrl_methods[] = { /* Device interface */ DEVMETHOD(device_probe, envctrl_probe), DEVMETHOD(device_attach, envctrl_attach), DEVMETHOD(device_detach, envctrl_detach), { 0, 0 } }; struct envctrl_softc { struct resource *iores; struct resource *intres[2]; dev_t devfs_cookie; device_t dev; void *intr_cookie[2]; }; static devclass_t envctrl_devclass; static driver_t envctrl_driver = { "SUNW,envctrl", envctrl_methods, sizeof(struct envctrl_softc), }; DRIVER_MODULE(envctrl, ebus, envctrl_driver, envctrl_devclass, 0, 0); static d_open_t envctrl_open; static d_close_t envctrl_close; static d_read_t envctrl_read; static d_write_t envctrl_write; static d_ioctl_t envctrl_ioctl; static driver_intr_t envctrl_intr1; static driver_intr_t envctrl_intr2; static struct cdevsw envctrl_cdevsw = { .d_version = D_VERSION, .d_open = envctrl_open, .d_close = envctrl_close, .d_read = envctrl_read, .d_write = envctrl_write, .d_ioctl = envctrl_ioctl, .d_name = "SUNW,envctrl", }; static int envctrl_probe(device_t dev) { if (strcmp("SUNW,envctrl", ebus_get_name(dev)) == 0) { device_set_desc(dev, "EBus SUNW,envctrl"); return (0); } return (ENXIO); } static int envctrl_attach(device_t dev) { struct envctrl_softc *sc; struct resource *res; const char *errmsg; int rid, rv, i; u_long start, count; sc = device_get_softc(dev); rid = 0; res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (res == NULL) { errmsg = "IO port"; goto allocfail; } sc->iores = res; for (i = 0; i < 2; i++) { if (bus_get_resource(dev, SYS_RES_IRQ, i, &start, &count) != 0) continue; rid = i; if (bootverbose) device_printf(dev, "Got IRQ rid %d, start %#lx, count %#lx\n", i, start, count); res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, start, start + count - 1, count, RF_ACTIVE); if (res == NULL) { errmsg = i == 0? "1st IRQ": "2nd IRQ"; goto allocfail; } sc->intres[i] = res; } rv = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->intres[0], INTR_TYPE_MISC /* | INTR_ENTROPY */, envctrl_intr1, sc, sc->intr_cookie + 0); if (rv) { errmsg = "1st IRQ"; goto irqfail; } rv = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->intres[1], INTR_TYPE_MISC /* | INTR_ENTROPY */, envctrl_intr2, sc, sc->intr_cookie + 1); if (rv) { errmsg = "1st IRQ"; goto irqfail; } sc->devfs_cookie = make_dev(&envctrl_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "envctrl"); sc->dev = dev; return (0); allocfail: device_printf(dev, "could not allocate resources: %s\n", errmsg); return (ENXIO); irqfail: device_printf(dev, "could not setup %s\n", errmsg); return (ENXIO); } static int envctrl_detach(device_t dev) { struct envctrl_softc *sc; sc = device_get_softc(dev); BUS_TEARDOWN_INTR(device_get_parent(dev), dev, sc->intres[0], sc->intr_cookie[0]); BUS_TEARDOWN_INTR(device_get_parent(dev), dev, sc->intres[1], sc->intr_cookie[1]); bus_deactivate_resource(dev, SYS_RES_IRQ, 0, sc->intres[0]); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->intres[0]); bus_deactivate_resource(dev, SYS_RES_IRQ, 1, sc->intres[1]); bus_release_resource(dev, SYS_RES_IRQ, 1, sc->intres[1]); bus_deactivate_resource(dev, SYS_RES_IOPORT, 0, sc->iores); bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->iores); destroy_dev(sc->devfs_cookie); return (0); } static int envctrl_open(dev_t dev, int oflags, int devtype, struct thread *td) { return (0); } static int envctrl_close(dev_t dev, int fflag, int devtype, struct thread *td) { return (0); } static int envctrl_read(dev_t dev, struct uio *uio, int ioflag) { struct envctrl_softc *sc; uint32_t buf; int rv; if (uio->uio_offset != 0) return (0); if (uio->uio_resid < sizeof(uint32_t)) return (EINVAL); sc = devclass_get_softc(envctrl_devclass, 0); buf = bus_space_read_4(sc->iores->r_bustag, sc->iores->r_bushandle, 0); rv = uiomove(&buf, sizeof(uint32_t), uio); return (rv); } static int envctrl_write(dev_t dev, struct uio *uio, int ioflag) { struct envctrl_softc *sc; uint32_t buf; int rv; if (uio->uio_offset != 0) return (0); if (uio->uio_resid < sizeof(uint32_t)) return (EINVAL); sc = devclass_get_softc(envctrl_devclass, 0); if ((rv = uiomove(&buf, sizeof(uint32_t), uio)) != 0) return (rv); bus_space_write_4(sc->iores->r_bustag, sc->iores->r_bushandle, 0, buf); return (0); } static int envctrl_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) { return (ENXIO); } static void envctrl_intr1(void *arg) { struct envctrl_softc *sc = (struct envctrl_softc *)arg; device_printf(sc->dev, "1st IRQ triggered\n"); } static void envctrl_intr2(void *arg) { struct envctrl_softc *sc = (struct envctrl_softc *)arg; device_printf(sc->dev, "2nd IRQ triggered\n"); } --Q68bSM7Ycu6FN28Q--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040509171444.B63877>