From owner-freebsd-sparc64@FreeBSD.ORG Sun May 9 12:27:06 2004 Return-Path: Delivered-To: freebsd-sparc64@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 430AB16A4CE for ; Sun, 9 May 2004 12:27:06 -0700 (PDT) Received: from ida.interface-business.de (ida.interface-business.de [193.101.57.9]) by mx1.FreeBSD.org (Postfix) with ESMTP id 5B9F643D45 for ; Sun, 9 May 2004 12:27:05 -0700 (PDT) (envelope-from j@ida.interface-business.de) Received: by ida.interface-business.de (Postfix, from userid 107) id E734A7A69; Sun, 9 May 2004 17:14:44 +0200 (MET DST) Date: Sun, 9 May 2004 17:14:44 +0200 From: Joerg Wunsch To: sparc64@freebsd.org Message-ID: <20040509171444.B63877@ida.interface-business.de> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="Q68bSM7Ycu6FN28Q" Content-Disposition: inline Content-Transfer-Encoding: 8bit User-Agent: Mutt/1.2.5i X-Phone: +49-351-31809-14 X-PGP-Fingerprint: DC 47 E6 E4 FF A6 E9 8F 93 21 E0 7D F9 12 D6 4E Organization: interface systems GmbH, Dresden Subject: ebus resource allocation error? X-BeenThere: freebsd-sparc64@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Joerg Wunsch List-Id: Porting FreeBSD to the Sparc List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 09 May 2004 19:27:06 -0000 --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: 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: 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 #include #include #include #include #include #include #include #include #include #include #include #include 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--