diff options
| author | Nicolas Souchu <nsouch@FreeBSD.org> | 2000-01-14 00:18:06 +0000 |
|---|---|---|
| committer | Nicolas Souchu <nsouch@FreeBSD.org> | 2000-01-14 00:18:06 +0000 |
| commit | 0f210c922b80eef92f841effdded7996a621a9da (patch) | |
| tree | c8c8f70a67c05a3d2584020b59bcb61f7755129f /sys/dev/pcf/pcf.c | |
| parent | e562c84330b8ab2e50ed16c1c1891aee7a548951 (diff) | |
Notes
Diffstat (limited to 'sys/dev/pcf/pcf.c')
| -rw-r--r-- | sys/dev/pcf/pcf.c | 140 |
1 files changed, 64 insertions, 76 deletions
diff --git a/sys/dev/pcf/pcf.c b/sys/dev/pcf/pcf.c index 1aeb7e650c85..e37823e400c3 100644 --- a/sys/dev/pcf/pcf.c +++ b/sys/dev/pcf/pcf.c @@ -34,12 +34,20 @@ #include <sys/malloc.h> #include <machine/clock.h> +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/rman.h> + +#include <isa/isareg.h> +#include <isa/isavar.h> #include <i386/isa/isa_device.h> #include <dev/iicbus/iiconf.h> #include "iicbus_if.h" +#define IO_PCFSIZE 2 + #define TIMEOUT 9999 /* XXX */ /* Status bits of S1 register (read only) */ @@ -71,37 +79,23 @@ struct pcf_softc { int pcf_base; /* isa port */ + int pcf_flags; u_char pcf_addr; /* interface I2C address */ int pcf_slave_mode; /* receiver or transmitter */ int pcf_started; /* 1 if start condition sent */ device_t iicbus; /* the corresponding iicbus */ -}; - -struct pcf_isa_softc { - - int pcf_unit; /* unit of the isa device */ - int pcf_base; /* isa port */ - int pcf_irq; /* isa irq or null if polled */ - - unsigned int pcf_flags; /* boot flags */ -}; - -#define MAXPCF 2 - -static struct pcf_isa_softc *pcfdata[MAXPCF]; -static int npcf = 0; - -static int pcfprobe_isa(struct isa_device *); -static int pcfattach_isa(struct isa_device *); -struct isa_driver pcfdriver = { - pcfprobe_isa, pcfattach_isa, "pcf" + int rid_irq, rid_ioport; + struct resource *res_irq, *res_ioport; + void *intr_cookie; }; static int pcf_probe(device_t); static int pcf_attach(device_t); +static void pcfintr(void *arg); + static int pcf_print_child(device_t, device_t); static int pcf_repeated_start(device_t, u_char, int); @@ -109,7 +103,6 @@ static int pcf_start(device_t, u_char, int); static int pcf_stop(device_t); static int pcf_write(device_t, char *, int, int *, int); static int pcf_read(device_t, char *, int, int *, int, int); -static ointhand2_t pcfintr; static int pcf_rst_card(device_t, u_char, u_char, u_char *); static device_method_t pcf_methods[] = { @@ -143,72 +136,68 @@ static devclass_t pcf_devclass; #define DEVTOSOFTC(dev) ((struct pcf_softc *)device_get_softc(dev)) static int -pcfprobe_isa(struct isa_device *dvp) +pcf_probe(device_t pcfdev) { - device_t pcfdev; - struct pcf_isa_softc *pcf; - - if (npcf >= MAXPCF) - return (0); - - if ((pcf = (struct pcf_isa_softc *)malloc(sizeof(struct pcf_isa_softc), - M_DEVBUF, M_NOWAIT)) == NULL) - return (0); - - pcf->pcf_base = dvp->id_iobase; /* XXX should be ivars */ - pcf->pcf_unit = dvp->id_unit; + struct pcf_softc *pcf = DEVTOSOFTC(pcfdev); + device_t parent = device_get_parent(pcfdev); - if (!(dvp->id_flags & IIC_POLLED)) - pcf->pcf_irq = (dvp->id_irq); + device_set_desc(pcfdev, "PCF8584 I2C bus controller"); - pcfdata[npcf++] = pcf; + pcf = DEVTOSOFTC(pcfdev); + bzero(pcf, sizeof(struct pcf_softc)); - /* XXX add the pcf device to the root_bus until isa bus exists */ - pcfdev = device_add_child(root_bus, "pcf", pcf->pcf_unit); + pcf->rid_irq = pcf->rid_ioport = 0; + pcf->res_irq = pcf->res_ioport = 0; - if (!pcfdev) + /* IO port is mandatory */ + pcf->res_ioport = bus_alloc_resource(pcfdev, SYS_RES_IOPORT, + &pcf->rid_ioport, 0ul, ~0ul, + IO_PCFSIZE, RF_ACTIVE); + if (pcf->res_ioport == 0) { + device_printf(pcfdev, "cannot reserve I/O port range\n"); goto error; + } + BUS_READ_IVAR(parent, pcfdev, ISA_IVAR_PORT, &pcf->pcf_base); - return (1); - -error: - free(pcf, M_DEVBUF); - return (0); -} - -static int -pcfattach_isa(struct isa_device *isdp) -{ - isdp->id_ointr = pcfintr; - return (1); /* ok */ -} + pcf->pcf_flags = device_get_flags(pcfdev); -static int -pcf_probe(device_t pcfdev) -{ - struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(pcfdev); - int unit = device_get_unit(pcfdev); - - /* retrieve base address from isa initialization - * - * XXX should use ivars with isabus - */ - pcf->pcf_base = pcfdata[unit]->pcf_base; + if (!(pcf->pcf_flags & IIC_POLLED)) { + pcf->res_irq = bus_alloc_resource(pcfdev, SYS_RES_IRQ, &pcf->rid_irq, + 0ul, ~0ul, 1, RF_ACTIVE); + if (pcf->res_irq == 0) { + device_printf(pcfdev, "can't reserve irq, polled mode.\n"); + pcf->pcf_flags |= IIC_POLLED; + } + } /* reset the chip */ pcf_rst_card(pcfdev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL); - /* XXX try do detect chipset */ - - device_set_desc(pcfdev, "PCF8584 I2C bus controller"); - return (0); +error: + if (pcf->res_ioport != 0) { + bus_deactivate_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport, + pcf->res_ioport); + bus_release_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport, + pcf->res_ioport); + } + return (ENXIO); } static int pcf_attach(device_t pcfdev) { - struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(pcfdev); + struct pcf_softc *pcf = DEVTOSOFTC(pcfdev); + device_t parent = device_get_parent(pcfdev); + int error = 0; + + if (pcf->res_irq) { + /* default to the tty mask for registration */ /* XXX */ + error = BUS_SETUP_INTR(parent, pcfdev, pcf->res_irq, INTR_TYPE_NET, + pcfintr, pcfdev, &pcf->intr_cookie); + if (error) + return (error); + } pcf->iicbus = iicbus_alloc_bus(pcfdev); @@ -392,10 +381,10 @@ error: } static void -pcfintr(unit) +pcfintr(void *arg) { - struct pcf_softc *pcf = - (struct pcf_softc *)devclass_get_softc(pcf_devclass, unit); + device_t pcfdev = (device_t)arg; + struct pcf_softc *pcf = DEVTOSOFTC(pcfdev); char data, status, addr; char error = 0; @@ -403,14 +392,13 @@ pcfintr(unit) status = PCF_GET_S1(pcf); if (status & PIN) { - printf("pcf%d: spurious interrupt, status=0x%x\n", unit, - status & 0xff); + device_printf(pcfdev, "spurious interrupt, status=0x%x\n", status & 0xff); goto error; } if (status & LAB) - printf("pcf%d: bus arbitration lost!\n", unit); + device_printf(pcfdev, "bus arbitration lost!\n"); if (status & BER) { error = IIC_EBUSERR; @@ -643,4 +631,4 @@ error: return (error); } -DRIVER_MODULE(pcf, root, pcf_driver, pcf_devclass, 0, 0); +DRIVER_MODULE(pcf, isa, pcf_driver, pcf_devclass, 0, 0); |
