Annotation of sys/arch/hppa/dev/pdc.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: pdc.c,v 1.30 2007/07/15 19:25:49 kettenis Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1998-2003 Michael Shalayeff
! 5: * All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 19: * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
! 20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 22: * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
! 25: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
! 26: * THE POSSIBILITY OF SUCH DAMAGE.
! 27: */
! 28:
! 29: #include "com.h"
! 30:
! 31: #include <sys/param.h>
! 32: #include <sys/systm.h>
! 33: #include <sys/device.h>
! 34: #include <sys/tty.h>
! 35: #include <sys/user.h>
! 36: #include <sys/timeout.h>
! 37:
! 38: #include <dev/cons.h>
! 39:
! 40: #include <machine/conf.h>
! 41: #include <machine/pdc.h>
! 42: #include <machine/iomod.h>
! 43: #include <machine/autoconf.h>
! 44:
! 45: typedef
! 46: struct pdc_softc {
! 47: struct device sc_dv;
! 48: struct tty *sc_tty;
! 49: struct timeout sc_to;
! 50: } pdcsoftc_t;
! 51:
! 52: pdcio_t pdc;
! 53: int pdcret[32] PDC_ALIGNMENT;
! 54: char pdc_consbuf[IODC_MINIOSIZ] PDC_ALIGNMENT;
! 55: iodcio_t pdc_cniodc, pdc_kbdiodc;
! 56: pz_device_t *pz_kbd, *pz_cons;
! 57:
! 58: int pdcngetc(dev_t);
! 59: void pdcnputc(dev_t, char *);
! 60:
! 61: struct consdev pdccons = { NULL, NULL, pdccngetc, pdccnputc,
! 62: nullcnpollc, NULL, makedev(22, 0), CN_NORMAL };
! 63:
! 64: int pdcmatch(struct device *, void *, void *);
! 65: void pdcattach(struct device *, struct device *, void *);
! 66:
! 67: struct cfattach pdc_ca = {
! 68: sizeof(pdcsoftc_t), pdcmatch, pdcattach
! 69: };
! 70:
! 71: struct cfdriver pdc_cd = {
! 72: NULL, "pdc", DV_DULL
! 73: };
! 74:
! 75: void pdcstart(struct tty *tp);
! 76: void pdctimeout(void *v);
! 77: int pdcparam(struct tty *tp, struct termios *);
! 78: int pdccnlookc(dev_t dev, int *cp);
! 79:
! 80: #if NCOM_GSC > 0
! 81: /* serial console speed table */
! 82: static int pdc_speeds[] = {
! 83: B50,
! 84: B75,
! 85: B110,
! 86: B150,
! 87: B300,
! 88: B600,
! 89: B1200,
! 90: B2400,
! 91: B4800,
! 92: B7200,
! 93: B9600,
! 94: B19200,
! 95: B38400,
! 96: B57600,
! 97: B115200,
! 98: B230400,
! 99: };
! 100: #endif
! 101:
! 102: void
! 103: pdc_init()
! 104: {
! 105: static int kbd_iodc[IODC_MAXSIZE/sizeof(int)];
! 106: static int cn_iodc[IODC_MAXSIZE/sizeof(int)];
! 107: int err;
! 108:
! 109: /* XXX locore've done it XXX pdc = (pdcio_t)PAGE0->mem_pdc; */
! 110: pz_kbd = &PAGE0->mem_kbd;
! 111: pz_cons = &PAGE0->mem_cons;
! 112:
! 113: /* XXX should we reset the console/kbd here?
! 114: well, /boot did that for us anyway */
! 115: if ((err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_READ,
! 116: pdcret, pz_cons->pz_hpa, IODC_IO, cn_iodc, IODC_MAXSIZE)) < 0 ||
! 117: (err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_READ,
! 118: pdcret, pz_kbd->pz_hpa, IODC_IO, kbd_iodc, IODC_MAXSIZE)) < 0) {
! 119: #ifdef DEBUG
! 120: printf("pdc_init: failed reading IODC (%d)\n", err);
! 121: #endif
! 122: }
! 123:
! 124: pdc_cniodc = (iodcio_t)cn_iodc;
! 125: pdc_kbdiodc = (iodcio_t)kbd_iodc;
! 126:
! 127: /* Start out with pdc as the console. */
! 128: cn_tab = &pdccons;
! 129:
! 130: /* Figure out console settings. */
! 131: #if NCOM_GSC > 0
! 132: if (PAGE0->mem_cons.pz_class == PCL_DUPLEX) {
! 133: struct pz_device *pzd = &PAGE0->mem_cons;
! 134: extern int comdefaultrate;
! 135: #ifdef DEBUG
! 136: printf("console: class %d flags %b ",
! 137: pzd->pz_class, pzd->pz_flags, PZF_BITS);
! 138: printf("bc %d/%d/%d/%d/%d/%d ",
! 139: pzd->pz_bc[0], pzd->pz_bc[1], pzd->pz_bc[2],
! 140: pzd->pz_bc[3], pzd->pz_bc[4], pzd->pz_bc[5]);
! 141: printf("mod %x layers %x/%x/%x/%x/%x/%x hpa %x\n", pzd->pz_mod,
! 142: pzd->pz_layers[0], pzd->pz_layers[1], pzd->pz_layers[2],
! 143: pzd->pz_layers[3], pzd->pz_layers[4], pzd->pz_layers[5],
! 144: pzd->pz_hpa);
! 145:
! 146: #endif
! 147:
! 148: /* compute correct baud rate */
! 149: if (PZL_SPEED(pzd->pz_layers[0]) <
! 150: sizeof(pdc_speeds) / sizeof(int))
! 151: comdefaultrate =
! 152: pdc_speeds[PZL_SPEED(pzd->pz_layers[0])];
! 153: else
! 154: comdefaultrate = B9600; /* XXX */
! 155: }
! 156: #endif
! 157: }
! 158:
! 159: int
! 160: pdcmatch(parent, cfdata, aux)
! 161: struct device *parent;
! 162: void *cfdata;
! 163: void *aux;
! 164: {
! 165: struct cfdata *cf = cfdata;
! 166: struct confargs *ca = aux;
! 167:
! 168: /* there could be only one */
! 169: if (cf->cf_unit > 0 && !strcmp(ca->ca_name, "pdc"))
! 170: return 0;
! 171:
! 172: return 1;
! 173: }
! 174:
! 175: void
! 176: pdcattach(parent, self, aux)
! 177: struct device *parent;
! 178: struct device *self;
! 179: void *aux;
! 180: {
! 181: struct pdc_softc *sc = (struct pdc_softc *)self;
! 182:
! 183: if (!pdc)
! 184: pdc_init();
! 185:
! 186: printf("\n");
! 187:
! 188: timeout_set(&sc->sc_to, pdctimeout, sc);
! 189: }
! 190:
! 191: int
! 192: pdcopen(dev, flag, mode, p)
! 193: dev_t dev;
! 194: int flag, mode;
! 195: struct proc *p;
! 196: {
! 197: int unit = minor(dev);
! 198: struct pdc_softc *sc;
! 199: struct tty *tp;
! 200: int s;
! 201: int error = 0, setuptimeout = 0;
! 202:
! 203: if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL)
! 204: return ENXIO;
! 205:
! 206: s = spltty();
! 207:
! 208: if (sc->sc_tty)
! 209: tp = sc->sc_tty;
! 210: else {
! 211: tp = sc->sc_tty = ttymalloc();
! 212: }
! 213:
! 214: tp->t_oproc = pdcstart;
! 215: tp->t_param = pdcparam;
! 216: tp->t_dev = dev;
! 217: if ((tp->t_state & TS_ISOPEN) == 0) {
! 218: ttychars(tp);
! 219: tp->t_iflag = TTYDEF_IFLAG;
! 220: tp->t_oflag = TTYDEF_OFLAG;
! 221: tp->t_cflag = TTYDEF_CFLAG|CLOCAL;
! 222: tp->t_lflag = TTYDEF_LFLAG;
! 223: tp->t_ispeed = tp->t_ospeed = B9600;
! 224: ttsetwater(tp);
! 225:
! 226: setuptimeout = 1;
! 227: } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) {
! 228: splx(s);
! 229: return (EBUSY);
! 230: }
! 231: tp->t_state |= TS_CARR_ON;
! 232: splx(s);
! 233:
! 234: error = (*linesw[tp->t_line].l_open)(dev, tp);
! 235: if (error == 0 && setuptimeout)
! 236: pdctimeout(sc);
! 237:
! 238: return error;
! 239: }
! 240:
! 241: int
! 242: pdcclose(dev, flag, mode, p)
! 243: dev_t dev;
! 244: int flag, mode;
! 245: struct proc *p;
! 246: {
! 247: int unit = minor(dev);
! 248: struct tty *tp;
! 249: struct pdc_softc *sc;
! 250:
! 251: if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL)
! 252: return ENXIO;
! 253:
! 254: tp = sc->sc_tty;
! 255: timeout_del(&sc->sc_to);
! 256: (*linesw[tp->t_line].l_close)(tp, flag);
! 257: ttyclose(tp);
! 258: return 0;
! 259: }
! 260:
! 261: int
! 262: pdcread(dev, uio, flag)
! 263: dev_t dev;
! 264: struct uio *uio;
! 265: int flag;
! 266: {
! 267: int unit = minor(dev);
! 268: struct tty *tp;
! 269: struct pdc_softc *sc;
! 270:
! 271: if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL)
! 272: return ENXIO;
! 273:
! 274: tp = sc->sc_tty;
! 275: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
! 276: }
! 277:
! 278: int
! 279: pdcwrite(dev, uio, flag)
! 280: dev_t dev;
! 281: struct uio *uio;
! 282: int flag;
! 283: {
! 284: int unit = minor(dev);
! 285: struct tty *tp;
! 286: struct pdc_softc *sc;
! 287:
! 288: if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL)
! 289: return ENXIO;
! 290:
! 291: tp = sc->sc_tty;
! 292: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
! 293: }
! 294:
! 295: int
! 296: pdcioctl(dev, cmd, data, flag, p)
! 297: dev_t dev;
! 298: u_long cmd;
! 299: caddr_t data;
! 300: int flag;
! 301: struct proc *p;
! 302: {
! 303: int unit = minor(dev);
! 304: int error;
! 305: struct tty *tp;
! 306: struct pdc_softc *sc;
! 307:
! 308: if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL)
! 309: return ENXIO;
! 310:
! 311: tp = sc->sc_tty;
! 312: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
! 313: if (error >= 0)
! 314: return error;
! 315: error = ttioctl(tp, cmd, data, flag, p);
! 316: if (error >= 0)
! 317: return error;
! 318:
! 319: return ENOTTY;
! 320: }
! 321:
! 322: int
! 323: pdcparam(tp, t)
! 324: struct tty *tp;
! 325: struct termios *t;
! 326: {
! 327:
! 328: return 0;
! 329: }
! 330:
! 331: void
! 332: pdcstart(tp)
! 333: struct tty *tp;
! 334: {
! 335: int s;
! 336:
! 337: s = spltty();
! 338: if (tp->t_state & (TS_TTSTOP | TS_BUSY)) {
! 339: splx(s);
! 340: return;
! 341: }
! 342: if (tp->t_outq.c_cc <= tp->t_lowat) {
! 343: if (tp->t_state & TS_ASLEEP) {
! 344: tp->t_state &= ~TS_ASLEEP;
! 345: wakeup((caddr_t)&tp->t_outq);
! 346: }
! 347: selwakeup(&tp->t_wsel);
! 348: }
! 349: tp->t_state |= TS_BUSY;
! 350: while (tp->t_outq.c_cc != 0)
! 351: pdccnputc(tp->t_dev, getc(&tp->t_outq));
! 352: tp->t_state &= ~TS_BUSY;
! 353: splx(s);
! 354: }
! 355:
! 356: int
! 357: pdcstop(tp, flag)
! 358: struct tty *tp;
! 359: int flag;
! 360: {
! 361: int s;
! 362:
! 363: s = spltty();
! 364: if (tp->t_state & TS_BUSY)
! 365: if ((tp->t_state & TS_TTSTOP) == 0)
! 366: tp->t_state |= TS_FLUSH;
! 367: splx(s);
! 368: return 0;
! 369: }
! 370:
! 371: void
! 372: pdctimeout(v)
! 373: void *v;
! 374: {
! 375: struct pdc_softc *sc = v;
! 376: struct tty *tp = sc->sc_tty;
! 377: int c;
! 378:
! 379: while (pdccnlookc(tp->t_dev, &c)) {
! 380: if (tp->t_state & TS_ISOPEN)
! 381: (*linesw[tp->t_line].l_rint)(c, tp);
! 382: }
! 383: timeout_add(&sc->sc_to, 1);
! 384: }
! 385:
! 386: struct tty *
! 387: pdctty(dev)
! 388: dev_t dev;
! 389: {
! 390: int unit = minor(dev);
! 391: struct pdc_softc *sc;
! 392:
! 393: if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL)
! 394: return NULL;
! 395:
! 396: return sc->sc_tty;
! 397: }
! 398:
! 399: int
! 400: pdccnlookc(dev, cp)
! 401: dev_t dev;
! 402: int *cp;
! 403: {
! 404: int err, l;
! 405: int s = splhigh();
! 406:
! 407: err = pdc_call(pdc_kbdiodc, 0, pz_kbd->pz_hpa, IODC_IO_CONSIN,
! 408: pz_kbd->pz_spa, pz_kbd->pz_layers, pdcret, 0, pdc_consbuf, 1, 0);
! 409:
! 410: l = pdcret[0];
! 411: *cp = pdc_consbuf[0];
! 412: splx(s);
! 413: #ifdef DEBUG
! 414: if (err < 0)
! 415: printf("pdccnlookc: input error: %d\n", err);
! 416: #endif
! 417:
! 418: return l;
! 419: }
! 420:
! 421: int
! 422: pdccngetc(dev)
! 423: dev_t dev;
! 424: {
! 425: int c;
! 426:
! 427: if (!pdc)
! 428: return 0;
! 429:
! 430: while(!pdccnlookc(dev, &c))
! 431: ;
! 432:
! 433: return (c);
! 434: }
! 435:
! 436: void
! 437: pdccnputc(dev, c)
! 438: dev_t dev;
! 439: int c;
! 440: {
! 441: register int err;
! 442: int s = splhigh();
! 443:
! 444: *pdc_consbuf = c;
! 445: err = pdc_call(pdc_cniodc, 0, pz_cons->pz_hpa, IODC_IO_CONSOUT,
! 446: pz_cons->pz_spa, pz_cons->pz_layers, pdcret, 0, pdc_consbuf, 1, 0);
! 447: splx(s);
! 448:
! 449: if (err < 0) {
! 450: #ifdef DEBUG
! 451: printf("pdccnputc: output error: %d\n", err);
! 452: #endif
! 453: }
! 454: }
CVSweb