1/* $NetBSD: pdc.c,v 1.4 2019/04/15 20:40:37 skrll Exp $ */ 2 3/* $OpenBSD: pdc.c,v 1.14 2001/04/29 21:05:43 mickey Exp $ */ 4 5/* 6 * Copyright (c) 1998-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: pdc.c,v 1.4 2019/04/15 20:40:37 skrll Exp $"); 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/device.h> 37#include <sys/proc.h> 38#include <sys/tty.h> 39#include <sys/callout.h> 40#include <sys/conf.h> 41#include <sys/kauth.h> 42 43#include <dev/cons.h> 44#include <dev/clock_subr.h> 45 46#include <machine/pdc.h> 47#include <machine/iomod.h> 48#include <machine/autoconf.h> 49 50#include <hppa/hppa/machdep.h> 51#include <hppa/dev/cpudevs.h> 52 53typedef 54struct pdc_softc { 55 device_t sc_dv; 56 struct tty *sc_tty; 57 struct callout sc_to; 58} pdcsoftc_t; 59 60pdcio_t pdc; 61 62enum pdc_type pdc_type; 63 64static struct pdc_result pdcret1 PDC_ALIGNMENT; 65static struct pdc_result pdcret2 PDC_ALIGNMENT; 66static char pdc_consbuf[IODC_MINIOSIZ] PDC_ALIGNMENT; 67 68iodcio_t pdc_cniodc, pdc_kbdiodc; 69pz_device_t *pz_kbd, *pz_cons; 70 71int pdcmatch(device_t, cfdata_t, void *); 72void pdcattach(device_t, device_t, void *); 73 74CFATTACH_DECL_NEW(pdc, sizeof(pdcsoftc_t), 75 pdcmatch, pdcattach, NULL, NULL); 76 77extern struct cfdriver pdc_cd; 78 79static int pdc_attached; 80 81dev_type_open(pdcopen); 82dev_type_close(pdcclose); 83dev_type_read(pdcread); 84dev_type_write(pdcwrite); 85dev_type_ioctl(pdcioctl); 86dev_type_stop(pdcstop); 87dev_type_tty(pdctty); 88dev_type_poll(pdcpoll); 89 90const struct cdevsw pdc_cdevsw = { 91 .d_open = pdcopen, 92 .d_close = pdcclose, 93 .d_read = pdcread, 94 .d_write = pdcwrite, 95 .d_ioctl = pdcioctl, 96 .d_stop = pdcstop, 97 .d_tty = pdctty, 98 .d_poll = pdcpoll, 99 .d_mmap = nommap, 100 .d_kqfilter = ttykqfilter, 101 .d_discard = nodiscard, 102 .d_flag = D_TTY 103}; 104 105void pdcstart(struct tty *); 106void pdctimeout(void *); 107int pdcparam(struct tty *, struct termios *); 108int pdccnlookc(dev_t, int *); 109 110static struct cnm_state pdc_cnm_state; 111 112static int pdcgettod(todr_chip_handle_t, struct timeval *); 113static int pdcsettod(todr_chip_handle_t, struct timeval *); 114 115void 116pdc_init(void) 117{ 118 static int kbd_iodc[IODC_MAXSIZE/sizeof(int)]; 119 static int cn_iodc[IODC_MAXSIZE/sizeof(int)]; 120 int err; 121 int pagezero_cookie; 122 123 pagezero_cookie = hppa_pagezero_map(); 124 125 pz_kbd = &PAGE0->mem_kbd; 126 pz_cons = &PAGE0->mem_cons; 127 128 pdc = (pdcio_t)PAGE0->mem_pdc; 129 130 /* XXX should we reset the console/kbd here? 131 well, /boot did that for us anyway */ 132 if ((err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_READ, 133 &pdcret1, pz_cons->pz_hpa, IODC_IO, cn_iodc, IODC_MAXSIZE)) < 0 || 134 (err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_READ, 135 &pdcret1, pz_kbd->pz_hpa, IODC_IO, kbd_iodc, IODC_MAXSIZE)) < 0) { 136#ifdef DEBUG 137 printf("pdc_init: failed reading IODC (%d)\n", err); 138#endif 139 } 140 141 hppa_pagezero_unmap(pagezero_cookie); 142 143 pdc_cniodc = (iodcio_t)cn_iodc; 144 pdc_kbdiodc = (iodcio_t)kbd_iodc; 145 146 /* XXX make pdc current console */ 147 cn_tab = &constab[0]; 148} 149 150void 151pdc_settype(int modelno) 152{ 153 switch (modelno) { 154 /* 720, 750, 730, 735, 755 */ 155 case HPPA_BOARD_HP720: 156 case HPPA_BOARD_HP750_66: 157 case HPPA_BOARD_HP730_66: 158 case HPPA_BOARD_HP735_99: 159 case HPPA_BOARD_HP755_99: 160 case HPPA_BOARD_HP755_125: 161 case HPPA_BOARD_HP735_130: 162 163 /* 710, 705, 7[12]5 */ 164 case HPPA_BOARD_HP710: 165 case HPPA_BOARD_HP705: 166 case HPPA_BOARD_HP715_50: 167 case HPPA_BOARD_HP715_33: 168 case HPPA_BOARD_HP715S_50: 169 case HPPA_BOARD_HP715S_33: 170 case HPPA_BOARD_HP715T_50: 171 case HPPA_BOARD_HP715T_33: 172 case HPPA_BOARD_HP715_75: 173 case HPPA_BOARD_HP715_99: 174 case HPPA_BOARD_HP725_50: 175 case HPPA_BOARD_HP725_75: 176 case HPPA_BOARD_HP725_99: 177 178 /* 745, 742, 747 */ 179 case HPPA_BOARD_HP745I_50: 180 case HPPA_BOARD_HP742I_50: 181 case HPPA_BOARD_HP747I_100: 182 183 /* 712/{60,80,100,120}, 715/{64,80,100,...}, etc */ 184 case HPPA_BOARD_HP712_60: 185 case HPPA_BOARD_HP712_80: 186 case HPPA_BOARD_HP712_100: 187 case HPPA_BOARD_HP743I_64: 188 case HPPA_BOARD_HP743I_100: 189 case HPPA_BOARD_HP712_120: 190 case HPPA_BOARD_HP715_80: 191 case HPPA_BOARD_HP715_64: 192 case HPPA_BOARD_HP715_100: 193 case HPPA_BOARD_HP715_100XC: 194 case HPPA_BOARD_HP725_100: 195 case HPPA_BOARD_HP725_120: 196 case HPPA_BOARD_HP715_100L: 197 case HPPA_BOARD_HP715_120L: 198 case HPPA_BOARD_HP725_80L: 199 case HPPA_BOARD_HP725_100L: 200 case HPPA_BOARD_HP725_120L: 201 case HPPA_BOARD_HP743_50: 202 case HPPA_BOARD_HP743_100: 203 case HPPA_BOARD_HP715_80M: 204 case HPPA_BOARD_HP811: 205 case HPPA_BOARD_HP801: 206 case HPPA_BOARD_HP743T: 207 pdc_type = PDC_TYPE_SNAKE; 208 break; 209 210 default: 211 pdc_type = PDC_TYPE_UNKNOWN; 212 } 213} 214 215enum pdc_type 216pdc_gettype(void) 217{ 218 219 return pdc_type; 220} 221 222int 223pdcmatch(device_t parent, cfdata_t cf, void *aux) 224{ 225 struct confargs *ca = aux; 226 227 /* there could be only one */ 228 if (pdc_attached || strcmp(ca->ca_name, "pdc")) 229 return 0; 230 231 return 1; 232} 233 234void 235pdcattach(device_t parent, device_t self, void *aux) 236{ 237 static struct todr_chip_handle todr = { 238 .todr_settime = pdcsettod, 239 .todr_gettime = pdcgettod, 240 }; 241 struct pdc_softc *sc = device_private(self); 242 243 sc->sc_dv = self; 244 pdc_attached = 1; 245 246 KASSERT(pdc != NULL); 247 248 cn_init_magic(&pdc_cnm_state); 249 cn_set_magic("+++++"); 250 251 /* attach the TOD clock */ 252 todr_attach(&todr); 253 254 aprint_normal("\n"); 255 256 callout_init(&sc->sc_to, 0); 257} 258 259int 260pdcopen(dev_t dev, int flag, int mode, struct lwp *l) 261{ 262 struct pdc_softc *sc; 263 struct tty *tp; 264 int s; 265 int error = 0, setuptimeout; 266 267 sc = device_lookup_private(&pdc_cd, minor(dev)); 268 if (sc == NULL) 269 return ENXIO; 270 271 s = spltty(); 272 273 if (sc->sc_tty) { 274 tp = sc->sc_tty; 275 } else { 276 tp = tty_alloc(); 277 sc->sc_tty = tp; 278 tty_attach(tp); 279 } 280 281 tp->t_oproc = pdcstart; 282 tp->t_param = pdcparam; 283 tp->t_dev = dev; 284 285 if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) { 286 splx(s); 287 return (EBUSY); 288 } 289 290 if ((tp->t_state & TS_ISOPEN) == 0) { 291 tp->t_state |= TS_CARR_ON; 292 ttychars(tp); 293 tp->t_iflag = TTYDEF_IFLAG; 294 tp->t_oflag = TTYDEF_OFLAG; 295 tp->t_cflag = TTYDEF_CFLAG|CLOCAL; 296 tp->t_lflag = TTYDEF_LFLAG; 297 tp->t_ispeed = tp->t_ospeed = 9600; 298 ttsetwater(tp); 299 300 setuptimeout = 1; 301 } else 302 setuptimeout = 0; 303 tp->t_state |= TS_CARR_ON; 304 305 splx(s); 306 307 error = (*tp->t_linesw->l_open)(dev, tp); 308 if (error == 0 && setuptimeout) 309 pdctimeout(sc); 310 311 return error; 312} 313 314int 315pdcclose(dev_t dev, int flag, int mode, struct lwp *l) 316{ 317 struct tty *tp; 318 struct pdc_softc *sc; 319 320 sc = device_lookup_private(&pdc_cd, minor(dev)); 321 if (sc == NULL) 322 return ENXIO; 323 324 tp = sc->sc_tty; 325 callout_stop(&sc->sc_to); 326 (*tp->t_linesw->l_close)(tp, flag); 327 ttyclose(tp); 328 return 0; 329} 330 331int 332pdcread(dev_t dev, struct uio *uio, int flag) 333{ 334 struct tty *tp; 335 struct pdc_softc *sc; 336 337 sc = device_lookup_private(&pdc_cd, minor(dev)); 338 if (sc == NULL) 339 return ENXIO; 340 341 tp = sc->sc_tty; 342 return ((*tp->t_linesw->l_read)(tp, uio, flag)); 343} 344 345int 346pdcwrite(dev_t dev, struct uio *uio, int flag) 347{ 348 struct tty *tp; 349 struct pdc_softc *sc; 350 351 sc = device_lookup_private(&pdc_cd, minor(dev)); 352 if (sc == NULL) 353 return ENXIO; 354 355 tp = sc->sc_tty; 356 return ((*tp->t_linesw->l_write)(tp, uio, flag)); 357} 358 359int 360pdcpoll(dev_t dev, int events, struct lwp *l) 361{ 362 struct pdc_softc *sc = device_lookup_private(&pdc_cd,minor(dev)); 363 struct tty *tp = sc->sc_tty; 364 365 return ((*tp->t_linesw->l_poll)(tp, events, l)); 366} 367 368int 369pdcioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 370{ 371 int error; 372 struct tty *tp; 373 struct pdc_softc *sc; 374 375 sc = device_lookup_private(&pdc_cd, minor(dev)); 376 if (sc == NULL) 377 return ENXIO; 378 379 tp = sc->sc_tty; 380 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 381 if (error >= 0) 382 return error; 383 error = ttioctl(tp, cmd, data, flag, l); 384 if (error >= 0) 385 return error; 386 387 return ENOTTY; 388} 389 390int 391pdcparam(struct tty *tp, struct termios *t) 392{ 393 394 return 0; 395} 396 397void 398pdcstart(struct tty *tp) 399{ 400 int s; 401 402 s = spltty(); 403 if (tp->t_state & (TS_TTSTOP | TS_BUSY)) { 404 splx(s); 405 return; 406 } 407 ttypull(tp); 408 tp->t_state |= TS_BUSY; 409 while (tp->t_outq.c_cc != 0) 410 pdccnputc(tp->t_dev, getc(&tp->t_outq)); 411 tp->t_state &= ~TS_BUSY; 412 splx(s); 413} 414 415void 416pdcstop(struct tty *tp, int flag) 417{ 418 int s; 419 420 s = spltty(); 421 if (tp->t_state & TS_BUSY) 422 if ((tp->t_state & TS_TTSTOP) == 0) 423 tp->t_state |= TS_FLUSH; 424 splx(s); 425} 426 427void 428pdctimeout(void *v) 429{ 430 struct pdc_softc *sc = v; 431 struct tty *tp = sc->sc_tty; 432 int c; 433 434 while (pdccnlookc(tp->t_dev, &c)) { 435 cn_check_magic(tp->t_dev, c, pdc_cnm_state); 436 if (tp->t_state & TS_ISOPEN) 437 (*tp->t_linesw->l_rint)(c, tp); 438 } 439 callout_reset(&sc->sc_to, 1, pdctimeout, sc); 440} 441 442struct tty * 443pdctty(dev_t dev) 444{ 445 struct pdc_softc *sc; 446 447 sc = device_lookup_private(&pdc_cd, minor(dev)); 448 if (sc == NULL) 449 return NULL; 450 451 return sc->sc_tty; 452} 453 454void 455pdccnprobe(struct consdev *cn) 456{ 457 458 cn->cn_dev = makedev(22,0); 459 cn->cn_pri = CN_NORMAL; 460} 461 462void 463pdccninit(struct consdev *cn) 464{ 465#ifdef DEBUG 466 printf("pdc0: console init\n"); 467#endif 468} 469 470int 471pdccnlookc(dev_t dev, int *cp) 472{ 473 int s, err __debugused, l, pagezero_cookie; 474 475 s = splhigh(); 476 pagezero_cookie = hppa_pagezero_map(); 477 err = pdc_call(pdc_kbdiodc, 0, pz_kbd->pz_hpa, IODC_IO_CONSIN, 478 pz_kbd->pz_spa, pz_kbd->pz_layers, &pdcret1, 0, pdc_consbuf, 1, 0); 479 l = pdcret1.result[0]; 480 *cp = pdc_consbuf[0]; 481 hppa_pagezero_unmap(pagezero_cookie); 482 splx(s); 483 484#ifdef DEBUG 485 if (err < 0) 486 printf("pdccnlookc: input error: %d\n", err); 487#endif 488 return l; 489} 490 491int 492pdccngetc(dev_t dev) 493{ 494 int c; 495 496 if (!pdc) 497 return 0; 498 while (!pdccnlookc(dev, &c)) 499 ; 500 return (c); 501} 502 503void 504pdccnputc(dev_t dev, int c) 505{ 506 int s, err, pagezero_cookie; 507 508 s = splhigh(); 509 pagezero_cookie = hppa_pagezero_map(); 510 *pdc_consbuf = c; 511 err = pdc_call(pdc_cniodc, 0, pz_cons->pz_hpa, IODC_IO_CONSOUT, 512 pz_cons->pz_spa, pz_cons->pz_layers, &pdcret1, 0, pdc_consbuf, 1, 0); 513 hppa_pagezero_unmap(pagezero_cookie); 514 splx(s); 515 516 if (err < 0) { 517#if defined(DDB) || defined(KGDB) 518 Debugger(); 519#endif /* DDB || KGDB */ 520 delay(250000); 521#if 0 522 /* 523 * It's not a good idea to use the output to print 524 * an output error. 525 */ 526 printf("pdccnputc: output error: %d\n", err); 527#endif 528 } 529} 530 531void 532pdccnpollc(dev_t dev, int on) 533{ 534} 535 536static int 537pdcgettod(todr_chip_handle_t tch, struct timeval *tvp) 538{ 539 struct pdc_tod *tod = (struct pdc_tod *)&pdcret1; 540 int error; 541 542 error = pdc_call((iodcio_t)pdc, 1, PDC_TOD, PDC_TOD_READ, 543 &pdcret1); 544 545 if (error == 0) { 546 tvp->tv_sec = tod->sec; 547 tvp->tv_usec = tod->usec; 548 } 549 return error; 550} 551 552static int 553pdcsettod(todr_chip_handle_t tch, struct timeval *tvp) 554{ 555 int error; 556 557 error = pdc_call((iodcio_t)pdc, 1, PDC_TOD, PDC_TOD_WRITE, 558 tvp->tv_sec, tvp->tv_usec); 559 560 return error; 561} 562 563 564int 565pdcproc_chassis_display(unsigned long disp) 566{ 567 int err; 568 569 err = pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_DISP, disp); 570 571 return err; 572} 573 574int 575pdcproc_chassis_info(struct pdc_chassis_info *pci, struct pdc_chassis_lcd *pcl) 576{ 577 int err; 578 579 err = pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_INFO, 580 &pdcret1, &pdcret2 , sizeof(*pcl)); 581 if (err < 0) 582 return err; 583 584 memcpy(pci, &pdcret1, sizeof(*pci)); 585 memcpy(pcl, &pdcret2, sizeof(*pcl)); 586 587 return err; 588} 589 590int 591pdcproc_pim(int type, struct pdc_pim *pp, void **buf, size_t *sz) 592{ 593 static char data[896] __attribute__((__aligned__(8))); 594 int err; 595 596 err = pdc_call((iodcio_t)pdc, 0, PDC_PIM, type, &pdcret1, data, 597 sizeof(data)); 598 if (err < 0) 599 return err; 600 601 memcpy(pp, &pdcret1, sizeof(*pp)); 602 *buf = data; 603 *sz = sizeof(data); 604 605 return err; 606} 607 608int 609pdcproc_model_info(struct pdc_model *pm) 610{ 611 int err; 612 613 err = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO, &pdcret1); 614 if (err < 0) 615 return err; 616 617 memcpy(pm, &pdcret1, sizeof(*pm)); 618 619 return err; 620} 621 622int 623pdcproc_model_cpuid(struct pdc_cpuid *pc) 624{ 625 int err; 626 627 err = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_CPUID, &pdcret1); 628 if (err < 0) 629 return err; 630 631 memcpy(pc, &pdcret1, sizeof(*pc)); 632 633 return err; 634} 635 636int 637pdcproc_cache(struct pdc_cache *pc) 638{ 639 int err; 640 641 err = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT, &pdcret1); 642 643 if (err < 0) 644 return err; 645 646 memcpy(pc, &pdcret1, sizeof(*pc)); 647 648 return err; 649} 650 651 652int 653pdcproc_cache_spidbits(struct pdc_spidb *pcs) 654{ 655 int err; 656 657 err = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_GETSPIDB, 658 &pdcret1); 659 660 if (err < 0) 661 return err; 662 663 memcpy(pcs, &pdcret1, sizeof(*pcs)); 664 665 return err; 666} 667 668int 669pdcproc_hpa_processor(hppa_hpa_t *hpa) 670{ 671 int err; 672 673 err = pdc_call((iodcio_t)pdc, 0, PDC_HPA, PDC_HPA_DFLT, &pdcret1); 674 if (err < 0) 675 return err; 676 677 *hpa = pdcret1.result[0]; 678 679 return err; 680} 681 682int 683pdcproc_coproc(struct pdc_coproc *pc) 684{ 685 int err; 686 687 err = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT, &pdcret1); 688 if (err < 0) 689 return err; 690 691 memcpy(pc, &pdcret1, sizeof(*pc)); 692 693 return err; 694} 695 696int 697pdcproc_iodc_read(hppa_hpa_t hpa, int command, int *actcnt, 698 struct pdc_iodc_read *buf1, size_t sz1, struct iodc_data *buf2, 699 size_t sz2) 700{ 701 int err; 702 703 err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_READ, 704 &pdcret1, hpa, command, &pdcret2, sizeof(pdcret2)); 705 706 if (err < 0) 707 return err; 708 709 if (actcnt != NULL) { 710 struct pdc_iodc_read *pir = (struct pdc_iodc_read *)&pdcret1; 711 712 *actcnt = pir->size; 713 } 714 715 memcpy(buf1, &pdcret1, sz1); 716 memcpy(buf2, &pdcret2, sz2); 717 718 return err; 719} 720 721int 722pdcproc_iodc_ninit(struct pdc_iodc_minit *pimi, hppa_hpa_t hpa, int sz) 723{ 724 int err; 725 726 err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_NINIT, &pdcret1, 727 hpa, sz); 728 729 if (err < 0) 730 return err; 731 732 memcpy(pimi, &pdcret1, sizeof(*pimi)); 733 734 return err; 735} 736 737int 738pdcproc_instr(unsigned int *mem) 739{ 740 int err; 741 742 err = pdc_call((iodcio_t)pdc, 0, PDC_INSTR, PDC_INSTR_DFLT, &pdcret1); 743 if (err < 0) 744 return err; 745 746 memcpy(mem, &pdcret1, sizeof(*mem)); 747 748 return err; 749} 750 751int 752pdcproc_block_tlb(struct pdc_btlb *pb) 753{ 754 int err; 755 756 err = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_DEFAULT, 757 &pdcret1); 758 if (err < 0) 759 return err; 760 761 memcpy(pb, &pdcret1, sizeof(*pb)); 762 763 return err; 764} 765 766int 767pdcproc_btlb_insert(pa_space_t sp, vaddr_t va, paddr_t pa, vsize_t sz, 768 u_int prot, int index) 769{ 770 int err; 771 772 err = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_INSERT, sp, 773 va, pa, sz, prot, index); 774 775 return err; 776} 777 778int 779pdcproc_btlb_purge(pa_space_t sp, vaddr_t va, paddr_t pa, vsize_t sz) 780{ 781 int err; 782 783 err = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_PURGE, sp, va, 784 pa, sz); 785 786 return err; 787} 788 789int 790pdcproc_btlb_purgeall(void) 791{ 792 int err; 793 794 err = pdc_call((iodcio_t)pdc, 0, PDC_BLOCK_TLB, PDC_BTLB_PURGE_ALL); 795 796 return err; 797} 798 799int pdcproc_tlb_info(struct pdc_hwtlb *ph) 800{ 801 int err; 802 803 err = pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_INFO, &pdcret1); 804 if (err < 0) 805 return err; 806 807 memcpy(ph, &pdcret1, sizeof(*ph)); 808 809 return err; 810} 811 812int 813pdcproc_tlb_config(struct pdc_hwtlb *ph, unsigned long hpt, 814 unsigned long hptsize, unsigned long type) 815{ 816 int err; 817 818 err = pdc_call((iodcio_t)pdc, 0, PDC_TLB, PDC_TLB_CONFIG, ph, hpt, 819 hptsize, type); 820 821 return err; 822} 823 824int 825pdcproc_system_map_find_mod(struct pdc_system_map_find_mod *psm, 826 struct device_path *dev, int mod) 827{ 828 int err; 829 830 err = pdc_call((iodcio_t)pdc, 0, PDC_SYSTEM_MAP, 831 PDC_SYSTEM_MAP_FIND_MOD, &pdcret1, &pdcret2, mod); 832 if (err < 0) 833 return err; 834 835 memcpy(psm, &pdcret1, sizeof(*psm)); 836 memcpy(dev, &pdcret2, sizeof(*dev)); 837 838 return err; 839} 840 841int 842pdcproc_system_map_find_addr(struct pdc_system_map_find_addr *psm, int mod, 843 int addr) 844{ 845 int err; 846 847 err = pdc_call((iodcio_t)pdc, 0, PDC_SYSTEM_MAP, 848 PDC_SYSTEM_MAP_FIND_ADDR, &pdcret1, mod, addr); 849 if (err < 0) 850 return err; 851 852 memcpy(psm, &pdcret1, sizeof(*psm)); 853 854 return err; 855 856} 857 858int 859pdcproc_system_map_trans_path(struct pdc_memmap *pmm, struct device_path *dev) 860{ 861 int err; 862 863 memcpy(&pdcret2, dev, sizeof(*dev)); 864 865 err = pdc_call((iodcio_t)pdc, 0, PDC_SYSTEM_MAP, 866 PDC_SYSTEM_MAP_TRANS_PATH, &pdcret1, &pdcret2); 867 if (err < 0) 868 return err; 869 870 memcpy(pmm, &pdcret1, sizeof(*pmm)); 871 872 return err; 873} 874 875int 876pdcproc_soft_power_info(struct pdc_power_info *pspi) 877{ 878 int err; 879 880 err = pdc_call((iodcio_t)pdc, 0, PDC_SOFT_POWER, PDC_SOFT_POWER_INFO, 881 &pdcret1, 0); 882 if (err < 0) 883 return err; 884 885 memcpy(pspi, &pdcret1, sizeof(*pspi)); 886 887 return err; 888} 889 890int 891pdcproc_soft_power_enable(int action) 892{ 893 int err; 894 895 err = pdc_call((iodcio_t)pdc, 0, PDC_SOFT_POWER, PDC_SOFT_POWER_ENABLE, 896 &pdcret1, action); 897 898 return err; 899} 900 901int 902pdcproc_memmap(struct pdc_memmap *pmm, struct device_path *dev) 903{ 904 int err; 905 906 memcpy(&pdcret2, dev, sizeof(*dev)); 907 908 err = pdc_call((iodcio_t)pdc, 0, PDC_MEMMAP, PDC_MEMMAP_HPA, &pdcret1, 909 &pdcret2); 910 if (err < 0) 911 return err; 912 913 memcpy(pmm, &pdcret1, sizeof(*pmm)); 914 915 return err; 916} 917 918int 919pdcproc_ioclrerrors(void) 920{ 921 int err; 922 923 err = pdc_call((iodcio_t)pdc, 0, PDC_IO, PDC_IO_READ_AND_CLEAR_ERRORS); 924 925 return err; 926} 927 928int 929pdcproc_ioreset(void) 930{ 931 int err; 932 933 err = pdc_call((iodcio_t)pdc, 0, PDC_IO, PDC_IO_RESET_DEVICES); 934 935 return err; 936} 937 938int 939pdcproc_doreset(void) 940{ 941 int err; 942 943 err = pdc_call((iodcio_t)pdc, 0, PDC_BROADCAST_RESET, PDC_DO_RESET); 944 945 return err; 946} 947 948int 949pdcproc_lan_station_id(char *addr, size_t sz, hppa_hpa_t hpa) 950{ 951 struct pdc_lan_station_id *mac = (struct pdc_lan_station_id *)&pdcret1; 952 int err; 953 954 err = pdc_call((iodcio_t)pdc, 0, PDC_LAN_STATION_ID, 955 PDC_LAN_STATION_ID_READ, &pdcret1, hpa); 956 if (err < 0) 957 return err; 958 959 memcpy(addr, mac->addr, sz); 960 961 return 0; 962} 963 964int 965pdcproc_pci_inttblsz(int *nentries) 966{ 967 struct pdc_pat_io_num *ppio = (struct pdc_pat_io_num *)&pdcret1; 968 int err; 969 970 err = pdc_call((iodcio_t)pdc, 0, PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SZ, 971 &pdcret1); 972 973 *nentries = ppio->num; 974 975 return err; 976} 977 978/* Maximum number of supported interrupt routing entries. */ 979#define MAX_INT_TBL_SZ 16 980 981int 982pdcproc_pci_gettable(int nentries, size_t size, void *table) 983{ 984 int err; 985 static struct pdc_pat_pci_rt int_tbl[MAX_INT_TBL_SZ] PDC_ALIGNMENT; 986 987 if (nentries > MAX_INT_TBL_SZ) 988 panic("interrupt routing table too big (%d entries)", nentries); 989 990 pdcret1.result[0] = nentries; 991 992 err = pdc_call((iodcio_t)pdc, 0, PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL, 993 &pdcret1, 0, &int_tbl); 994 if (err < 0) 995 return err; 996 997 memcpy(table, int_tbl, size); 998 999 return err; 1000} 1001