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