1 /* $NetBSD: isa_machdep.c,v 1.21 2025/05/01 05:36:02 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Wayne Knowles 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: isa_machdep.c,v 1.21 2025/05/01 05:36:02 tsutsui Exp $"); 34 35 #define __INTR_PRIVATE 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 #include <sys/kmem.h> 41 #include <sys/queue.h> 42 43 #include <machine/sysconf.h> 44 #include <machine/autoconf.h> 45 #include <machine/mainboard.h> 46 #include <machine/bus.h> 47 48 #include <dev/isa/isavar.h> 49 #include <dev/isa/isareg.h> 50 51 static int mipscoisabusprint(void *, const char *); 52 static int isabusmatch(device_t, cfdata_t, void *); 53 static void isabusattach(device_t, device_t, void *); 54 55 struct isabus_softc { 56 struct mipsco_isa_chipset sc_isa_ic; 57 }; 58 59 CFATTACH_DECL_NEW(isabus, sizeof(struct isabus_softc), 60 isabusmatch, isabusattach, NULL, NULL); 61 62 extern struct cfdriver isabus_cd; 63 64 static struct mipsco_bus_space isa_io_bst, isa_mem_bst, isa_ctl_bst; 65 static struct mipsco_bus_dma_tag isa_dmatag; 66 67 static void isa_bus_space_init(struct mipsco_bus_space *, const char *, 68 paddr_t, size_t); 69 int isa_intr(void *); 70 71 72 int 73 isabusmatch(device_t parent, cfdata_t cfp, void *aux) 74 { 75 struct confargs *ca = aux; 76 77 if (strcmp(ca->ca_name, isabus_cd.cd_name) != 0) 78 return 0; 79 return 1; 80 } 81 82 static void 83 isa_bus_space_init(struct mipsco_bus_space *bst, const char *type, paddr_t paddr, size_t len) 84 { 85 vaddr_t vaddr = MIPS_PHYS_TO_KSEG1(paddr); /* XXX */ 86 87 /* Setup default bus_space */ 88 mipsco_bus_space_init(bst, type, paddr, vaddr, 0x0, len); 89 90 /* ISA bus maps 1 word for every byte, therefore stride = 2 */ 91 mipsco_bus_space_set_aligned_stride(bst, 2); 92 93 /* 94 * ISA bus will do an automatic byte swap, but when accessing 95 * memory using bus_space_stream functions we need to byte swap 96 * to reverse the one performed in hardware 97 */ 98 bst->bs_bswap = 1; 99 100 bst->bs_intr_establish = (void *)isa_intr_establish; 101 102 printf(" %s %p", type, (void *)vaddr); 103 } 104 105 106 void 107 isabusattach(device_t parent, device_t self, void *aux) 108 { 109 struct isabus_softc *sc = device_private(self); 110 struct mipsco_isa_chipset *ic = &sc->sc_isa_ic; 111 struct isabus_attach_args iba; 112 113 printf(":"); 114 115 iba.iba_iot = &isa_io_bst; 116 iba.iba_memt = &isa_mem_bst; 117 iba.iba_dmat = &isa_dmatag; 118 iba.iba_ic = ic; 119 120 isa_bus_space_init(&isa_io_bst, "isa_io", PIZAZZ_ISA_IOBASE, 121 PIZAZZ_ISA_IOSIZE); 122 123 isa_bus_space_init(&isa_mem_bst, "isa_mem", PIZAZZ_ISA_MEMBASE, 124 PIZAZZ_ISA_MEMSIZE); 125 126 isa_bus_space_init(&isa_ctl_bst, "isa_intr", PIZAZZ_ISA_INTRLATCH, 127 sizeof(uint32_t)); 128 129 _bus_dma_tag_init(&isa_dmatag); 130 131 ic->ic_bst = &isa_ctl_bst; 132 133 if (bus_space_map(ic->ic_bst, 0x00000, sizeof(uint32_t), 134 BUS_SPACE_MAP_LINEAR, &ic->ic_bsh) != 0) { 135 printf(": can't map intrreg\n"); 136 return; 137 } 138 139 /* Clear ISA interrupt latch */ 140 bus_space_write_4(ic->ic_bst, ic->ic_bsh, 0, 0); 141 142 evcnt_attach_dynamic(&ic->ic_intrcnt, EVCNT_TYPE_INTR, NULL, 143 device_xname(self), "intr"); 144 145 LIST_INIT(&ic->intr_q); 146 (*platform.intr_establish)(SYS_INTR_ATBUS, isa_intr, ic); 147 148 printf("\n"); 149 config_found(self, &iba, mipscoisabusprint, CFARGS_NONE); 150 } 151 152 int 153 mipscoisabusprint(void *aux, const char *name) 154 { 155 if (name == NULL) 156 return UNCONF; 157 return QUIET; 158 } 159 160 void 161 isa_attach_hook(device_t parent, device_t self, struct isabus_attach_args *iba) 162 { 163 } 164 165 void 166 isa_detach_hook(isa_chipset_tag_t ic, device_t self) 167 { 168 } 169 170 const struct evcnt * 171 isa_intr_evcnt(isa_chipset_tag_t ic, int irq) 172 { 173 /* XXX for now, no evcnt parent reported */ 174 return NULL; 175 } 176 177 void * 178 isa_intr_establish(isa_chipset_tag_t ic, int intr, int type, int level, int (*ih_fun)(void*), void *ih_arg) 179 /* type: XXX not yet */ 180 /* level: XXX not yet */ 181 { 182 struct mipsco_intrhand *ih; 183 184 ih = kmem_alloc(sizeof *ih, KM_SLEEP); 185 ih->ih_fun = ih_fun; 186 ih->ih_arg = ih_arg; 187 LIST_INSERT_HEAD(&ic->intr_q, ih, ih_q); 188 return ih; 189 } 190 191 void 192 isa_intr_disestablish(isa_chipset_tag_t ic, void *cookie) 193 { 194 struct mipsco_intrhand *ih = cookie; 195 196 LIST_REMOVE(ih, ih_q); 197 kmem_free(ih, sizeof(*ih)); 198 } 199 200 int 201 isa_intr_alloc(isa_chipset_tag_t ic, int mask, int type, int *irq) 202 { 203 return 0; 204 } 205 206 int 207 isa_intr(void *arg) 208 { 209 struct mipsco_isa_chipset *ic = (struct mipsco_isa_chipset *)arg; 210 struct mipsco_intrhand *ih; 211 int rv, handled; 212 213 ic->ic_intrcnt.ev_count++; 214 215 handled = 0; 216 LIST_FOREACH(ih, &ic->intr_q, ih_q) { 217 /* 218 * The handler returns one of three values: 219 * 0: This interrupt wasn't for me. 220 * 1: This interrupt was for me. 221 * -1: This interrupt might have been for me, but I can't say 222 * for sure. 223 */ 224 rv = (*ih->ih_fun)(ih->ih_arg); 225 handled |= (rv != 0); 226 } 227 228 /* Clear ISA interrupt latch */ 229 bus_space_write_4(ic->ic_bst, ic->ic_bsh, 0, 0); 230 231 return handled; 232 } 233