#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: isa_machdep.c,v 1.21 2025/05/01 05:36:02 tsutsui Exp $");
#define __INTR_PRIVATE
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/kmem.h>
#include <sys/queue.h>
#include <machine/sysconf.h>
#include <machine/autoconf.h>
#include <machine/mainboard.h>
#include <machine/bus.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isareg.h>
static int mipscoisabusprint(void *, const char *);
static int isabusmatch(device_t, cfdata_t, void *);
static void isabusattach(device_t, device_t, void *);
struct isabus_softc {
struct mipsco_isa_chipset sc_isa_ic;
};
CFATTACH_DECL_NEW(isabus, sizeof(struct isabus_softc),
isabusmatch, isabusattach, NULL, NULL);
extern struct cfdriver isabus_cd;
static struct mipsco_bus_space isa_io_bst, isa_mem_bst, isa_ctl_bst;
static struct mipsco_bus_dma_tag isa_dmatag;
static void isa_bus_space_init(struct mipsco_bus_space *, const char *,
paddr_t, size_t);
int isa_intr(void *);
int
isabusmatch(device_t parent, cfdata_t cfp, void *aux)
{
struct confargs *ca = aux;
if (strcmp(ca->ca_name, isabus_cd.cd_name) != 0)
return 0;
return 1;
}
static void
isa_bus_space_init(struct mipsco_bus_space *bst, const char *type, paddr_t paddr, size_t len)
{
vaddr_t vaddr = MIPS_PHYS_TO_KSEG1(paddr);
mipsco_bus_space_init(bst, type, paddr, vaddr, 0x0, len);
mipsco_bus_space_set_aligned_stride(bst, 2);
bst->bs_bswap = 1;
bst->bs_intr_establish = (void *)isa_intr_establish;
printf(" %s %p", type, (void *)vaddr);
}
void
isabusattach(device_t parent, device_t self, void *aux)
{
struct isabus_softc *sc = device_private(self);
struct mipsco_isa_chipset *ic = &sc->sc_isa_ic;
struct isabus_attach_args iba;
printf(":");
iba.iba_iot = &isa_io_bst;
iba.iba_memt = &isa_mem_bst;
iba.iba_dmat = &isa_dmatag;
iba.iba_ic = ic;
isa_bus_space_init(&isa_io_bst, "isa_io", PIZAZZ_ISA_IOBASE,
PIZAZZ_ISA_IOSIZE);
isa_bus_space_init(&isa_mem_bst, "isa_mem", PIZAZZ_ISA_MEMBASE,
PIZAZZ_ISA_MEMSIZE);
isa_bus_space_init(&isa_ctl_bst, "isa_intr", PIZAZZ_ISA_INTRLATCH,
sizeof(uint32_t));
_bus_dma_tag_init(&isa_dmatag);
ic->ic_bst = &isa_ctl_bst;
if (bus_space_map(ic->ic_bst, 0x00000, sizeof(uint32_t),
BUS_SPACE_MAP_LINEAR, &ic->ic_bsh) != 0) {
printf(": can't map intrreg\n");
return;
}
bus_space_write_4(ic->ic_bst, ic->ic_bsh, 0, 0);
evcnt_attach_dynamic(&ic->ic_intrcnt, EVCNT_TYPE_INTR, NULL,
device_xname(self), "intr");
LIST_INIT(&ic->intr_q);
(*platform.intr_establish)(SYS_INTR_ATBUS, isa_intr, ic);
printf("\n");
config_found(self, &iba, mipscoisabusprint, CFARGS_NONE);
}
int
mipscoisabusprint(void *aux, const char *name)
{
if (name == NULL)
return UNCONF;
return QUIET;
}
void
isa_attach_hook(device_t parent, device_t self, struct isabus_attach_args *iba)
{
}
void
isa_detach_hook(isa_chipset_tag_t ic, device_t self)
{
}
const struct evcnt *
isa_intr_evcnt(isa_chipset_tag_t ic, int irq)
{
return NULL;
}
void *
isa_intr_establish(isa_chipset_tag_t ic, int intr, int type, int level, int (*ih_fun)(void*), void *ih_arg)
{
struct mipsco_intrhand *ih;
ih = kmem_alloc(sizeof *ih, KM_SLEEP);
ih->ih_fun = ih_fun;
ih->ih_arg = ih_arg;
LIST_INSERT_HEAD(&ic->intr_q, ih, ih_q);
return ih;
}
void
isa_intr_disestablish(isa_chipset_tag_t ic, void *cookie)
{
struct mipsco_intrhand *ih = cookie;
LIST_REMOVE(ih, ih_q);
kmem_free(ih, sizeof(*ih));
}
int
isa_intr_alloc(isa_chipset_tag_t ic, int mask, int type, int *irq)
{
return 0;
}
int
isa_intr(void *arg)
{
struct mipsco_isa_chipset *ic = (struct mipsco_isa_chipset *)arg;
struct mipsco_intrhand *ih;
int rv, handled;
ic->ic_intrcnt.ev_count++;
handled = 0;
LIST_FOREACH(ih, &ic->intr_q, ih_q) {
rv = (*ih->ih_fun)(ih->ih_arg);
handled |= (rv != 0);
}
bus_space_write_4(ic->ic_bst, ic->ic_bsh, 0, 0);
return handled;
}