Annotation of sys/arch/luna88k/dev/lcd.c, Revision 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