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