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