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