#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <bus/isa/isavar.h>
#include <sys/systm.h>
#include <sys/sensors.h>
#include "lm78var.h"
#include "../wbsio/wbsioreg.h"
#include "../wbsio/wbsiovar.h"
#define LMC_ADDR 0x05
#define LMC_DATA 0x06
#if defined(LMDEBUG)
#define DPRINTF(x) do { kprintf x; } while (0)
#else
#define DPRINTF(x)
#endif
struct lm_isa_softc {
struct lm_softc sc_lmsc;
struct resource *sc_iores;
int sc_iorid;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
};
static int lm_isa_probe(device_t);
static int lm_isa_attach(device_t);
static int lm_isa_detach(device_t);
u_int8_t lm_isa_readreg(struct lm_softc *, int);
void lm_isa_writereg(struct lm_softc *, int, int);
static device_method_t lm_isa_methods[] = {
DEVMETHOD(device_probe, lm_isa_probe),
DEVMETHOD(device_attach, lm_isa_attach),
DEVMETHOD(device_detach, lm_isa_detach),
DEVMETHOD_END
};
static driver_t lm_isa_driver = {
"lm",
lm_isa_methods,
sizeof (struct lm_isa_softc)
};
static devclass_t lm_devclass;
DRIVER_MODULE(lm, isa, lm_isa_driver, lm_devclass, NULL, NULL);
DRIVER_MODULE(lm, wbsio, lm_isa_driver, lm_devclass, NULL, NULL);
static int
lm_isa_probe(device_t dev)
{
struct lm_isa_softc *sc = device_get_softc(dev);
struct wbsio_softc *wbsc = NULL;
struct resource *iores;
struct devclass *parent_devclass;
const char *parent_name;
int iorid = 0;
bus_space_tag_t iot;
bus_space_handle_t ioh;
int banksel, vendid, chipid, addr;
parent_devclass = device_get_devclass(device_get_parent(dev));
parent_name = devclass_get_name(parent_devclass);
if (strcmp("wbsio", parent_name) == 0) {
wbsc = device_get_softc(device_get_parent(dev));
sc->sc_lmsc.sioid = wbsc->sc_devid;
} else {
sc->sc_lmsc.sioid = 0;
}
iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &iorid,
0ul, ~0ul, 8, RF_ACTIVE);
if (iores == NULL) {
DPRINTF(("%s: can't map i/o space\n", __func__));
return (1);
}
iot = rman_get_bustag(iores);
ioh = rman_get_bushandle(iores);
bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
banksel = bus_space_read_1(iot, ioh, LMC_DATA);
bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
bus_space_write_1(iot, ioh, LMC_DATA, WB_BANKSEL_HBAC);
bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID);
vendid = bus_space_read_1(iot, ioh, LMC_DATA) << 8;
bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
bus_space_write_1(iot, ioh, LMC_DATA, 0);
bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID);
vendid |= bus_space_read_1(iot, ioh, LMC_DATA);
bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
bus_space_write_1(iot, ioh, LMC_DATA, banksel);
if (vendid == WB_VENDID_WINBOND)
goto found;
bus_space_write_1(iot, ioh, LMC_ADDR, 0x58 );
vendid = bus_space_read_1(iot, ioh, LMC_DATA);
if (vendid == 0x90 )
goto notfound;
bus_space_write_1(iot, ioh, LMC_ADDR, LM_SBUSADDR);
addr = bus_space_read_1(iot, ioh, LMC_DATA);
if ((addr & 0xfc) == 0x2c) {
bus_space_write_1(iot, ioh, LMC_ADDR, LM_CHIPID);
chipid = bus_space_read_1(iot, ioh, LMC_DATA);
switch (chipid & LM_CHIPID_MASK) {
case LM_CHIPID_LM78:
case LM_CHIPID_LM78J:
case LM_CHIPID_LM79:
case LM_CHIPID_LM81:
goto found;
}
}
notfound:
bus_release_resource(dev, SYS_RES_IOPORT, iorid, iores);
return (1);
found:
sc->sc_lmsc.sc_dev = dev;
sc->sc_iot = iot;
sc->sc_ioh = ioh;
sc->sc_lmsc.lm_writereg = lm_isa_writereg;
sc->sc_lmsc.lm_readreg = lm_isa_readreg;
lm_probe(&sc->sc_lmsc);
bus_release_resource(dev, SYS_RES_IOPORT, iorid, iores);
sc->sc_iot = 0;
sc->sc_ioh = 0;
return (0);
}
static int
lm_isa_attach(device_t dev)
{
struct lm_isa_softc *sc = device_get_softc(dev);
#ifdef notyet
struct lm_softc *lmsc;
int i;
u_int8_t sbusaddr;
#endif
sc->sc_iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_iorid,
0ul, ~0ul, 8, RF_ACTIVE);
if (sc->sc_iores == NULL) {
device_printf(dev, "can't map i/o space\n");
return (1);
}
sc->sc_iot = rman_get_bustag(sc->sc_iores);
sc->sc_ioh = rman_get_bushandle(sc->sc_iores);
lm_attach(&sc->sc_lmsc);
#ifdef notyet
sbusaddr = lm_isa_readreg(&sc->sc_lmsc, LM_SBUSADDR);
if (sbusaddr == 0)
return (0);
for (i = 0; i < lm_cd.cd_ndevs; i++) {
lmsc = lm_cd.cd_devs[i];
if (lmsc == &sc->sc_lmsc)
continue;
if (lmsc && lmsc->sbusaddr == sbusaddr &&
lmsc->chipid == sc->sc_lmsc.chipid)
config_detach(&lmsc->sc_dev, 0);
}
#endif
return (0);
}
static int
lm_isa_detach(device_t dev)
{
struct lm_isa_softc *sc = device_get_softc(dev);
int error;
error = lm_detach(&sc->sc_lmsc);
if (error)
return (error);
error = bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_iorid,
sc->sc_iores);
if (error)
return (error);
return (0);
}
u_int8_t
lm_isa_readreg(struct lm_softc *lmsc, int reg)
{
struct lm_isa_softc *sc = (struct lm_isa_softc *)lmsc;
bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_ADDR, reg);
return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, LMC_DATA));
}
void
lm_isa_writereg(struct lm_softc *lmsc, int reg, int val)
{
struct lm_isa_softc *sc = (struct lm_isa_softc *)lmsc;
bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_ADDR, reg);
bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_DATA, val);
}