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