Annotation of sys/arch/luna88k/dev/lcd.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: lcd.c,v 1.3 2007/02/09 14:26:09 aoyama Exp $ */
2: /* $NetBSD: lcd.c,v 1.2 2000/01/07 05:13:08 nisimura Exp $ */
3:
4: /*-
5: * Copyright (c) 2000 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Tohru Nishimura.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/device.h>
43: #include <sys/ioctl.h>
44: #include <sys/fcntl.h>
45:
46: #include <machine/autoconf.h>
47: #include <machine/conf.h>
48: #include <machine/lcd.h>
49:
50: #define PIO1_MODE_OUTPUT 0x84
51: #define PIO1_MODE_INPUT 0x94
52:
53: #define POWER 0x10
54:
55: #define ENABLE 0x80
56: #define DISABLE 0x00
57:
58: #define WRITE_CMD (0x00 | 0x00)
59: #define WRITE_DATA (0x00 | 0x40)
60: #define READ_BUSY (0x20 | 0x00)
61: #define READ_DATA (0x20 | 0x40)
62:
63: #define LCD_INIT 0x38
64: #define LCD_ENTRY 0x06
65: #define LCD_ON 0x0c
66: #define LCD_CLS 0x01
67: #define LCD_HOME 0x02
68: #define LCD_LOCATE(X, Y) (((Y) & 1 ? 0xc0 : 0x80) | ((X) & 0x0f))
69:
70: #define LCD_MAXBUFLEN 80
71:
72: struct pio {
73: volatile u_int8_t portA;
74: volatile unsigned : 24;
75: volatile u_int8_t portB;
76: volatile unsigned : 24;
77: volatile u_int8_t portC;
78: volatile unsigned : 24;
79: volatile u_int8_t cntrl;
80: volatile unsigned : 24;
81: };
82:
83: /* Autoconf stuff */
84: int lcd_match(struct device *, void *, void *);
85: void lcd_attach(struct device *, struct device *, void *);
86:
87: struct lcd_softc {
88: struct device sc_dev;
89: int sc_opened;
90: };
91:
92: struct cfattach lcd_ca = {
93: sizeof(struct lcd_softc), lcd_match, lcd_attach
94: };
95:
96: struct cfdriver lcd_cd = {
97: NULL, "lcd", DV_DULL, 0
98: };
99:
100: /* Internal prototypes */
101: void lcdbusywait(void);
102: void lcdput(int);
103: void lcdctrl(int);
104: void lcdshow(const char *);
105: void greeting(void);
106:
107: /* Internal variables */
108: /* "1234567890123456" */
109: static const char lcd_boot_message1[] = "OpenBSD/luna88k ";
110: static const char lcd_boot_message2[] = " SX-9100/DT ";
111:
112: /*
113: * Autoconf functions
114: */
115: int
116: lcd_match(parent, cf, aux)
117: struct device *parent;
118: void *cf, *aux;
119: {
120: struct mainbus_attach_args *ma = aux;
121:
122: if (strcmp(ma->ma_name, lcd_cd.cd_name))
123: return 0;
124: if (badaddr((vaddr_t)ma->ma_addr, 4))
125: return 0;
126: return 1;
127: }
128:
129: void
130: lcd_attach(parent, self, aux)
131: struct device *parent, *self;
132: void *aux;
133: {
134: printf("\n");
135:
136: /* Say hello to the world on LCD. */
137: greeting();
138: }
139:
140: /*
141: * open/close/write/ioctl
142: */
143:
144: int
145: lcdopen(dev, flags, fmt, p)
146: dev_t dev;
147: int flags, fmt;
148: struct proc *p;
149: {
150: int unit = minor(dev);
151: struct lcd_softc *sc;
152:
153: if (unit >= lcd_cd.cd_ndevs)
154: return ENXIO;
155: if ((sc = lcd_cd.cd_devs[unit]) == NULL)
156: return ENXIO;
157: if (sc->sc_opened)
158: return EBUSY;
159: sc->sc_opened = 1;
160:
161: return 0;
162: }
163:
164: int
165: lcdclose(dev, flags, fmt, p)
166: dev_t dev;
167: int flags, fmt;
168: struct proc *p;
169: {
170: int unit = minor(dev);
171: struct lcd_softc *sc;
172:
173: sc = lcd_cd.cd_devs[unit];
174: sc->sc_opened = 0;
175:
176: return 0;
177: }
178:
179: int
180: lcdwrite(dev, uio, flag)
181: dev_t dev;
182: struct uio *uio;
183: int flag;
184: {
185: int error, len;
186: int i, n;
187: char buf[LCD_MAXBUFLEN];
188:
189: len = n = uio->uio_resid;
190:
191: if ((len < 0) || (len > LCD_MAXBUFLEN))
192: return EIO;
193:
194: while (n > 0) {
195: error = uiomove(buf, n, uio);
196: if (error)
197: return EIO;
198: n = uio->uio_resid;
199: }
200:
201: for(i = 0; i < len; i++) {
202: lcdput((int)buf[i]);
203: }
204:
205: return 0;
206: }
207:
208: int
209: lcdioctl(dev, cmd, addr, flag, p)
210: dev_t dev;
211: u_long cmd;
212: caddr_t addr;
213: int flag;
214: struct proc *p;
215: {
216: int val;
217:
218: /* check if the device opened with write mode */
219: switch(cmd) {
220: case LCDCLS:
221: case LCDHOME:
222: case LCDMODE:
223: case LCDDISP:
224: case LCDMOVE:
225: case LCDSEEK:
226: case LCDRESTORE:
227: if ((flag & FWRITE) == 0)
228: return EACCES;
229: break;
230: }
231:
232: switch(cmd) {
233: case LCDCLS:
234: lcdctrl(LCD_CLS);
235: break;
236:
237: case LCDHOME:
238: lcdctrl(LCD_HOME);
239: break;
240:
241: case LCDMODE:
242: val = *(int *)addr;
243: switch (val) {
244: case LCDMODE_C_LEFT:
245: case LCDMODE_C_RIGHT:
246: case LCDMODE_D_LEFT:
247: case LCDMODE_D_RIGHT:
248: lcdctrl(val);
249: break;
250: default:
251: return EINVAL;
252: }
253: break;
254:
255: case LCDDISP:
256: val = *(int *)addr;
257: if ((val & 0x7) != val)
258: return EINVAL;
259: lcdctrl(val | 0x8);
260: break;
261:
262: case LCDMOVE:
263: val = *(int *)addr;
264: switch (val) {
265: case LCDMOVE_C_LEFT:
266: case LCDMOVE_C_RIGHT:
267: case LCDMOVE_D_LEFT:
268: case LCDMOVE_D_RIGHT:
269: lcdctrl(val);
270: break;
271: default:
272: return EINVAL;
273: }
274: break;
275:
276: case LCDSEEK:
277: val = *(int *)addr & 0x7f;
278: lcdctrl(val | 0x80);
279: break;
280:
281: case LCDRESTORE:
282: greeting();
283: break;
284:
285: default:
286: return ENOTTY;
287: }
288: return 0;
289: }
290:
291: /*
292: * Internal functions
293: */
294: void
295: lcdbusywait()
296: {
297: struct pio *p1 = (struct pio *)0x4D000000;
298: int msb, s;
299:
300: s = splhigh();
301: p1->cntrl = PIO1_MODE_INPUT;
302: p1->portC = POWER | READ_BUSY | ENABLE;
303: splx(s);
304:
305: do {
306: msb = p1->portA & ENABLE;
307: delay(5);
308: } while (msb != 0);
309:
310: s = splhigh();
311: p1->portC = POWER | READ_BUSY | DISABLE;
312: splx(s);
313: }
314:
315: void
316: lcdput(cc)
317: int cc;
318: {
319: struct pio *p1 = (struct pio *)0x4D000000;
320: int s;
321:
322: lcdbusywait();
323:
324: s = splhigh();
325: p1->cntrl = PIO1_MODE_OUTPUT;
326:
327: p1->portC = POWER | WRITE_DATA | ENABLE;
328: p1->portA = cc;
329: p1->portC = POWER | WRITE_DATA | DISABLE;
330: splx(s);
331: }
332:
333: void
334: lcdctrl(cc)
335: int cc;
336: {
337: struct pio *p1 = (struct pio *)0x4D000000;
338: int s;
339:
340: lcdbusywait();
341:
342: s = splhigh();
343: p1->cntrl = PIO1_MODE_OUTPUT;
344:
345: p1->portC = POWER | WRITE_CMD | ENABLE;
346: p1->portA = cc;
347: p1->portC = POWER | WRITE_CMD | DISABLE;
348: splx(s);
349: }
350:
351: void
352: lcdshow(s)
353: const char *s;
354: {
355: int cc;
356:
357: while ((cc = *s++) != '\0')
358: lcdput(cc);
359: }
360:
361: void
362: greeting()
363: {
364: lcdctrl(LCD_INIT);
365: lcdctrl(LCD_ENTRY);
366: lcdctrl(LCD_ON);
367:
368: lcdctrl(LCD_CLS);
369: lcdctrl(LCD_HOME);
370:
371: lcdctrl(LCD_LOCATE(0, 0));
372: lcdshow(lcd_boot_message1);
373: lcdctrl(LCD_LOCATE(0, 1));
374: lcdshow(lcd_boot_message2);
375: }
CVSweb