1 /* $NetBSD: dino.c,v 1.11 2021/04/24 23:36:39 thorpej Exp $ */ 2 3 /* $OpenBSD: dino.c,v 1.5 2004/02/13 20:39:31 mickey Exp $ */ 4 5 /* 6 * Copyright (c) 2003 Michael Shalayeff 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: dino.c,v 1.11 2021/04/24 23:36:39 thorpej Exp $"); 33 34 /* #include "cardbus.h" */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/device.h> 39 #include <sys/reboot.h> 40 #include <sys/malloc.h> 41 #include <sys/extent.h> 42 43 #include <machine/iomod.h> 44 #include <machine/autoconf.h> 45 #include <machine/intr.h> 46 47 #include <hppa/include/vmparam.h> 48 #include <hppa/dev/cpudevs.h> 49 50 #if NCARDBUS > 0 51 #include <dev/cardbus/rbus.h> 52 #endif 53 54 #include <dev/pci/pcireg.h> 55 #include <dev/pci/pcivar.h> 56 #include <dev/pci/pcidevs.h> 57 58 #define DINO_MEM_CHUNK 0x800000 59 60 /* from machdep.c */ 61 extern struct extent *hppa_io_extent; 62 63 struct dino_regs { 64 /* HPA Supervisory Register Set */ 65 uint32_t pad0; /* 0x000 */ 66 uint32_t iar0; /* 0x004 rw intr addr reg 0 */ 67 uint32_t iodc; /* 0x008 rw iodc data/addr */ 68 uint32_t irr0; /* 0x00c r intr req reg 0 */ 69 uint32_t iar1; /* 0x010 rw intr addr reg 1 */ 70 uint32_t irr1; /* 0x014 r intr req reg 1 */ 71 uint32_t imr; /* 0x018 rw intr mask reg */ 72 uint32_t ipr; /* 0x01c rw intr pending reg */ 73 uint32_t toc_addr; /* 0x020 rw TOC addr reg */ 74 uint32_t icr; /* 0x024 rw intr control reg */ 75 uint32_t ilr; /* 0x028 r intr level reg */ 76 uint32_t pad1; /* 0x02c */ 77 uint32_t io_command; /* 0x030 w command register */ 78 uint32_t io_status; /* 0x034 r status register */ 79 uint32_t io_control; /* 0x038 rw control register */ 80 uint32_t pad2; /* 0x03c AUX registers follow */ 81 82 /* HPA Auxiliary Register Set */ 83 uint32_t io_gsc_err_addr;/* 0x040 GSC error address */ 84 uint32_t io_err_info; /* 0x044 error info register */ 85 uint32_t io_pci_err_addr;/* 0x048 PCI error address */ 86 uint32_t pad3[4]; /* 0x04c */ 87 uint32_t io_fbb_en; /* 0x05c fast back2back enable reg */ 88 uint32_t io_addr_en; /* 0x060 address enable reg */ 89 uint32_t pci_addr; /* 0x064 PCI conf/io/mem addr reg */ 90 uint32_t pci_conf_data; /* 0x068 PCI conf data reg */ 91 uint32_t pci_io_data; /* 0x06c PCI io data reg */ 92 uint32_t pci_mem_data; /* 0x070 PCI memory data reg */ 93 uint32_t pad4[0x740/4]; /* 0x074 */ 94 95 /* HPA Bus (GSC) Specific-Dependent Register Set */ 96 uint32_t gsc2x_config; /* 0x7b4 GSC2X config reg */ 97 uint32_t pad5[0x48/4]; /* 0x7b8: BSRS registers follow */ 98 99 /* HPA HVERSION (Dino)-Dependent Register Set */ 100 uint32_t gmask; /* 0x800 GSC arbitration mask */ 101 uint32_t pamr; /* 0x804 PCI arbitration mask */ 102 uint32_t papr; /* 0x808 PCI arbitration priority */ 103 uint32_t damode; /* 0x80c PCI arbitration mode */ 104 uint32_t pcicmd; /* 0x810 PCI command register */ 105 uint32_t pcists; /* 0x814 PCI status register */ 106 uint32_t pad6; /* 0x818 */ 107 uint32_t mltim; /* 0x81c PCI master latency timer */ 108 uint32_t brdg_feat; /* 0x820 PCI bridge feature enable */ 109 uint32_t pciror; /* 0x824 PCI read optimization reg */ 110 uint32_t pciwor; /* 0x828 PCI write optimization reg */ 111 uint32_t pad7; /* 0x82c */ 112 uint32_t tltim; /* 0x830 PCI target latency reg */ 113 }; 114 115 struct dino_softc { 116 device_t sc_dv; 117 118 int sc_ver; 119 void *sc_ih; 120 struct hppa_interrupt_register sc_ir; 121 bus_space_tag_t sc_bt; 122 bus_space_handle_t sc_bh; 123 bus_dma_tag_t sc_dmat; 124 125 struct hppa_bus_dma_tag sc_dmatag; 126 struct hppa_bus_space_tag sc_memt; 127 128 volatile struct dino_regs *sc_regs; 129 130 struct hppa_pci_chipset_tag sc_pc; 131 struct hppa_bus_space_tag sc_iot; 132 133 struct extent *sc_ioex; 134 int sc_memrefcount[30]; 135 136 char sc_ioexname[20]; 137 }; 138 139 int dinomatch(device_t, struct cfdata *, void *); 140 void dinoattach(device_t, device_t, void *); 141 static device_t dino_callback(device_t, struct confargs *); 142 143 CFATTACH_DECL_NEW(dino, sizeof(struct dino_softc), dinomatch, dinoattach, NULL, 144 NULL); 145 146 void dino_attach_hook(device_t, device_t, 147 struct pcibus_attach_args *); 148 void dino_enable_bus(struct dino_softc *, int); 149 int dino_maxdevs(void *, int); 150 pcitag_t dino_make_tag(void *, int, int, int); 151 void dino_decompose_tag(void *, pcitag_t, int *, int *, int *); 152 pcireg_t dino_conf_read(void *, pcitag_t, int); 153 void dino_conf_write(void *, pcitag_t, int, pcireg_t); 154 155 int dino_intr_map(const struct pci_attach_args *, pci_intr_handle_t *); 156 const char *dino_intr_string(void *, pci_intr_handle_t, char *, size_t); 157 void *dino_intr_establish(void *, pci_intr_handle_t, int, 158 int (*)(void *), void *); 159 void dino_intr_disestablish(void *, void *); 160 161 void *dino_alloc_parent(device_t, struct pci_attach_args *, int); 162 163 int dino_iomap(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *); 164 int dino_memmap(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *); 165 int dino_subregion(void *, bus_space_handle_t, bus_size_t, bus_size_t, 166 bus_space_handle_t *); 167 int dino_ioalloc(void *, bus_addr_t, bus_addr_t, bus_size_t, 168 bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *); 169 int dino_memalloc(void *, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t, 170 bus_size_t, int, bus_addr_t *, bus_space_handle_t *); 171 void dino_unmap(void *, bus_space_handle_t, bus_size_t); 172 void dino_free(void *, bus_space_handle_t, bus_size_t); 173 void dino_barrier(void *, bus_space_handle_t, bus_size_t, bus_size_t, int); 174 void *dino_vaddr(void *, bus_space_handle_t); 175 paddr_t dino_mmap(void *, bus_addr_t, off_t, int, int); 176 177 uint8_t dino_r1(void *, bus_space_handle_t, bus_size_t); 178 uint16_t dino_r2(void *, bus_space_handle_t, bus_size_t); 179 uint32_t dino_r4(void *, bus_space_handle_t, bus_size_t); 180 uint64_t dino_r8(void *, bus_space_handle_t, bus_size_t); 181 void dino_w1(void *, bus_space_handle_t, bus_size_t, uint8_t); 182 void dino_w2(void *, bus_space_handle_t, bus_size_t, uint16_t); 183 void dino_w4(void *, bus_space_handle_t, bus_size_t, uint32_t); 184 void dino_w8(void *, bus_space_handle_t, bus_size_t, uint64_t); 185 void dino_rm_1(void *, bus_space_handle_t, bus_size_t, uint8_t *, bus_size_t); 186 void dino_rm_2(void *, bus_space_handle_t, bus_size_t, uint16_t *, bus_size_t); 187 void dino_rm_4(void *, bus_space_handle_t, bus_size_t, uint32_t *, bus_size_t); 188 void dino_rm_8(void *, bus_space_handle_t, bus_size_t, uint64_t *, bus_size_t); 189 void dino_wm_1(void *, bus_space_handle_t, bus_size_t, const uint8_t *, 190 bus_size_t); 191 void dino_wm_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *, 192 bus_size_t); 193 void dino_wm_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *, 194 bus_size_t); 195 void dino_wm_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *, 196 bus_size_t); 197 void dino_sm_1(void *, bus_space_handle_t, bus_size_t, uint8_t, bus_size_t); 198 void dino_sm_2(void *, bus_space_handle_t, bus_size_t, uint16_t, bus_size_t); 199 void dino_sm_4(void *, bus_space_handle_t, bus_size_t, uint32_t, bus_size_t); 200 void dino_sm_8(void *, bus_space_handle_t, bus_size_t, uint64_t, bus_size_t); 201 void dino_rrm_2(void *, bus_space_handle_t, bus_size_t, uint16_t *, 202 bus_size_t); 203 void dino_rrm_4(void *, bus_space_handle_t, bus_size_t, uint32_t *, 204 bus_size_t); 205 void dino_rrm_8(void *, bus_space_handle_t, bus_size_t, uint64_t *, 206 bus_size_t); 207 void dino_wrm_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *, 208 bus_size_t); 209 void dino_wrm_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *, 210 bus_size_t); 211 void dino_wrm_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *, 212 bus_size_t); 213 void dino_rr_1(void *, bus_space_handle_t, bus_size_t, uint8_t *, bus_size_t); 214 void dino_rr_2(void *, bus_space_handle_t, bus_size_t, uint16_t *, bus_size_t); 215 void dino_rr_4(void *, bus_space_handle_t, bus_size_t, uint32_t *, bus_size_t); 216 void dino_rr_8(void *, bus_space_handle_t, bus_size_t, uint64_t *, bus_size_t); 217 void dino_wr_1(void *, bus_space_handle_t, bus_size_t, const uint8_t *, 218 bus_size_t); 219 void dino_wr_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *, 220 bus_size_t); 221 void dino_wr_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *, 222 bus_size_t); 223 void dino_wr_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *, 224 bus_size_t); 225 void dino_rrr_2(void *, bus_space_handle_t, bus_size_t, uint16_t *, 226 bus_size_t); 227 void dino_rrr_4(void *, bus_space_handle_t, bus_size_t, uint32_t *, 228 bus_size_t); 229 void dino_rrr_8(void *, bus_space_handle_t, bus_size_t, uint64_t *, 230 bus_size_t); 231 void dino_wrr_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *, 232 bus_size_t); 233 void dino_wrr_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *, 234 bus_size_t); 235 void dino_wrr_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *, 236 bus_size_t); 237 void dino_sr_1(void *, bus_space_handle_t, bus_size_t, uint8_t, bus_size_t); 238 void dino_sr_2(void *, bus_space_handle_t, bus_size_t, uint16_t, bus_size_t); 239 void dino_sr_4(void *, bus_space_handle_t, bus_size_t, uint32_t, bus_size_t); 240 void dino_sr_8(void *, bus_space_handle_t, bus_size_t, uint64_t, bus_size_t); 241 void dino_cp_1(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t, 242 bus_size_t, bus_size_t); 243 void dino_cp_2(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t, 244 bus_size_t, bus_size_t); 245 void dino_cp_4(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t, 246 bus_size_t, bus_size_t); 247 void dino_cp_8(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t, 248 bus_size_t, bus_size_t); 249 int dino_dmamap_create(void *, bus_size_t, int, bus_size_t, bus_size_t, int, 250 bus_dmamap_t *); 251 void dino_dmamap_destroy(void *, bus_dmamap_t); 252 int dino_dmamap_load(void *, bus_dmamap_t, void *, bus_size_t, struct proc *, 253 int); 254 int dino_dmamap_load_mbuf(void *, bus_dmamap_t, struct mbuf *, int); 255 int dino_dmamap_load_uio(void *, bus_dmamap_t, struct uio *, int); 256 int dino_dmamap_load_raw(void *, bus_dmamap_t, bus_dma_segment_t *, int, 257 bus_size_t, int); 258 void dino_dmamap_unload(void *, bus_dmamap_t); 259 void dino_dmamap_sync(void *, bus_dmamap_t, bus_addr_t, bus_size_t, int); 260 int dino_dmamem_alloc(void *, bus_size_t, bus_size_t, bus_size_t, 261 bus_dma_segment_t *, int, int *, int); 262 void dino_dmamem_free(void *, bus_dma_segment_t *, int); 263 int dino_dmamem_map(void *, bus_dma_segment_t *, int, size_t, void **, int); 264 void dino_dmamem_unmap(void *, void *, size_t); 265 paddr_t dino_dmamem_mmap(void *, bus_dma_segment_t *, int, off_t, int, int); 266 267 268 void 269 dino_attach_hook(device_t parent, device_t self, 270 struct pcibus_attach_args *pba) 271 { 272 struct dino_softc *sc = pba->pba_pc->_cookie; 273 274 /* 275 * The firmware enables only devices that are needed for booting. 276 * So other devices will fail to map PCI MEM / IO when they attach. 277 * Therefore we recursively walk all buses to simply enable everything. 278 */ 279 dino_enable_bus(sc, 0); 280 } 281 282 void 283 dino_enable_bus(struct dino_softc *sc, int bus) 284 { 285 int func; 286 int dev; 287 pcitag_t tag; 288 pcireg_t data; 289 pcireg_t class; 290 291 for (dev = 0; dev < 32; dev++) { 292 tag = dino_make_tag(sc, bus, dev, 0); 293 if (tag != -1 && dino_conf_read(sc, tag, 0) != 0xffffffff) { 294 for (func = 0; func < 8; func++) { 295 tag = dino_make_tag(sc, bus, dev, func); 296 if (dino_conf_read(sc, tag, 0) != 0xffffffff) { 297 data = dino_conf_read(sc, tag, 298 PCI_COMMAND_STATUS_REG); 299 dino_conf_write(sc, tag, 300 PCI_COMMAND_STATUS_REG, 301 PCI_COMMAND_IO_ENABLE | 302 PCI_COMMAND_MEM_ENABLE | 303 PCI_COMMAND_MASTER_ENABLE | data); 304 } 305 } 306 class = dino_conf_read(sc, tag, PCI_CLASS_REG); 307 if (PCI_CLASS(class) == PCI_CLASS_BRIDGE && 308 PCI_SUBCLASS(class) == PCI_SUBCLASS_BRIDGE_PCI) 309 dino_enable_bus(sc, bus + 1); 310 } 311 } 312 } 313 314 int 315 dino_maxdevs(void *v, int bus) 316 { 317 return 32; 318 } 319 320 pcitag_t 321 dino_make_tag(void *v, int bus, int dev, int func) 322 { 323 if (bus > 255 || dev > 31 || func > 7) 324 panic("dino_make_tag: bad request"); 325 326 return (bus << 16) | (dev << 11) | (func << 8); 327 } 328 329 void 330 dino_decompose_tag(void *v, pcitag_t tag, int *bus, int *dev, int *func) 331 { 332 *bus = (tag >> 16) & 0xff; 333 *dev = (tag >> 11) & 0x1f; 334 *func= (tag >> 8) & 0x07; 335 } 336 337 pcireg_t 338 dino_conf_read(void *v, pcitag_t tag, int reg) 339 { 340 struct dino_softc *sc = v; 341 volatile struct dino_regs *r = sc->sc_regs; 342 pcireg_t data; 343 uint32_t pamr; 344 345 if ((unsigned int)reg >= PCI_CONF_SIZE) 346 return (pcireg_t) -1; 347 348 /* 349 * XXX 350 * accessing dev 1f / func 7 on the 2nd Dino causes a machine check 351 * exception on my C200 352 */ 353 if ((tag & 0xff00) == 0xff00) 354 return -1; 355 356 /* fix arbitration errata by disabling all pci devs on config read */ 357 pamr = r->pamr; 358 r->pamr = 0; 359 360 r->pci_addr = tag | reg; 361 data = r->pci_conf_data; 362 363 /* restore arbitration */ 364 r->pamr = pamr; 365 366 return le32toh(data); 367 } 368 369 void 370 dino_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 371 { 372 struct dino_softc *sc = v; 373 volatile struct dino_regs *r = sc->sc_regs; 374 uint32_t pamr; 375 376 if ((unsigned int)reg >= PCI_CONF_SIZE) 377 return; 378 379 /* 380 * XXX 381 * accessing dev 1f / func 7 on the 2nd Dino causes a machine check 382 * exception on my C200 383 */ 384 if ((tag & 0xff00) == 0xff00) return; 385 386 /* fix arbitration errata by disabling all pci devs on config read */ 387 pamr = r->pamr; 388 r->pamr = 0; 389 390 r->pci_addr = tag | reg; 391 r->pci_conf_data = htole32(data); 392 393 /* fix coalescing config and io writes by interleaving w/ a read */ 394 r->pci_addr = tag | PCI_ID_REG; 395 (void)r->pci_conf_data; 396 397 /* restore arbitration */ 398 r->pamr = pamr; 399 } 400 401 int 402 dino_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 403 { 404 int line = pa->pa_intrline; 405 406 if (line == 0xff) 407 return 1; 408 409 *ihp = line; 410 411 return 0; 412 } 413 414 const char * 415 dino_intr_string(void *v, pci_intr_handle_t ih, char *buf, size_t len) 416 { 417 snprintf(buf, len, "irq %ld", ih); 418 return buf; 419 } 420 421 extern int cold; 422 423 424 void * 425 dino_intr_establish(void *v, pci_intr_handle_t ih, 426 int pri, int (*handler)(void *), void *arg) 427 { 428 struct dino_softc *sc = v; 429 430 return hppa_intr_establish(pri, handler, arg, &sc->sc_ir, ih); 431 } 432 433 void 434 dino_intr_disestablish(void *v, void *cookie) 435 { 436 /* XXX Implement me */ 437 } 438 439 440 #if NCARDBUS > 0 441 void * 442 dino_alloc_parent(device_t self, struct pci_attach_args *pa, int io) 443 { 444 struct dino_softc *sc = pa->pa_pc->_cookie; 445 struct extent *ex; 446 bus_space_tag_t tag; 447 bus_addr_t start; 448 bus_size_t size; 449 450 if (io) { 451 ex = sc->sc_ioex; 452 tag = pa->pa_iot; 453 start = 0xa000; 454 size = 0x1000; 455 } else { 456 ex = hppa_io_extent; 457 tag = pa->pa_memt; 458 start = ex->ex_start; /* XXX or 0xf0800000? */ 459 size = DINO_MEM_CHUNK; 460 } 461 462 if (extent_alloc_subregion(ex, start, ex->ex_end, size, size, 463 EX_NOBOUNDARY, EX_NOWAIT, &start)) 464 return NULL; 465 extent_free(ex, start, size, EX_NOWAIT); 466 return rbus_new_root_share(tag, ex, start, size, start); 467 } 468 #endif 469 470 int 471 dino_iomap(void *v, bus_addr_t bpa, bus_size_t size, 472 int flags, bus_space_handle_t *bshp) 473 { 474 struct dino_softc *sc = v; 475 int error; 476 477 if (!(flags & BUS_SPACE_MAP_NOEXTENT) && 478 (error = extent_alloc_region(sc->sc_ioex, bpa, size, EX_NOWAIT))) 479 return error; 480 481 if (bshp) 482 *bshp = bpa; 483 484 return 0; 485 } 486 487 int 488 dino_memmap(void *v, bus_addr_t bpa, bus_size_t size, 489 int flags, bus_space_handle_t *bshp) 490 { 491 struct dino_softc *sc = v; 492 volatile struct dino_regs *r = sc->sc_regs; 493 uint32_t reg; 494 int error; 495 496 reg = r->io_addr_en; 497 reg |= 1 << ((bpa >> 23) & 0x1f); 498 #ifdef DEBUG 499 if (reg & 0x80000001) 500 panic("mapping outside the mem extent range"); 501 #endif 502 if ((error = bus_space_map(sc->sc_bt, bpa, size, flags, bshp))) 503 return error; 504 ++sc->sc_memrefcount[((bpa >> 23) & 0x1f)]; 505 /* map into the upper bus space, if not yet mapped this 8M */ 506 if (reg != r->io_addr_en) 507 r->io_addr_en = reg; 508 return 0; 509 } 510 511 int 512 dino_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset, 513 bus_size_t size, bus_space_handle_t *nbshp) 514 { 515 *nbshp = bsh + offset; 516 return 0; 517 } 518 519 int 520 dino_ioalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size, 521 bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp, 522 bus_space_handle_t *bshp) 523 { 524 struct dino_softc *sc = v; 525 struct extent *ex = sc->sc_ioex; 526 bus_addr_t bpa; 527 int error; 528 529 if (rstart < ex->ex_start || rend > ex->ex_end) 530 panic("dino_ioalloc: bad region start/end"); 531 532 if ((error = extent_alloc_subregion(ex, rstart, rend, size, 533 align, boundary, EX_NOWAIT, &bpa))) 534 return error; 535 536 if (addrp) 537 *addrp = bpa; 538 if (bshp) 539 *bshp = bpa; 540 541 return 0; 542 } 543 544 int 545 dino_memalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size, 546 bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp, 547 bus_space_handle_t *bshp) 548 { 549 struct dino_softc *sc = v; 550 volatile struct dino_regs *r = sc->sc_regs; 551 uint32_t reg; 552 int i, error; 553 554 /* 555 * Allow allocation only when PCI MEM is already mapped. 556 * Needed to avoid allocation of I/O space used by devices that 557 * have no driver in the current kernel. 558 * Dino can map PCI MEM in the range 0xf0800000..0xff800000 only. 559 */ 560 reg = r->io_addr_en; 561 if (rstart < 0xf0800000 || rend >= 0xff800000 || reg == 0) 562 return -1; 563 /* Find used PCI MEM and narrow allocateble region down to it. */ 564 for (i = 1; i < 31; i++) 565 if ((reg & 1 << i) != 0) { 566 rstart = HPPA_IOSPACE | i << 23; 567 rend = (HPPA_IOSPACE | (i + 1) << 23) - 1; 568 break; 569 } 570 if ((error = bus_space_alloc(sc->sc_bt, rstart, rend, size, align, 571 boundary, flags, addrp, bshp))) 572 return error; 573 ++sc->sc_memrefcount[((*bshp >> 23) & 0x1f)]; 574 return 0; 575 } 576 577 void 578 dino_unmap(void *v, bus_space_handle_t bsh, bus_size_t size) 579 { 580 struct dino_softc *sc = v; 581 volatile struct dino_regs *r = sc->sc_regs; 582 583 if (bsh & HPPA_IOSPACE) { 584 bus_space_unmap(sc->sc_bt, bsh, size); 585 if (--sc->sc_memrefcount[((bsh >> 23) & 0x1f)] == 0) 586 /* Unmap the upper PCI MEM space. */ 587 r->io_addr_en &= ~(1 << ((bsh >> 23) & 0x1f)); 588 } else { 589 /* XXX gotta follow the BUS_SPACE_MAP_NOEXTENT flag */ 590 if (extent_free(sc->sc_ioex, bsh, size, EX_NOWAIT)) 591 printf("dino_unmap: ps 0x%lx, size 0x%lx\n" 592 "dino_unmap: can't free region\n", bsh, size); 593 } 594 } 595 596 void 597 dino_free(void *v, bus_space_handle_t bh, bus_size_t size) 598 { 599 /* should be enough */ 600 dino_unmap(v, bh, size); 601 } 602 603 void 604 dino_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op) 605 { 606 sync_caches(); 607 } 608 609 void* 610 dino_vaddr(void *v, bus_space_handle_t h) 611 { 612 struct dino_softc *sc = v; 613 614 return bus_space_vaddr(sc->sc_bt, h); 615 } 616 617 paddr_t 618 dino_mmap(void *v, bus_addr_t addr, off_t off, int prot, int flags) 619 { 620 return btop(addr + off); 621 } 622 623 uint8_t 624 dino_r1(void *v, bus_space_handle_t h, bus_size_t o) 625 { 626 h += o; 627 if (h & HPPA_IOSPACE) 628 return *(volatile uint8_t *)h; 629 else { 630 struct dino_softc *sc = v; 631 volatile struct dino_regs *r = sc->sc_regs; 632 633 r->pci_addr = h; 634 return *((volatile uint8_t *)&r->pci_io_data + (h & 3)); 635 } 636 } 637 638 uint16_t 639 dino_r2(void *v, bus_space_handle_t h, bus_size_t o) 640 { 641 volatile uint16_t *p; 642 643 h += o; 644 if (h & HPPA_IOSPACE) 645 p = (volatile uint16_t *)h; 646 else { 647 struct dino_softc *sc = v; 648 volatile struct dino_regs *r = sc->sc_regs; 649 650 r->pci_addr = h; 651 p = (volatile uint16_t *)&r->pci_io_data; 652 if (h & 2) 653 p++; 654 } 655 return le16toh(*p); 656 } 657 658 uint32_t 659 dino_r4(void *v, bus_space_handle_t h, bus_size_t o) 660 { 661 uint32_t data; 662 663 h += o; 664 if (h & HPPA_IOSPACE) 665 data = *(volatile uint32_t *)h; 666 else { 667 struct dino_softc *sc = v; 668 volatile struct dino_regs *r = sc->sc_regs; 669 670 r->pci_addr = h; 671 data = r->pci_io_data; 672 } 673 674 return le32toh(data); 675 } 676 677 uint64_t 678 dino_r8(void *v, bus_space_handle_t h, bus_size_t o) 679 { 680 uint64_t data; 681 682 h += o; 683 if (h & HPPA_IOSPACE) 684 data = *(volatile uint64_t *)h; 685 else 686 panic("dino_r8: not implemented"); 687 688 return le64toh(data); 689 } 690 691 void 692 dino_w1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t vv) 693 { 694 h += o; 695 if (h & HPPA_IOSPACE) 696 *(volatile uint8_t *)h = vv; 697 else { 698 struct dino_softc *sc = v; 699 volatile struct dino_regs *r = sc->sc_regs; 700 701 r->pci_addr = h; 702 *((volatile uint8_t *)&r->pci_io_data + (h & 3)) = vv; 703 } 704 } 705 706 void 707 dino_w2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t vv) 708 { 709 volatile uint16_t *p; 710 711 h += o; 712 if (h & HPPA_IOSPACE) 713 p = (volatile uint16_t *)h; 714 else { 715 struct dino_softc *sc = v; 716 volatile struct dino_regs *r = sc->sc_regs; 717 718 r->pci_addr = h; 719 p = (volatile uint16_t *)&r->pci_io_data; 720 if (h & 2) 721 p++; 722 } 723 724 *p = htole16(vv); 725 } 726 727 void 728 dino_w4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t vv) 729 { 730 h += o; 731 vv = htole32(vv); 732 if (h & HPPA_IOSPACE) 733 *(volatile uint32_t *)h = vv; 734 else { 735 struct dino_softc *sc = v; 736 volatile struct dino_regs *r = sc->sc_regs; 737 738 r->pci_addr = h; 739 r->pci_io_data = vv; 740 } 741 } 742 743 void 744 dino_w8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t vv) 745 { 746 h += o; 747 if (h & HPPA_IOSPACE) 748 *(volatile uint64_t *)h = htole64(vv); 749 else 750 panic("dino_w8: not implemented"); 751 } 752 753 754 void 755 dino_rm_1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t *a, bus_size_t c) 756 { 757 volatile uint8_t *p; 758 759 h += o; 760 if (h & HPPA_IOSPACE) 761 p = (volatile uint8_t *)h; 762 else { 763 struct dino_softc *sc = v; 764 volatile struct dino_regs *r = sc->sc_regs; 765 766 r->pci_addr = h; 767 p = (volatile uint8_t *)&r->pci_io_data + (h & 3); 768 } 769 770 while (c--) 771 *a++ = *p; 772 } 773 774 void 775 dino_rm_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t *a, bus_size_t c) 776 { 777 volatile uint16_t *p; 778 779 h += o; 780 if (h & HPPA_IOSPACE) 781 p = (volatile uint16_t *)h; 782 else { 783 struct dino_softc *sc = v; 784 volatile struct dino_regs *r = sc->sc_regs; 785 786 r->pci_addr = h; 787 p = (volatile uint16_t *)&r->pci_io_data; 788 if (h & 2) 789 p++; 790 } 791 792 while (c--) 793 *a++ = le16toh(*p); 794 } 795 796 void 797 dino_rm_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t *a, bus_size_t c) 798 { 799 volatile uint32_t *p; 800 801 h += o; 802 if (h & HPPA_IOSPACE) 803 p = (volatile uint32_t *)h; 804 else { 805 struct dino_softc *sc = v; 806 volatile struct dino_regs *r = sc->sc_regs; 807 808 r->pci_addr = h; 809 p = (volatile uint32_t *)&r->pci_io_data; 810 } 811 812 while (c--) 813 *a++ = le32toh(*p); 814 } 815 816 void 817 dino_rm_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t *a, bus_size_t c) 818 { 819 panic("dino_rm_8: not implemented"); 820 } 821 822 void 823 dino_wm_1(void *v, bus_space_handle_t h, bus_size_t o, const uint8_t *a, bus_size_t c) 824 { 825 volatile uint8_t *p; 826 827 h += o; 828 if (h & HPPA_IOSPACE) 829 p = (volatile uint8_t *)h; 830 else { 831 struct dino_softc *sc = v; 832 volatile struct dino_regs *r = sc->sc_regs; 833 834 r->pci_addr = h; 835 p = (volatile uint8_t *)&r->pci_io_data + (h & 3); 836 } 837 838 while (c--) 839 *p = *a++; 840 } 841 842 void 843 dino_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const uint16_t *a, bus_size_t c) 844 { 845 volatile uint16_t *p; 846 847 h += o; 848 if (h & HPPA_IOSPACE) 849 p = (volatile uint16_t *)h; 850 else { 851 struct dino_softc *sc = v; 852 volatile struct dino_regs *r = sc->sc_regs; 853 854 r->pci_addr = h; 855 p = (volatile uint16_t *)&r->pci_io_data; 856 if (h & 2) 857 p++; 858 } 859 860 while (c--) 861 *p = htole16(*a++); 862 } 863 864 void 865 dino_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const uint32_t *a, bus_size_t c) 866 { 867 volatile uint32_t *p; 868 869 h += o; 870 if (h & HPPA_IOSPACE) 871 p = (volatile uint32_t *)h; 872 else { 873 struct dino_softc *sc = v; 874 volatile struct dino_regs *r = sc->sc_regs; 875 876 r->pci_addr = h; 877 p = (volatile uint32_t *)&r->pci_io_data; 878 } 879 880 while (c--) 881 *p = htole32(*a++); 882 } 883 884 void 885 dino_wm_8(void *v, bus_space_handle_t h, bus_size_t o, const uint64_t *a, bus_size_t c) 886 { 887 panic("dino_wm_8: not implemented"); 888 } 889 890 void 891 dino_sm_1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t vv, bus_size_t c) 892 { 893 volatile uint8_t *p; 894 895 h += o; 896 if (h & HPPA_IOSPACE) 897 p = (volatile uint8_t *)h; 898 else { 899 struct dino_softc *sc = v; 900 volatile struct dino_regs *r = sc->sc_regs; 901 902 r->pci_addr = h; 903 p = (volatile uint8_t *)&r->pci_io_data + (h & 3); 904 } 905 906 while (c--) 907 *p = vv; 908 } 909 910 void 911 dino_sm_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t vv, bus_size_t c) 912 { 913 volatile uint16_t *p; 914 915 h += o; 916 if (h & HPPA_IOSPACE) 917 p = (volatile uint16_t *)h; 918 else { 919 struct dino_softc *sc = v; 920 volatile struct dino_regs *r = sc->sc_regs; 921 922 r->pci_addr = h; 923 p = (volatile uint16_t *)&r->pci_io_data; 924 if (h & 2) 925 p++; 926 } 927 928 while (c--) 929 *p = htole16(vv); 930 } 931 932 void 933 dino_sm_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t vv, bus_size_t c) 934 { 935 volatile uint32_t *p; 936 937 h += o; 938 if (h & HPPA_IOSPACE) 939 p = (volatile uint32_t *)h; 940 else { 941 struct dino_softc *sc = v; 942 volatile struct dino_regs *r = sc->sc_regs; 943 944 r->pci_addr = h; 945 p = (volatile uint32_t *)&r->pci_io_data; 946 } 947 948 while (c--) 949 *p = htole32(vv); 950 } 951 952 void 953 dino_sm_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t vv, bus_size_t c) 954 { 955 panic("dino_sm_8: not implemented"); 956 } 957 958 void 959 dino_rrm_2(void *v, bus_space_handle_t h, bus_size_t o, 960 uint16_t *a, bus_size_t c) 961 { 962 volatile uint16_t *p; 963 964 h += o; 965 if (h & HPPA_IOSPACE) 966 p = (volatile uint16_t *)h; 967 else { 968 struct dino_softc *sc = v; 969 volatile struct dino_regs *r = sc->sc_regs; 970 971 r->pci_addr = h; 972 p = (volatile uint16_t *)&r->pci_io_data; 973 if (h & 2) 974 p++; 975 } 976 977 while (c--) 978 *a++ = *p; 979 } 980 981 void 982 dino_rrm_4(void *v, bus_space_handle_t h, bus_size_t o, 983 uint32_t *a, bus_size_t c) 984 { 985 volatile uint32_t *p; 986 987 h += o; 988 if (h & HPPA_IOSPACE) 989 p = (volatile uint32_t *)h; 990 else { 991 struct dino_softc *sc = v; 992 volatile struct dino_regs *r = sc->sc_regs; 993 994 r->pci_addr = h; 995 p = (volatile uint32_t *)&r->pci_io_data; 996 } 997 998 while (c--) 999 *a++ = *p; 1000 } 1001 1002 void 1003 dino_rrm_8(void *v, bus_space_handle_t h, bus_size_t o, 1004 uint64_t *a, bus_size_t c) 1005 { 1006 panic("dino_rrm_8: not implemented"); 1007 } 1008 1009 void 1010 dino_wrm_2(void *v, bus_space_handle_t h, bus_size_t o, 1011 const uint16_t *a, bus_size_t c) 1012 { 1013 volatile uint16_t *p; 1014 1015 h += o; 1016 if (h & HPPA_IOSPACE) 1017 p = (volatile uint16_t *)h; 1018 else { 1019 struct dino_softc *sc = v; 1020 volatile struct dino_regs *r = sc->sc_regs; 1021 1022 r->pci_addr = h; 1023 p = (volatile uint16_t *)&r->pci_io_data; 1024 if (h & 2) 1025 p++; 1026 } 1027 1028 while (c--) 1029 *p = *a++; 1030 } 1031 1032 void 1033 dino_wrm_4(void *v, bus_space_handle_t h, bus_size_t o, 1034 const uint32_t *a, bus_size_t c) 1035 { 1036 volatile uint32_t *p; 1037 1038 h += o; 1039 if (h & HPPA_IOSPACE) 1040 p = (volatile uint32_t *)h; 1041 else { 1042 struct dino_softc *sc = v; 1043 volatile struct dino_regs *r = sc->sc_regs; 1044 1045 r->pci_addr = h; 1046 p = (volatile uint32_t *)&r->pci_io_data; 1047 } 1048 1049 while (c--) 1050 *p = *a++; 1051 } 1052 1053 void 1054 dino_wrm_8(void *v, bus_space_handle_t h, bus_size_t o, 1055 const uint64_t *a, bus_size_t c) 1056 { 1057 panic("dino_wrm_8: not implemented"); 1058 } 1059 1060 void 1061 dino_rr_1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t *a, bus_size_t c) 1062 { 1063 volatile uint8_t *p; 1064 1065 h += o; 1066 if (h & HPPA_IOSPACE) { 1067 p = (volatile uint8_t *)h; 1068 while (c--) 1069 *a++ = *p++; 1070 } else { 1071 struct dino_softc *sc = v; 1072 volatile struct dino_regs *r = sc->sc_regs; 1073 1074 for (; c--; h++) { 1075 r->pci_addr = h; 1076 p = (volatile uint8_t *)&r->pci_io_data + (h & 3); 1077 *a++ = *p; 1078 } 1079 } 1080 } 1081 1082 void 1083 dino_rr_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t *a, bus_size_t c) 1084 { 1085 volatile uint16_t *p, data; 1086 1087 h += o; 1088 if (h & HPPA_IOSPACE) { 1089 p = (volatile uint16_t *)h; 1090 while (c--) { 1091 data = *p++; 1092 *a++ = le16toh(data); 1093 } 1094 } else { 1095 struct dino_softc *sc = v; 1096 volatile struct dino_regs *r = sc->sc_regs; 1097 1098 for (; c--; h += 2) { 1099 r->pci_addr = h; 1100 p = (volatile uint16_t *)&r->pci_io_data; 1101 if (h & 2) 1102 p++; 1103 data = *p; 1104 *a++ = le16toh(data); 1105 } 1106 } 1107 } 1108 1109 void 1110 dino_rr_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t *a, bus_size_t c) 1111 { 1112 volatile uint32_t *p, data; 1113 1114 h += o; 1115 if (h & HPPA_IOSPACE) { 1116 p = (volatile uint32_t *)h; 1117 while (c--) { 1118 data = *p++; 1119 *a++ = le32toh(data); 1120 } 1121 } else { 1122 struct dino_softc *sc = v; 1123 volatile struct dino_regs *r = sc->sc_regs; 1124 1125 for (; c--; h += 4) { 1126 r->pci_addr = h; 1127 data = r->pci_io_data; 1128 *a++ = le32toh(data); 1129 } 1130 } 1131 } 1132 1133 void 1134 dino_rr_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t *a, bus_size_t c) 1135 { 1136 panic("dino_rr_8: not implemented"); 1137 } 1138 1139 void 1140 dino_wr_1(void *v, bus_space_handle_t h, bus_size_t o, const uint8_t *a, bus_size_t c) 1141 { 1142 volatile uint8_t *p; 1143 1144 h += o; 1145 if (h & HPPA_IOSPACE) { 1146 p = (volatile uint8_t *)h; 1147 while (c--) 1148 *p++ = *a++; 1149 } else { 1150 struct dino_softc *sc = v; 1151 volatile struct dino_regs *r = sc->sc_regs; 1152 1153 for (; c--; h++) { 1154 r->pci_addr = h; 1155 p = (volatile uint8_t *)&r->pci_io_data + (h & 3); 1156 *p = *a++; 1157 } 1158 } 1159 } 1160 1161 void 1162 dino_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const uint16_t *a, bus_size_t c) 1163 { 1164 volatile uint16_t *p, data; 1165 1166 h += o; 1167 if (h & HPPA_IOSPACE) { 1168 p = (volatile uint16_t *)h; 1169 while (c--) { 1170 data = *a++; 1171 *p++ = htole16(data); 1172 } 1173 } else { 1174 struct dino_softc *sc = v; 1175 volatile struct dino_regs *r = sc->sc_regs; 1176 1177 for (; c--; h += 2) { 1178 r->pci_addr = h; 1179 p = (volatile uint16_t *)&r->pci_io_data; 1180 if (h & 2) 1181 p++; 1182 data = *a++; 1183 *p = htole16(data); 1184 } 1185 } 1186 } 1187 1188 void 1189 dino_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const uint32_t *a, bus_size_t c) 1190 { 1191 volatile uint32_t *p, data; 1192 1193 h += o; 1194 if (h & HPPA_IOSPACE) { 1195 p = (volatile uint32_t *)h; 1196 while (c--) { 1197 data = *a++; 1198 *p++ = htole32(data); 1199 } 1200 } else { 1201 struct dino_softc *sc = v; 1202 volatile struct dino_regs *r = sc->sc_regs; 1203 1204 for (; c--; h += 4) { 1205 r->pci_addr = h; 1206 data = *a++; 1207 r->pci_io_data = htole32(data); 1208 } 1209 } 1210 } 1211 1212 void 1213 dino_wr_8(void *v, bus_space_handle_t h, bus_size_t o, const uint64_t *a, bus_size_t c) 1214 { 1215 panic("dino_wr_8: not implemented"); 1216 } 1217 1218 void 1219 dino_rrr_2(void *v, bus_space_handle_t h, bus_size_t o, 1220 uint16_t *a, bus_size_t c) 1221 { 1222 volatile uint16_t *p; 1223 1224 h += o; 1225 if (h & HPPA_IOSPACE) { 1226 p = (volatile uint16_t *)h; 1227 while (c--) 1228 *a++ = *p++; 1229 } else { 1230 struct dino_softc *sc = v; 1231 volatile struct dino_regs *r = sc->sc_regs; 1232 1233 for (; c--; h += 2) { 1234 r->pci_addr = h; 1235 p = (volatile uint16_t *)&r->pci_io_data; 1236 if (h & 2) 1237 p++; 1238 *a++ = *p; 1239 } 1240 } 1241 } 1242 1243 void 1244 dino_rrr_4(void *v, bus_space_handle_t h, bus_size_t o, 1245 uint32_t *a, bus_size_t c) 1246 { 1247 volatile uint32_t *p; 1248 1249 h += o; 1250 if (h & HPPA_IOSPACE) { 1251 p = (volatile uint32_t *)h; 1252 while (c--) 1253 *a++ = *p++; 1254 } else { 1255 struct dino_softc *sc = v; 1256 volatile struct dino_regs *r = sc->sc_regs; 1257 1258 for (; c--; h += 4) { 1259 r->pci_addr = h; 1260 *a++ = r->pci_io_data; 1261 } 1262 } 1263 } 1264 1265 void 1266 dino_rrr_8(void *v, bus_space_handle_t h, bus_size_t o, 1267 uint64_t *a, bus_size_t c) 1268 { 1269 panic("dino_rrr_8: not implemented"); 1270 } 1271 1272 void 1273 dino_wrr_2(void *v, bus_space_handle_t h, bus_size_t o, 1274 const uint16_t *a, bus_size_t c) 1275 { 1276 volatile uint16_t *p; 1277 1278 h += o; 1279 if (h & HPPA_IOSPACE) { 1280 p = (volatile uint16_t *)h; 1281 while (c--) 1282 *p++ = *a++; 1283 } else { 1284 struct dino_softc *sc = v; 1285 volatile struct dino_regs *r = sc->sc_regs; 1286 1287 for (; c--; h += 2) { 1288 r->pci_addr = h; 1289 p = (volatile uint16_t *)&r->pci_io_data; 1290 if (h & 2) 1291 p++; 1292 *p = *a++; 1293 } 1294 } 1295 } 1296 1297 void 1298 dino_wrr_4(void *v, bus_space_handle_t h, bus_size_t o, 1299 const uint32_t *a, bus_size_t c) 1300 { 1301 volatile uint32_t *p; 1302 1303 c /= 4; 1304 h += o; 1305 if (h & HPPA_IOSPACE) { 1306 p = (volatile uint32_t *)h; 1307 while (c--) 1308 *p++ = *a++; 1309 } else { 1310 struct dino_softc *sc = v; 1311 volatile struct dino_regs *r = sc->sc_regs; 1312 1313 for (; c--; h += 4) { 1314 r->pci_addr = h; 1315 r->pci_io_data = *a++; 1316 } 1317 } 1318 } 1319 1320 void 1321 dino_wrr_8(void *v, bus_space_handle_t h, bus_size_t o, 1322 const uint64_t *a, bus_size_t c) 1323 { 1324 panic("dino_wrr_8: not implemented"); 1325 } 1326 1327 void 1328 dino_sr_1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t vv, bus_size_t c) 1329 { 1330 volatile uint8_t *p; 1331 1332 h += o; 1333 if (h & HPPA_IOSPACE) { 1334 p = (volatile uint8_t *)h; 1335 while (c--) 1336 *p++ = vv; 1337 } else { 1338 struct dino_softc *sc = v; 1339 volatile struct dino_regs *r = sc->sc_regs; 1340 1341 for (; c--; h++) { 1342 r->pci_addr = h; 1343 p = (volatile uint8_t *)&r->pci_io_data + (h & 3); 1344 *p = vv; 1345 } 1346 } 1347 } 1348 1349 void 1350 dino_sr_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t vv, bus_size_t c) 1351 { 1352 volatile uint16_t *p; 1353 1354 h += o; 1355 vv = htole16(vv); 1356 if (h & HPPA_IOSPACE) { 1357 p = (volatile uint16_t *)h; 1358 while (c--) 1359 *p++ = vv; 1360 } else { 1361 struct dino_softc *sc = v; 1362 volatile struct dino_regs *r = sc->sc_regs; 1363 1364 for (; c--; h += 2) { 1365 r->pci_addr = h; 1366 p = (volatile uint16_t *)&r->pci_io_data; 1367 if (h & 2) 1368 p++; 1369 *p = vv; 1370 } 1371 } 1372 } 1373 1374 void 1375 dino_sr_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t vv, bus_size_t c) 1376 { 1377 volatile uint32_t *p; 1378 1379 h += o; 1380 vv = htole32(vv); 1381 if (h & HPPA_IOSPACE) { 1382 p = (volatile uint32_t *)h; 1383 while (c--) 1384 *p++ = vv; 1385 } else { 1386 struct dino_softc *sc = v; 1387 volatile struct dino_regs *r = sc->sc_regs; 1388 1389 for (; c--; h += 4) { 1390 r->pci_addr = h; 1391 r->pci_io_data = vv; 1392 } 1393 } 1394 } 1395 1396 void 1397 dino_sr_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t vv, bus_size_t c) 1398 { 1399 panic("dino_sr_8: not implemented"); 1400 } 1401 1402 void 1403 dino_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1, 1404 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 1405 { 1406 while (c--) 1407 dino_w1(v, h1, o1++, dino_r1(v, h2, o2++)); 1408 } 1409 1410 void 1411 dino_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1, 1412 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 1413 { 1414 while (c--) { 1415 dino_w2(v, h1, o1, dino_r2(v, h2, o2)); 1416 o1 += 2; 1417 o2 += 2; 1418 } 1419 } 1420 1421 void 1422 dino_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1, 1423 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 1424 { 1425 while (c--) { 1426 dino_w4(v, h1, o1, dino_r4(v, h2, o2)); 1427 o1 += 4; 1428 o2 += 4; 1429 } 1430 } 1431 1432 void 1433 dino_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1, 1434 bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 1435 { 1436 while (c--) { 1437 dino_w8(v, h1, o1, dino_r8(v, h2, o2)); 1438 o1 += 8; 1439 o2 += 8; 1440 } 1441 } 1442 1443 1444 const struct hppa_bus_space_tag dino_iomemt = { 1445 NULL, 1446 1447 NULL, dino_unmap, dino_subregion, NULL, dino_free, 1448 dino_barrier, dino_vaddr, dino_mmap, 1449 dino_r1, dino_r2, dino_r4, dino_r8, 1450 dino_w1, dino_w2, dino_w4, dino_w8, 1451 dino_rm_1, dino_rm_2, dino_rm_4, dino_rm_8, 1452 dino_wm_1, dino_wm_2, dino_wm_4, dino_wm_8, 1453 dino_sm_1, dino_sm_2, dino_sm_4, dino_sm_8, 1454 dino_rrm_2, dino_rrm_4, dino_rrm_8, 1455 dino_wrm_2, dino_wrm_4, dino_wrm_8, 1456 dino_rr_1, dino_rr_2, dino_rr_4, dino_rr_8, 1457 dino_wr_1, dino_wr_2, dino_wr_4, dino_wr_8, 1458 dino_rrr_2, dino_rrr_4, dino_rrr_8, 1459 dino_wrr_2, dino_wrr_4, dino_wrr_8, 1460 dino_sr_1, dino_sr_2, dino_sr_4, dino_sr_8, 1461 dino_cp_1, dino_cp_2, dino_cp_4, dino_cp_8 1462 }; 1463 1464 int 1465 dino_dmamap_create(void *v, bus_size_t size, int nsegments, 1466 bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) 1467 { 1468 struct dino_softc *sc = v; 1469 1470 /* TODO check the addresses, boundary, enable dma */ 1471 1472 return bus_dmamap_create(sc->sc_dmat, size, nsegments, 1473 maxsegsz, boundary, flags, dmamp); 1474 } 1475 1476 void 1477 dino_dmamap_destroy(void *v, bus_dmamap_t map) 1478 { 1479 struct dino_softc *sc = v; 1480 1481 bus_dmamap_destroy(sc->sc_dmat, map); 1482 } 1483 1484 int 1485 dino_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size, 1486 struct proc *p, int flags) 1487 { 1488 struct dino_softc *sc = v; 1489 1490 return bus_dmamap_load(sc->sc_dmat, map, addr, size, p, flags); 1491 } 1492 1493 int 1494 dino_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m, int flags) 1495 { 1496 struct dino_softc *sc = v; 1497 1498 return bus_dmamap_load_mbuf(sc->sc_dmat, map, m, flags); 1499 } 1500 1501 int 1502 dino_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags) 1503 { 1504 struct dino_softc *sc = v; 1505 1506 return bus_dmamap_load_uio(sc->sc_dmat, map, uio, flags); 1507 } 1508 1509 int 1510 dino_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs, 1511 int nsegs, bus_size_t size, int flags) 1512 { 1513 struct dino_softc *sc = v; 1514 1515 return bus_dmamap_load_raw(sc->sc_dmat, map, segs, nsegs, size, flags); 1516 } 1517 1518 void 1519 dino_dmamap_unload(void *v, bus_dmamap_t map) 1520 { 1521 struct dino_softc *sc = v; 1522 1523 bus_dmamap_unload(sc->sc_dmat, map); 1524 } 1525 1526 void 1527 dino_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off, 1528 bus_size_t len, int ops) 1529 { 1530 struct dino_softc *sc = v; 1531 1532 return bus_dmamap_sync(sc->sc_dmat, map, off, len, ops); 1533 } 1534 1535 int 1536 dino_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment, 1537 bus_size_t boundary, bus_dma_segment_t *segs, 1538 int nsegs, int *rsegs, int flags) 1539 { 1540 struct dino_softc *sc = v; 1541 1542 return bus_dmamem_alloc(sc->sc_dmat, size, alignment, boundary, 1543 segs, nsegs, rsegs, flags); 1544 } 1545 1546 void 1547 dino_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs) 1548 { 1549 struct dino_softc *sc = v; 1550 1551 bus_dmamem_free(sc->sc_dmat, segs, nsegs); 1552 } 1553 1554 int 1555 dino_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size, 1556 void **kvap, int flags) 1557 { 1558 struct dino_softc *sc = v; 1559 1560 return bus_dmamem_map(sc->sc_dmat, segs, nsegs, size, kvap, flags); 1561 } 1562 1563 void 1564 dino_dmamem_unmap(void *v, void *kva, size_t size) 1565 { 1566 struct dino_softc *sc = v; 1567 1568 bus_dmamem_unmap(sc->sc_dmat, kva, size); 1569 } 1570 1571 paddr_t 1572 dino_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off, 1573 int prot, int flags) 1574 { 1575 struct dino_softc *sc = v; 1576 1577 return bus_dmamem_mmap(sc->sc_dmat, segs, nsegs, off, prot, flags); 1578 } 1579 1580 const struct hppa_bus_dma_tag dino_dmat = { 1581 NULL, 1582 dino_dmamap_create, dino_dmamap_destroy, 1583 dino_dmamap_load, dino_dmamap_load_mbuf, 1584 dino_dmamap_load_uio, dino_dmamap_load_raw, 1585 dino_dmamap_unload, dino_dmamap_sync, 1586 1587 dino_dmamem_alloc, dino_dmamem_free, dino_dmamem_map, 1588 dino_dmamem_unmap, dino_dmamem_mmap 1589 }; 1590 1591 const struct hppa_pci_chipset_tag dino_pc = { 1592 NULL, 1593 dino_attach_hook, dino_maxdevs, dino_make_tag, dino_decompose_tag, 1594 dino_conf_read, dino_conf_write, 1595 dino_intr_map, dino_intr_string, 1596 dino_intr_establish, dino_intr_disestablish, 1597 #if NCARDBUS > 0 1598 dino_alloc_parent 1599 #else 1600 NULL 1601 #endif 1602 }; 1603 1604 int 1605 dinomatch(device_t parent, cfdata_t cfdata, void *aux) 1606 { 1607 struct confargs *ca = aux; 1608 1609 /* there will be only one */ 1610 if (ca->ca_type.iodc_type != HPPA_TYPE_BRIDGE || 1611 ca->ca_type.iodc_sv_model != HPPA_BRIDGE_DINO) 1612 return 0; 1613 1614 /* do not match on the elroy family */ 1615 if (ca->ca_type.iodc_model == 0x78) 1616 return 0; 1617 1618 return 1; 1619 } 1620 1621 void 1622 dinoattach(device_t parent, device_t self, void *aux) 1623 { 1624 struct dino_softc *sc = device_private(self); 1625 struct confargs *ca = (struct confargs *)aux, nca; 1626 struct pcibus_attach_args pba; 1627 volatile struct dino_regs *r; 1628 struct cpu_info *ci = &cpus[0]; 1629 const char *p = NULL; 1630 int s, ver; 1631 1632 sc->sc_dv = self; 1633 sc->sc_bt = ca->ca_iot; 1634 sc->sc_dmat = ca->ca_dmatag; 1635 1636 ca->ca_irq = hppa_intr_allocate_bit(&ci->ci_ir, ca->ca_irq); 1637 if (ca->ca_irq == HPPACF_IRQ_UNDEF) { 1638 aprint_error_dev(self, ": can't allocate interrupt"); 1639 return; 1640 } 1641 1642 if (bus_space_map(sc->sc_bt, ca->ca_hpa, PAGE_SIZE, 0, &sc->sc_bh)) { 1643 aprint_error(": can't map space\n"); 1644 return; 1645 } 1646 1647 sc->sc_regs = r = (volatile struct dino_regs *)sc->sc_bh; 1648 #ifdef trust_the_firmware_to_proper_initialize_everything 1649 r->io_addr_en = 0; 1650 r->io_control = 0x80; 1651 r->pamr = 0; 1652 r->papr = 0; 1653 r->io_fbb_en |= 1; 1654 r->damode = 0; 1655 r->gmask &= ~1; /* allow GSC bus req */ 1656 r->pciror = 0; 1657 r->pciwor = 0; 1658 r->brdg_feat = 0xc0000000; 1659 #endif 1660 1661 snprintf(sc->sc_ioexname, sizeof(sc->sc_ioexname), 1662 "%s_io", device_xname(self)); 1663 sc->sc_ioex = extent_create(sc->sc_ioexname, 0, 0xffff, 1664 NULL, 0, EX_WAITOK | EX_MALLOCOK); 1665 1666 /* interrupts guts */ 1667 s = splhigh(); 1668 r->icr = 0; 1669 r->imr = 0; 1670 (void)r->irr0; 1671 r->iar0 = ci->ci_hpa | (31 - ca->ca_irq); 1672 splx(s); 1673 /* Establish the interrupt register. */ 1674 hppa_interrupt_register_establish(ci, &sc->sc_ir); 1675 sc->sc_ir.ir_name = device_xname(self); 1676 sc->sc_ir.ir_mask = &r->imr; 1677 sc->sc_ir.ir_req = &r->irr0; 1678 sc->sc_ir.ir_level = &r->ilr; 1679 /* Add the I/O interrupt register. */ 1680 1681 sc->sc_ih = hppa_intr_establish(IPL_NONE, NULL, &sc->sc_ir, 1682 &ci->ci_ir, ca->ca_irq); 1683 1684 /* TODO establish the bus error interrupt */ 1685 1686 ver = ca->ca_type.iodc_revision; 1687 switch ((ca->ca_type.iodc_model << 4) | 1688 (ca->ca_type.iodc_revision >> 4)) { 1689 case 0x05d: 1690 p = "Dino (card)"; /* j2240 */ 1691 /* FALLTHROUGH */ 1692 case 0x680: 1693 if (!p) 1694 p = "Dino"; 1695 switch (ver & 0xf) { 1696 case 0: ver = 0x20; break; 1697 case 1: ver = 0x21; break; 1698 case 2: ver = 0x30; break; 1699 case 3: ver = 0x31; break; 1700 } 1701 break; 1702 1703 case 0x682: 1704 p = "Cujo"; 1705 switch (ver & 0xf) { 1706 case 0: ver = 0x10; break; 1707 case 1: ver = 0x20; break; 1708 } 1709 break; 1710 1711 default: 1712 p = "Mojo"; 1713 break; 1714 } 1715 1716 sc->sc_ver = ver; 1717 aprint_normal(": %s V%d.%d\n", p, ver >> 4, ver & 0xf); 1718 1719 sc->sc_iot = dino_iomemt; 1720 sc->sc_iot.hbt_cookie = sc; 1721 sc->sc_iot.hbt_map = dino_iomap; 1722 sc->sc_iot.hbt_alloc = dino_ioalloc; 1723 sc->sc_memt = dino_iomemt; 1724 sc->sc_memt.hbt_cookie = sc; 1725 sc->sc_memt.hbt_map = dino_memmap; 1726 sc->sc_memt.hbt_alloc = dino_memalloc; 1727 sc->sc_pc = dino_pc; 1728 sc->sc_pc._cookie = sc; 1729 sc->sc_dmatag = dino_dmat; 1730 sc->sc_dmatag._cookie = sc; 1731 1732 /* scan for ps2 kbd/ms, serial, and flying toasters */ 1733 nca = *ca; 1734 1735 nca.ca_hpabase = 0; 1736 nca.ca_nmodules = MAXMODBUS; 1737 pdc_scanbus(self, &nca, dino_callback); 1738 1739 memset(&pba, 0, sizeof(pba)); 1740 pba.pba_iot = &sc->sc_iot; 1741 pba.pba_memt = &sc->sc_memt; 1742 pba.pba_dmat = &sc->sc_dmatag; 1743 pba.pba_pc = &sc->sc_pc; 1744 pba.pba_bus = 0; 1745 pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY; 1746 config_found(self, &pba, pcibusprint, 1747 CFARG_IATTR, "pcibus", 1748 CFARG_EOL); 1749 } 1750 1751 static device_t 1752 dino_callback(device_t self, struct confargs *ca) 1753 { 1754 return config_found(self, ca, mbprint, 1755 CFARG_SUBMATCH, mbsubmatch, 1756 CFARG_IATTR, "gedoens", 1757 CFARG_EOL); 1758 } 1759