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