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