1 1.37 thorpej /* $NetBSD: btvmei.c,v 1.37 2023/12/05 15:41:34 thorpej Exp $ */ 2 1.1 drochner 3 1.1 drochner /* 4 1.1 drochner * Copyright (c) 1999 5 1.1 drochner * Matthias Drochner. All rights reserved. 6 1.1 drochner * 7 1.1 drochner * Redistribution and use in source and binary forms, with or without 8 1.1 drochner * modification, are permitted provided that the following conditions 9 1.1 drochner * are met: 10 1.1 drochner * 1. Redistributions of source code must retain the above copyright 11 1.1 drochner * notice, this list of conditions and the following disclaimer. 12 1.1 drochner * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 drochner * notice, this list of conditions and the following disclaimer in the 14 1.1 drochner * documentation and/or other materials provided with the distribution. 15 1.1 drochner * 3. The name of the author may not be used to endorse or promote products 16 1.1 drochner * derived from this software without specific prior written permission. 17 1.1 drochner * 18 1.1 drochner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.1 drochner * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.1 drochner * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.1 drochner * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.1 drochner * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 1.1 drochner * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 1.1 drochner * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 1.1 drochner * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 1.1 drochner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 1.1 drochner * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 drochner * 29 1.1 drochner */ 30 1.6 lukem 31 1.6 lukem #include <sys/cdefs.h> 32 1.37 thorpej __KERNEL_RCSID(0, "$NetBSD: btvmei.c,v 1.37 2023/12/05 15:41:34 thorpej Exp $"); 33 1.1 drochner 34 1.1 drochner #include <sys/param.h> 35 1.1 drochner #include <sys/systm.h> 36 1.7 simonb #include <sys/kernel.h> 37 1.1 drochner #include <sys/device.h> 38 1.1 drochner #include <sys/proc.h> 39 1.36 thorpej #include <sys/kmem.h> 40 1.36 thorpej #include <sys/vmem.h> 41 1.1 drochner 42 1.17 ad #include <sys/bus.h> 43 1.1 drochner 44 1.1 drochner #include <dev/pci/pcireg.h> 45 1.1 drochner #include <dev/pci/pcivar.h> 46 1.1 drochner #include <dev/pci/pcidevs.h> 47 1.1 drochner 48 1.1 drochner #include <dev/vme/vmereg.h> 49 1.1 drochner #include <dev/vme/vmevar.h> 50 1.1 drochner 51 1.1 drochner #include <dev/pci/btvmeireg.h> 52 1.1 drochner #include <dev/pci/btvmeivar.h> 53 1.1 drochner 54 1.24 cegger static int b3_617_match(device_t, cfdata_t, void *); 55 1.24 cegger static void b3_617_attach(device_t, device_t, void *); 56 1.1 drochner #ifdef notyet 57 1.24 cegger static int b3_617_detach(device_t); 58 1.1 drochner #endif 59 1.24 cegger void b3_617_slaveconfig(device_t, struct vme_attach_args *); 60 1.1 drochner 61 1.13 perry static void b3_617_vmeintr(struct b3_617_softc *, unsigned char); 62 1.1 drochner 63 1.1 drochner /* 64 1.33 msaitoh * mapping resources, needed for deallocation 65 1.1 drochner */ 66 1.1 drochner struct b3_617_vmeresc { 67 1.1 drochner bus_space_handle_t handle; 68 1.1 drochner bus_size_t len; 69 1.1 drochner int firstpage, maplen; 70 1.1 drochner }; 71 1.1 drochner 72 1.29 chs CFATTACH_DECL_NEW(btvmei, sizeof(struct b3_617_softc), 73 1.11 thorpej b3_617_match, b3_617_attach, NULL, NULL); 74 1.1 drochner 75 1.1 drochner static int 76 1.24 cegger b3_617_match(device_t parent, cfdata_t match, void *aux) 77 1.1 drochner { 78 1.1 drochner struct pci_attach_args *pa = aux; 79 1.1 drochner 80 1.1 drochner if ((PCI_VENDOR(pa->pa_id) != PCI_VENDOR_BIT3) 81 1.1 drochner || (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_BIT3_PCIVME617)) 82 1.1 drochner return (0); 83 1.1 drochner return (1); 84 1.1 drochner } 85 1.1 drochner 86 1.1 drochner static void 87 1.24 cegger b3_617_attach(device_t parent, device_t self, void *aux) 88 1.1 drochner { 89 1.25 cegger struct b3_617_softc *sc = device_private(self); 90 1.1 drochner struct pci_attach_args *pa = aux; 91 1.1 drochner pci_chipset_tag_t pc = pa->pa_pc; 92 1.1 drochner 93 1.1 drochner pci_intr_handle_t ih; 94 1.1 drochner const char *intrstr; 95 1.1 drochner struct vmebus_attach_args vaa; 96 1.30 christos char intrbuf[PCI_INTRSTR_LEN]; 97 1.1 drochner 98 1.29 chs sc->sc_dev = self; 99 1.1 drochner sc->sc_pc = pc; 100 1.1 drochner sc->sc_dmat = pa->pa_dmat; 101 1.1 drochner 102 1.28 drochner pci_aprint_devinfo_fancy(pa, "VME bus adapter", "BIT3 PCI-VME 617", 1); 103 1.1 drochner 104 1.1 drochner /* 105 1.1 drochner * Map CSR and mapping table spaces. 106 1.1 drochner * Don't map VME window; parts are mapped as needed to 107 1.1 drochner * save kernel virtual memory space 108 1.1 drochner */ 109 1.1 drochner if (pci_mapreg_map(pa, 0x14, 110 1.1 drochner PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 111 1.1 drochner 0, &sc->csrt, &sc->csrh, NULL, NULL) && 112 1.1 drochner pci_mapreg_map(pa, 0x10, 113 1.1 drochner PCI_MAPREG_TYPE_IO, 114 1.1 drochner 0, &sc->csrt, &sc->csrh, NULL, NULL)) { 115 1.18 cegger aprint_error_dev(self, "can't map CSR space\n"); 116 1.1 drochner return; 117 1.1 drochner } 118 1.1 drochner 119 1.1 drochner if (pci_mapreg_map(pa, 0x18, 120 1.1 drochner PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 121 1.1 drochner 0, &sc->mapt, &sc->maph, NULL, NULL)) { 122 1.18 cegger aprint_error_dev(self, "can't map map space\n"); 123 1.1 drochner return; 124 1.1 drochner } 125 1.1 drochner 126 1.1 drochner if (pci_mapreg_info(pc, pa->pa_tag, 0x1c, 127 1.1 drochner PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 128 1.1 drochner &sc->vmepbase, 0, 0)) { 129 1.18 cegger aprint_error_dev(self, "can't get VME range\n"); 130 1.1 drochner return; 131 1.1 drochner } 132 1.1 drochner sc->sc_vmet = pa->pa_memt; /* XXX needed for VME mappings */ 133 1.1 drochner 134 1.1 drochner /* Map and establish the interrupt. */ 135 1.4 sommerfe if (pci_intr_map(pa, &ih)) { 136 1.29 chs aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n"); 137 1.1 drochner return; 138 1.1 drochner } 139 1.30 christos intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); 140 1.1 drochner /* 141 1.1 drochner * Use a low interrupt level (the lowest?). 142 1.1 drochner * We will raise before calling a subdevice's handler. 143 1.1 drochner */ 144 1.31 jdolecek sc->sc_ih = pci_intr_establish_xname(pc, ih, IPL_BIO, b3_617_intr, sc, 145 1.31 jdolecek device_xname(self)); 146 1.1 drochner if (sc->sc_ih == NULL) { 147 1.29 chs aprint_error_dev(sc->sc_dev, "couldn't establish interrupt"); 148 1.1 drochner if (intrstr != NULL) 149 1.26 njoly aprint_error(" at %s", intrstr); 150 1.26 njoly aprint_error("\n"); 151 1.1 drochner return; 152 1.1 drochner } 153 1.29 chs aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); 154 1.1 drochner 155 1.1 drochner if (b3_617_init(sc)) 156 1.1 drochner return; 157 1.1 drochner 158 1.1 drochner /* 159 1.1 drochner * set up all the tags for use by VME devices 160 1.1 drochner */ 161 1.1 drochner sc->sc_vct.cookie = self; 162 1.1 drochner sc->sc_vct.vct_probe = b3_617_vme_probe; 163 1.1 drochner sc->sc_vct.vct_map = b3_617_map_vme; 164 1.1 drochner sc->sc_vct.vct_unmap = b3_617_unmap_vme; 165 1.1 drochner sc->sc_vct.vct_int_map = b3_617_map_vmeint; 166 1.1 drochner sc->sc_vct.vct_int_establish = b3_617_establish_vmeint; 167 1.1 drochner sc->sc_vct.vct_int_disestablish = b3_617_disestablish_vmeint; 168 1.1 drochner sc->sc_vct.vct_dmamap_create = b3_617_dmamap_create; 169 1.1 drochner sc->sc_vct.vct_dmamap_destroy = b3_617_dmamap_destroy; 170 1.1 drochner sc->sc_vct.vct_dmamem_alloc = b3_617_dmamem_alloc; 171 1.1 drochner sc->sc_vct.vct_dmamem_free = b3_617_dmamem_free; 172 1.1 drochner 173 1.1 drochner vaa.va_vct = &(sc->sc_vct); 174 1.1 drochner vaa.va_bdt = pa->pa_dmat; 175 1.1 drochner vaa.va_slaveconfig = b3_617_slaveconfig; 176 1.1 drochner 177 1.1 drochner sc->csrwindow.offset = -1; 178 1.1 drochner sc->dmawindow24.offset = -1; 179 1.1 drochner sc->dmawindow32.offset = -1; 180 1.35 thorpej config_found(self, &vaa, 0, CFARGS_NONE); 181 1.1 drochner } 182 1.1 drochner 183 1.1 drochner #ifdef notyet 184 1.1 drochner static int 185 1.24 cegger b3_617_detach(device_t dev) 186 1.1 drochner { 187 1.25 cegger struct b3_617_softc *sc = device_private(dev); 188 1.1 drochner 189 1.1 drochner b3_617_halt(sc); 190 1.1 drochner 191 1.1 drochner if (sc->sc_ih) 192 1.1 drochner pci_intr_disestablish(sc->sc_pc, sc->sc_ih); 193 1.1 drochner 194 1.1 drochner bus_space_unmap(sc->sc_bc, sc->csrbase, 32); 195 1.1 drochner bus_space_unmap(sc->sc_bc, sc->mapbase, 64*1024); 196 1.1 drochner 197 1.1 drochner return(0); 198 1.1 drochner } 199 1.1 drochner #endif 200 1.1 drochner 201 1.1 drochner void 202 1.24 cegger b3_617_slaveconfig(device_t dev, struct vme_attach_args *va) 203 1.1 drochner { 204 1.25 cegger struct b3_617_softc *sc = device_private(dev); 205 1.1 drochner vme_chipset_tag_t vmect; 206 1.1 drochner int i, res; 207 1.16 cube const char *name = 0; /* XXX gcc! */ 208 1.1 drochner 209 1.1 drochner vmect = &sc->sc_vct; 210 1.1 drochner if (!va) 211 1.1 drochner goto freeit; 212 1.1 drochner 213 1.1 drochner #ifdef DIAGNOSTIC 214 1.1 drochner if (vmect != va->va_vct) 215 1.8 provos panic("pcivme_slaveconfig: chipset tag?"); 216 1.1 drochner #endif 217 1.1 drochner 218 1.1 drochner for (i = 0; i < va->numcfranges; i++) { 219 1.1 drochner res = vme_space_alloc(vmect, va->r[i].offset, 220 1.1 drochner va->r[i].size, va->r[i].am); 221 1.1 drochner if (res) 222 1.1 drochner panic("%s: can't alloc slave window %x/%x/%x", 223 1.18 cegger device_xname(dev), va->r[i].offset, 224 1.1 drochner va->r[i].size, va->r[i].am); 225 1.1 drochner 226 1.1 drochner switch (va->r[i].am & VME_AM_ADRSIZEMASK) { 227 1.1 drochner /* structure assignments! */ 228 1.1 drochner case VME_AM_A16: 229 1.1 drochner sc->csrwindow = va->r[i]; 230 1.1 drochner name = "VME CSR"; 231 1.1 drochner break; 232 1.1 drochner case VME_AM_A24: 233 1.1 drochner sc->dmawindow24 = va->r[i]; 234 1.1 drochner name = "A24 DMA"; 235 1.1 drochner break; 236 1.1 drochner case VME_AM_A32: 237 1.1 drochner sc->dmawindow32 = va->r[i]; 238 1.1 drochner name = "A32 DMA"; 239 1.1 drochner break; 240 1.1 drochner } 241 1.18 cegger printf("%s: %s window: %x-%x\n", device_xname(dev), 242 1.1 drochner name, va->r[i].offset, 243 1.1 drochner va->r[i].offset + va->r[i].size - 1); 244 1.1 drochner } 245 1.1 drochner return; 246 1.1 drochner 247 1.1 drochner freeit: 248 1.1 drochner if (sc->csrwindow.offset != -1) 249 1.1 drochner vme_space_free(vmect, sc->csrwindow.offset, 250 1.1 drochner sc->csrwindow.size, sc->csrwindow.am); 251 1.1 drochner if (sc->dmawindow32.offset != -1) 252 1.1 drochner vme_space_free(vmect, sc->dmawindow32.offset, 253 1.1 drochner sc->dmawindow32.size, sc->dmawindow32.am); 254 1.1 drochner if (sc->dmawindow24.offset != -1) 255 1.1 drochner vme_space_free(vmect, sc->dmawindow24.offset, 256 1.1 drochner sc->dmawindow24.size, sc->dmawindow24.am); 257 1.1 drochner } 258 1.1 drochner 259 1.1 drochner int 260 1.20 dsl b3_617_reset(struct b3_617_softc *sc) 261 1.1 drochner { 262 1.1 drochner unsigned char status; 263 1.1 drochner 264 1.1 drochner /* reset sequence, ch 5.2 */ 265 1.1 drochner status = read_csr_byte(sc, LOC_STATUS); 266 1.1 drochner if (status & LSR_NO_CONNECT) { 267 1.29 chs printf("%s: not connected\n", device_xname(sc->sc_dev)); 268 1.1 drochner return (-1); 269 1.1 drochner } 270 1.1 drochner status = read_csr_byte(sc, REM_STATUS); /* discard */ 271 1.1 drochner write_csr_byte(sc, LOC_CMD1, LC1_CLR_ERROR); 272 1.1 drochner status = read_csr_byte(sc, LOC_STATUS); 273 1.1 drochner if (status & LSR_CERROR_MASK) { 274 1.3 tv char sbuf[sizeof(BIT3_LSR_BITS) + 64]; 275 1.2 tv 276 1.19 christos snprintb(sbuf, sizeof(sbuf), BIT3_LSR_BITS, status); 277 1.29 chs printf("%s: interface error, lsr=%s\n", device_xname(sc->sc_dev), 278 1.2 tv sbuf); 279 1.1 drochner return (-1); 280 1.1 drochner } 281 1.1 drochner return (0); 282 1.1 drochner } 283 1.1 drochner 284 1.1 drochner int 285 1.20 dsl b3_617_init(struct b3_617_softc *sc) 286 1.1 drochner { 287 1.1 drochner unsigned int i; 288 1.1 drochner 289 1.1 drochner if (b3_617_reset(sc)) 290 1.1 drochner return (-1); 291 1.1 drochner 292 1.1 drochner /* all maps invalid */ 293 1.1 drochner for (i = MR_PCI_VME; i < MR_PCI_VME + MR_PCI_VME_SIZE; i += 4) 294 1.1 drochner write_mapmem(sc, i, MR_RAM_INVALID); 295 1.1 drochner for (i = MR_VME_PCI; i < MR_VME_PCI + MR_VME_PCI_SIZE; i += 4) 296 1.1 drochner write_mapmem(sc, i, MR_RAM_INVALID); 297 1.1 drochner for (i = MR_DMA_PCI; i < MR_DMA_PCI + MR_DMA_PCI_SIZE; i += 4) 298 1.1 drochner write_mapmem(sc, i, MR_RAM_INVALID); 299 1.1 drochner 300 1.1 drochner /* 301 1.1 drochner * set up scatter page allocation control 302 1.1 drochner */ 303 1.36 thorpej sc->vme_arena = vmem_create("pcivme", 304 1.36 thorpej MR_PCI_VME, /* base */ 305 1.36 thorpej MR_PCI_VME_SIZE, /* size */ 306 1.36 thorpej 4, /* quantum */ 307 1.36 thorpej NULL, /* allocfn */ 308 1.36 thorpej NULL, /* releasefn */ 309 1.36 thorpej NULL, /* source */ 310 1.36 thorpej 0, /* qcache_max */ 311 1.36 thorpej VM_SLEEP, 312 1.36 thorpej IPL_NONE); 313 1.1 drochner #if 0 314 1.36 thorpej sc->vme_arena = vmem_create("vmepci", 315 1.36 thorpej MR_VME_PCI, /* base */ 316 1.36 thorpej MR_VME_PCI_SIZE, /* size */ 317 1.36 thorpej 4, /* quantum */ 318 1.36 thorpej NULL, /* allocfn */ 319 1.36 thorpej NULL, /* releasefn */ 320 1.36 thorpej NULL, /* source */ 321 1.36 thorpej 0, /* qcache_max */ 322 1.36 thorpej VM_SLEEP, 323 1.36 thorpej IPL_NONE); 324 1.36 thorpej 325 1.36 thorpej sc->dma_arena = vmem_create("dmapci", 326 1.36 thorpej MR_DMA_PCI, /* base */ 327 1.36 thorpej MR_DMA_PCI_SIZE, /* size */ 328 1.36 thorpej XXX, /* quantum */ 329 1.36 thorpej NULL, /* allocfn */ 330 1.36 thorpej NULL, /* releasefn */ 331 1.36 thorpej NULL, /* source */ 332 1.36 thorpej 0, /* qcache_max */ 333 1.36 thorpej VM_SLEEP, 334 1.36 thorpej IPL_VM); 335 1.1 drochner #endif 336 1.1 drochner 337 1.1 drochner /* 338 1.1 drochner * init int handler queue, 339 1.1 drochner * enable interrupts if PCI interrupt available 340 1.1 drochner */ 341 1.1 drochner TAILQ_INIT(&(sc->intrhdls)); 342 1.1 drochner sc->strayintrs = 0; 343 1.1 drochner 344 1.1 drochner if (sc->sc_ih) 345 1.1 drochner write_csr_byte(sc, LOC_INT_CTRL, LIC_INT_ENABLE); 346 1.1 drochner /* no error ints */ 347 1.1 drochner write_csr_byte(sc, REM_CMD2, 0); /* enables VME IRQ */ 348 1.1 drochner 349 1.1 drochner return (0); 350 1.1 drochner } 351 1.1 drochner 352 1.1 drochner #ifdef notyet /* for detach */ 353 1.1 drochner void 354 1.20 dsl b3_617_halt(struct b3_617_softc *sc) 355 1.1 drochner { 356 1.1 drochner /* 357 1.1 drochner * because detach code checks for existence of children, 358 1.33 msaitoh * all resources (mappings, VME IRQs, DMA requests) 359 1.1 drochner * should be deallocated at this point 360 1.1 drochner */ 361 1.1 drochner 362 1.1 drochner /* disable IRQ */ 363 1.1 drochner write_csr_byte(sc, LOC_INT_CTRL, 0); 364 1.1 drochner } 365 1.1 drochner #endif 366 1.1 drochner 367 1.1 drochner static void 368 1.20 dsl b3_617_vmeintr(struct b3_617_softc *sc, unsigned char lstat) 369 1.1 drochner { 370 1.1 drochner int level; 371 1.1 drochner 372 1.1 drochner for (level = 7; level >= 1; level--) { 373 1.1 drochner unsigned char vector; 374 1.1 drochner struct b3_617_vmeintrhand *ih; 375 1.1 drochner int found; 376 1.1 drochner 377 1.1 drochner if (!(lstat & (1 << level))) 378 1.1 drochner continue; 379 1.1 drochner 380 1.1 drochner write_csr_byte(sc, REM_CMD1, level); 381 1.1 drochner vector = read_csr_byte(sc, REM_IACK); 382 1.1 drochner 383 1.1 drochner found = 0; 384 1.1 drochner 385 1.1 drochner for (ih = sc->intrhdls.tqh_first; ih; 386 1.1 drochner ih = ih->ih_next.tqe_next) { 387 1.1 drochner if ((ih->ih_level == level) && 388 1.1 drochner ((ih->ih_vector == -1) || 389 1.1 drochner (ih->ih_vector == vector))) { 390 1.1 drochner int s, res; 391 1.1 drochner /* 392 1.1 drochner * We should raise the interrupt level 393 1.1 drochner * to ih->ih_prior here. How to do this 394 1.15 wiz * machine-independently? 395 1.1 drochner * To be safe, raise to the maximum. 396 1.1 drochner */ 397 1.1 drochner s = splhigh(); 398 1.1 drochner found |= (res = (*(ih->ih_fun))(ih->ih_arg)); 399 1.1 drochner splx(s); 400 1.1 drochner if (res) 401 1.1 drochner ih->ih_count++; 402 1.1 drochner if (res == 1) 403 1.1 drochner break; 404 1.1 drochner } 405 1.1 drochner } 406 1.1 drochner if (!found) 407 1.1 drochner sc->strayintrs++; 408 1.1 drochner } 409 1.1 drochner } 410 1.1 drochner 411 1.1 drochner #define sc ((struct b3_617_softc*)vsc) 412 1.1 drochner 413 1.1 drochner int 414 1.20 dsl b3_617_map_vme(void *vsc, vme_addr_t vmeaddr, vme_size_t len, vme_am_t am, vme_datasize_t datasizes, vme_swap_t swap, bus_space_tag_t *tag, bus_space_handle_t *handle, vme_mapresc_t *resc) 415 1.1 drochner { 416 1.1 drochner vme_addr_t vmebase, vmeend, va; 417 1.36 thorpej unsigned long maplen, i; 418 1.36 thorpej vmem_addr_t first; 419 1.1 drochner u_int32_t mapreg; 420 1.1 drochner bus_addr_t pcibase; 421 1.1 drochner int res; 422 1.1 drochner struct b3_617_vmeresc *r; 423 1.1 drochner 424 1.1 drochner /* first mapped address */ 425 1.1 drochner vmebase = vmeaddr & ~(VME_PAGESIZE - 1); 426 1.1 drochner /* base of last mapped page */ 427 1.1 drochner vmeend = (vmeaddr + len - 1) & ~(VME_PAGESIZE - 1); 428 1.1 drochner /* bytes in scatter table required */ 429 1.1 drochner maplen = ((vmeend - vmebase) / VME_PAGESIZE + 1) * 4; 430 1.1 drochner 431 1.37 thorpej if (vmem_alloc(sc->vme_arena, maplen, VM_BESTFIT | VM_NOSLEEP, &first)) 432 1.1 drochner return (ENOMEM); 433 1.1 drochner 434 1.1 drochner /* 435 1.1 drochner * set up adapter mapping registers 436 1.1 drochner */ 437 1.1 drochner mapreg = (am << MR_AMOD_SHIFT) | MR_FC_RRAM | swap; 438 1.1 drochner 439 1.1 drochner for (i = first, va = vmebase; 440 1.1 drochner i < first + maplen; 441 1.1 drochner i += 4, va += VME_PAGESIZE) { 442 1.1 drochner write_mapmem(sc, i, mapreg | va); 443 1.1 drochner #ifdef BIT3DEBUG 444 1.1 drochner printf("mapreg@%lx=%x\n", i, read_mapmem(sc, i)); 445 1.1 drochner #endif 446 1.1 drochner } 447 1.1 drochner 448 1.1 drochner #ifdef DIAGNOSTIC 449 1.1 drochner if (va != vmeend + VME_PAGESIZE) 450 1.1 drochner panic("b3_617_map_pci_vme: botch"); 451 1.1 drochner #endif 452 1.1 drochner /* 453 1.1 drochner * map needed range in PCI space 454 1.1 drochner */ 455 1.1 drochner pcibase = sc->vmepbase + (first - MR_PCI_VME) / 4 * VME_PAGESIZE 456 1.1 drochner + (vmeaddr & (VME_PAGESIZE - 1)); 457 1.1 drochner 458 1.1 drochner if ((res = bus_space_map(sc->sc_vmet, pcibase, len, 0, handle))) { 459 1.1 drochner for (i = first; i < first + maplen; i += 4) 460 1.1 drochner write_mapmem(sc, i, MR_RAM_INVALID); 461 1.36 thorpej vmem_free(sc->vme_arena, first, maplen); 462 1.1 drochner return (res); 463 1.1 drochner } 464 1.1 drochner 465 1.1 drochner *tag = sc->sc_vmet; 466 1.1 drochner 467 1.1 drochner /* 468 1.1 drochner * save all data needed for later unmapping 469 1.1 drochner */ 470 1.36 thorpej r = kmem_alloc(sizeof(*r), KM_SLEEP); 471 1.1 drochner r->handle = *handle; 472 1.1 drochner r->len = len; 473 1.1 drochner r->firstpage = first; 474 1.1 drochner r->maplen = maplen; 475 1.1 drochner *resc = r; 476 1.1 drochner return (0); 477 1.1 drochner } 478 1.1 drochner 479 1.1 drochner void 480 1.20 dsl b3_617_unmap_vme(void *vsc, vme_mapresc_t resc) 481 1.1 drochner { 482 1.1 drochner unsigned long i; 483 1.1 drochner struct b3_617_vmeresc *r = resc; 484 1.1 drochner 485 1.1 drochner /* unmap PCI window */ 486 1.1 drochner bus_space_unmap(sc->sc_vmet, r->handle, r->len); 487 1.1 drochner 488 1.1 drochner for (i = r->firstpage; i < r->firstpage + r->maplen; i += 4) 489 1.1 drochner write_mapmem(sc, i, MR_RAM_INVALID); 490 1.1 drochner 491 1.36 thorpej vmem_free(sc->vme_arena, r->firstpage, r->maplen); 492 1.36 thorpej kmem_free(r, sizeof(*r)); 493 1.1 drochner } 494 1.1 drochner 495 1.1 drochner int 496 1.22 dsl b3_617_vme_probe(void *vsc, vme_addr_t addr, vme_size_t len, vme_am_t am, vme_datasize_t datasize, int (*callback)(void *, bus_space_tag_t, bus_space_handle_t), void *cbarg) 497 1.1 drochner { 498 1.1 drochner bus_space_tag_t tag; 499 1.1 drochner bus_space_handle_t handle; 500 1.1 drochner vme_mapresc_t resc; 501 1.1 drochner int res, i; 502 1.1 drochner volatile u_int32_t dummy; 503 1.1 drochner int status; 504 1.1 drochner 505 1.1 drochner res = b3_617_map_vme(vsc, addr, len, am, 0, 0, 506 1.1 drochner &tag, &handle, &resc); 507 1.1 drochner if (res) 508 1.1 drochner return (res); 509 1.1 drochner 510 1.1 drochner if (read_csr_byte(sc, LOC_STATUS) & LSR_ERROR_MASK) { 511 1.1 drochner printf("b3_617_vme_badaddr: error bit not clean - resetting\n"); 512 1.1 drochner write_csr_byte(sc, LOC_CMD1, LC1_CLR_ERROR); 513 1.1 drochner } 514 1.1 drochner 515 1.1 drochner if (callback) 516 1.1 drochner res = (*callback)(cbarg, tag, handle); 517 1.1 drochner else { 518 1.1 drochner for (i = 0; i < len;) { 519 1.1 drochner switch (datasize) { 520 1.1 drochner case VME_D8: 521 1.1 drochner dummy = bus_space_read_1(tag, handle, i); 522 1.36 thorpej (void)dummy; 523 1.1 drochner i++; 524 1.1 drochner break; 525 1.1 drochner case VME_D16: 526 1.1 drochner dummy = bus_space_read_2(tag, handle, i); 527 1.36 thorpej (void)dummy; 528 1.1 drochner i += 2; 529 1.1 drochner break; 530 1.1 drochner case VME_D32: 531 1.1 drochner dummy = bus_space_read_4(tag, handle, i); 532 1.36 thorpej (void)dummy; 533 1.1 drochner i += 4; 534 1.1 drochner break; 535 1.1 drochner default: 536 1.1 drochner panic("b3_617_vme_probe: invalid datasize %x", 537 1.1 drochner datasize); 538 1.1 drochner } 539 1.1 drochner } 540 1.1 drochner } 541 1.1 drochner 542 1.1 drochner if ((status = read_csr_byte(sc, LOC_STATUS)) & LSR_ERROR_MASK) { 543 1.1 drochner #ifdef BIT3DEBUG 544 1.1 drochner printf("b3_617_vme_badaddr: caught error %x\n", status); 545 1.1 drochner #endif 546 1.1 drochner write_csr_byte(sc, LOC_CMD1, LC1_CLR_ERROR); 547 1.1 drochner res = EIO; 548 1.1 drochner } 549 1.1 drochner 550 1.1 drochner b3_617_unmap_vme(vsc, resc); 551 1.1 drochner return (res); 552 1.1 drochner } 553 1.1 drochner 554 1.1 drochner int 555 1.21 dsl b3_617_map_vmeint(void *vsc, int level, int vector, vme_intr_handle_t *handlep) 556 1.1 drochner { 557 1.1 drochner if (!sc->sc_ih) { 558 1.1 drochner printf("%s: b3_617_map_vmeint: no IRQ\n", 559 1.29 chs device_xname(sc->sc_dev)); 560 1.1 drochner return (ENXIO); 561 1.1 drochner } 562 1.1 drochner /* 563 1.1 drochner * We should check whether the interface can pass this interrupt 564 1.1 drochner * level at all, but we don't know much about the jumper setting. 565 1.1 drochner */ 566 1.1 drochner *handlep = (void *)(long)((level << 8) | vector); /* XXX */ 567 1.1 drochner return (0); 568 1.1 drochner } 569 1.1 drochner 570 1.1 drochner void * 571 1.22 dsl b3_617_establish_vmeint(void *vsc, vme_intr_handle_t handle, int prior, int (*func)(void *), void *arg) 572 1.1 drochner { 573 1.1 drochner struct b3_617_vmeintrhand *ih; 574 1.1 drochner long lv; 575 1.1 drochner int s; 576 1.1 drochner 577 1.36 thorpej ih = kmem_alloc(sizeof *ih, KM_SLEEP); 578 1.1 drochner 579 1.1 drochner lv = (long)handle; /* XXX */ 580 1.1 drochner 581 1.1 drochner ih->ih_fun = func; 582 1.1 drochner ih->ih_arg = arg; 583 1.1 drochner ih->ih_level = lv >> 8; 584 1.1 drochner ih->ih_vector = lv & 0xff; 585 1.1 drochner ih->ih_prior = prior; 586 1.1 drochner ih->ih_count = 0; 587 1.1 drochner 588 1.1 drochner s = splhigh(); 589 1.1 drochner TAILQ_INSERT_TAIL(&(sc->intrhdls), ih, ih_next); 590 1.1 drochner splx(s); 591 1.1 drochner 592 1.1 drochner return (ih); 593 1.1 drochner } 594 1.1 drochner 595 1.1 drochner void 596 1.20 dsl b3_617_disestablish_vmeint(void *vsc, void *cookie) 597 1.1 drochner { 598 1.1 drochner struct b3_617_vmeintrhand *ih = cookie; 599 1.1 drochner int s; 600 1.1 drochner 601 1.1 drochner if (!ih) { 602 1.1 drochner printf("b3_617_unmap_vmeint: NULL arg\n"); 603 1.1 drochner return; 604 1.1 drochner } 605 1.1 drochner 606 1.1 drochner s = splhigh(); 607 1.1 drochner TAILQ_REMOVE(&(sc->intrhdls), ih, ih_next); 608 1.1 drochner splx(s); 609 1.1 drochner 610 1.36 thorpej kmem_free(ih, sizeof(*ih)); 611 1.1 drochner } 612 1.1 drochner 613 1.1 drochner int 614 1.20 dsl b3_617_intr(void *vsc) 615 1.1 drochner { 616 1.1 drochner int handled = 0; 617 1.1 drochner 618 1.1 drochner /* follows ch. 5.5.5 (reordered for speed) */ 619 1.1 drochner while (read_csr_byte(sc, LOC_INT_CTRL) & LIC_INT_PENDING) { 620 1.1 drochner unsigned char lstat; 621 1.1 drochner 622 1.1 drochner handled = 1; 623 1.1 drochner 624 1.1 drochner /* no error interrupts! */ 625 1.1 drochner 626 1.1 drochner lstat = read_csr_byte(sc, LDMA_CMD); 627 1.1 drochner if ((lstat & LDC_DMA_DONE) && (lstat & LDC_DMA_INT_ENABLE)) { 628 1.1 drochner /* DMA done indicator flag */ 629 1.1 drochner write_csr_byte(sc, LDMA_CMD, lstat & (~LDC_DMA_DONE)); 630 1.1 drochner #if 0 631 1.1 drochner b3_617_cntlrdma_done(sc); 632 1.1 drochner #endif 633 1.1 drochner continue; 634 1.1 drochner } 635 1.1 drochner 636 1.1 drochner lstat = read_csr_byte(sc, LOC_INT_STATUS); 637 1.1 drochner if (lstat & LIS_CINT_MASK) { 638 1.1 drochner /* VME backplane interrupt, ch. 5.5.3 */ 639 1.1 drochner b3_617_vmeintr(sc, lstat); 640 1.1 drochner } 641 1.1 drochner 642 1.1 drochner /* for now, ignore "mailbox interrupts" */ 643 1.1 drochner 644 1.1 drochner lstat = read_csr_byte(sc, LOC_STATUS); 645 1.1 drochner if (lstat & LSR_PR_STATUS) { 646 1.5 wiz /* PR interrupt received from REMOTE */ 647 1.1 drochner write_csr_byte(sc, LOC_CMD1, LC1_CLR_PR_INT); 648 1.1 drochner continue; 649 1.1 drochner } 650 1.1 drochner 651 1.1 drochner lstat = read_csr_byte(sc, REM_STATUS); 652 1.1 drochner if (lstat & RSR_PT_STATUS) { 653 1.1 drochner /* PT interrupt is set */ 654 1.1 drochner write_csr_byte(sc, REM_CMD1, RC1_CLR_PT_INT); 655 1.1 drochner continue; 656 1.1 drochner } 657 1.1 drochner } 658 1.1 drochner return (handled); 659 1.1 drochner } 660 1.1 drochner 661 1.1 drochner int 662 1.36 thorpej b3_617_dmamap_create(void *vsc, vme_size_t len, vme_am_t am, 663 1.36 thorpej vme_datasize_t datasize, vme_swap_t swap, int nsegs, vme_size_t segsz, 664 1.36 thorpej vme_addr_t bound, int flags, bus_dmamap_t *mapp) 665 1.1 drochner { 666 1.1 drochner return (EINVAL); 667 1.1 drochner } 668 1.1 drochner 669 1.1 drochner void 670 1.20 dsl b3_617_dmamap_destroy(void *vsc, bus_dmamap_t map) 671 1.1 drochner { 672 1.1 drochner } 673 1.1 drochner 674 1.1 drochner int 675 1.36 thorpej b3_617_dmamem_alloc(void *vsc, vme_size_t len, vme_am_t am, 676 1.36 thorpej vme_datasize_t datasizes, vme_swap_t swap, bus_dma_segment_t *segs, 677 1.36 thorpej int nsegs, int *rsegs, int flags) 678 1.1 drochner { 679 1.1 drochner return (EINVAL); 680 1.1 drochner } 681 1.1 drochner 682 1.1 drochner void 683 1.20 dsl b3_617_dmamem_free(void *vsc, bus_dma_segment_t *segs, int nsegs) 684 1.1 drochner { 685 1.1 drochner } 686 1.1 drochner 687 1.1 drochner #undef sc 688