Annotation of sys/arch/hppa/dev/pdc.c, Revision 1.1.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