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