1 /* $NetBSD: hd44780_subr.c,v 1.5 2005/02/04 05:58:44 joff Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Dennis I. Chernoivanov 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 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * Subroutines for Hitachi HD44870 style displays 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: hd44780_subr.c,v 1.5 2005/02/04 05:58:44 joff Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/conf.h> 40 #include <sys/kernel.h> 41 #include <sys/malloc.h> 42 #include <sys/types.h> 43 #include <sys/ioccom.h> 44 45 #include <machine/autoconf.h> 46 #include <machine/intr.h> 47 #include <machine/bus.h> 48 49 #include <uvm/uvm_extern.h> 50 51 #include <dev/wscons/wsdisplayvar.h> 52 #include <dev/wscons/wsconsio.h> 53 #include <dev/wscons/wscons_callbacks.h> 54 55 #include <dev/ic/hd44780reg.h> 56 #include <dev/ic/hd44780var.h> 57 58 #define COORD_TO_IDX(x, y) ((y) * sc->sc_cols + (x)) 59 #define COORD_TO_DADDR(x, y) ((y) * HD_ROW2_ADDR + (x)) 60 #define IDX_TO_ROW(idx) (((idx) >= sc->sc_cols) ? 1 : 0) 61 #define IDX_TO_COL(idx) (((idx) >= sc->sc_cols) ? \ 62 ((idx) - sc->sc_cols) : (idx)) 63 #define IDX_TO_DDADDR(idx) ((IDX_TO_ROW((idx)) == 1) ? \ 64 (HD_ROW2_ADDR + IDX_TO_COL((idx))) : \ 65 (IDX_TO_COL((idx)))) 66 #define DADDR_TO_ROW(daddr) (((daddr) >= HD_ROW2_ADDR) ? 1 : 0) 67 #define DADDR_TO_COL(daddr) ((DADDR_TO_ROW((daddr)) == 1) ? \ 68 ((daddr) - HD_ROW2_ADDR) : (daddr)) 69 70 static void hlcd_cursor(void *, int, int, int); 71 static int hlcd_mapchar(void *, int, unsigned int *); 72 static void hlcd_putchar(void *, int, int, u_int, long); 73 static void hlcd_copycols(void *, int, int, int,int); 74 static void hlcd_erasecols(void *, int, int, int, long); 75 static void hlcd_copyrows(void *, int, int, int); 76 static void hlcd_eraserows(void *, int, int, long); 77 static int hlcd_allocattr(void *, int, int, int, long *); 78 static void hlcd_updatechar(struct hd44780_chip *, int, int); 79 static void hlcd_redraw(void *); 80 81 const struct wsdisplay_emulops hlcd_emulops = { 82 hlcd_cursor, 83 hlcd_mapchar, 84 hlcd_putchar, 85 hlcd_copycols, 86 hlcd_erasecols, 87 hlcd_copyrows, 88 hlcd_eraserows, 89 hlcd_allocattr 90 }; 91 92 static int hlcd_ioctl(void *, u_long, caddr_t, int, struct proc *); 93 static paddr_t hlcd_mmap(void *, off_t, int); 94 static int hlcd_alloc_screen(void *, const struct wsscreen_descr *, 95 void **, int *, int *, long *); 96 static void hlcd_free_screen(void *, void *); 97 static int hlcd_show_screen(void *, void *, int, 98 void (*) (void *, int, int), void *); 99 100 const struct wsdisplay_accessops hlcd_accessops = { 101 hlcd_ioctl, 102 hlcd_mmap, 103 hlcd_alloc_screen, 104 hlcd_free_screen, 105 hlcd_show_screen, 106 0 /* load_font */ 107 }; 108 109 static void 110 hlcd_cursor(id, on, row, col) 111 void *id; 112 int on, row, col; 113 { 114 struct hlcd_screen *hdscr = id; 115 116 hdscr->hlcd_curon = on; 117 hdscr->hlcd_curx = col; 118 hdscr->hlcd_cury = row; 119 } 120 121 static int 122 hlcd_mapchar(id, uni, index) 123 void *id; 124 int uni; 125 unsigned int *index; 126 { 127 if (uni < 256) { 128 *index = uni; 129 return (5); 130 } 131 *index = ' '; 132 return (0); 133 } 134 135 static void 136 hlcd_putchar(id, row, col, c, attr) 137 void *id; 138 int row, col; 139 u_int c; 140 long attr; 141 { 142 struct hlcd_screen *hdscr = id; 143 144 c &= 0xff; 145 if (row > 0 && (hdscr->hlcd_sc->sc_flags & HD_MULTILINE)) 146 hdscr->image[hdscr->hlcd_sc->sc_cols * row + col] = c; 147 else 148 hdscr->image[col] = c; 149 } 150 151 /* 152 * copies columns inside a row. 153 */ 154 static void 155 hlcd_copycols(id, row, srccol, dstcol, ncols) 156 void *id; 157 int row, srccol, dstcol, ncols; 158 { 159 struct hlcd_screen *hdscr = id; 160 161 if ((dstcol + ncols - 1) > hdscr->hlcd_sc->sc_cols) 162 ncols = hdscr->hlcd_sc->sc_cols - srccol; 163 164 if (row > 0 && (hdscr->hlcd_sc->sc_flags & HD_MULTILINE)) 165 bcopy(&hdscr->image[hdscr->hlcd_sc->sc_cols * row + srccol], 166 &hdscr->image[hdscr->hlcd_sc->sc_cols * row + dstcol], ncols); 167 else 168 bcopy(&hdscr->image[srccol], &hdscr->image[dstcol], ncols); 169 } 170 171 172 /* 173 * Erases a bunch of chars inside one row. 174 */ 175 static void 176 hlcd_erasecols(id, row, startcol, ncols, fillattr) 177 void *id; 178 int row, startcol, ncols; 179 long fillattr; 180 { 181 struct hlcd_screen *hdscr = id; 182 183 if ((startcol + ncols) > hdscr->hlcd_sc->sc_cols) 184 ncols = hdscr->hlcd_sc->sc_cols - startcol; 185 186 if (row > 0 && (hdscr->hlcd_sc->sc_flags & HD_MULTILINE)) 187 memset(&hdscr->image[hdscr->hlcd_sc->sc_cols * row + startcol], 188 ' ', ncols); 189 else 190 memset(&hdscr->image[startcol], ' ', ncols); 191 } 192 193 194 static void 195 hlcd_copyrows(id, srcrow, dstrow, nrows) 196 void *id; 197 int srcrow, dstrow, nrows; 198 { 199 struct hlcd_screen *hdscr = id; 200 int ncols = hdscr->hlcd_sc->sc_cols; 201 202 if (!(hdscr->hlcd_sc->sc_flags & HD_MULTILINE)) 203 return; 204 bcopy(&hdscr->image[srcrow * ncols], &hdscr->image[dstrow * ncols], 205 nrows * ncols); 206 } 207 208 static void 209 hlcd_eraserows(id, startrow, nrows, fillattr) 210 void *id; 211 int startrow, nrows; 212 long fillattr; 213 { 214 struct hlcd_screen *hdscr = id; 215 int ncols = hdscr->hlcd_sc->sc_cols; 216 217 memset(&hdscr->image[startrow * ncols], ' ', ncols * nrows); 218 } 219 220 221 static int 222 hlcd_allocattr(id, fg, bg, flags, attrp) 223 void *id; 224 int fg, bg, flags; 225 long *attrp; 226 { 227 *attrp = flags; 228 return 0; 229 } 230 231 static int 232 hlcd_ioctl(v, cmd, data, flag, p) 233 void *v; 234 u_long cmd; 235 caddr_t data; 236 int flag; 237 struct proc *p; 238 { 239 240 switch (cmd) { 241 case WSDISPLAYIO_GTYPE: 242 *(u_int *)data = WSDISPLAY_TYPE_HDLCD; 243 break; 244 245 case WSDISPLAYIO_SVIDEO: 246 break; 247 248 case WSDISPLAYIO_GVIDEO: 249 *(u_int *)data = WSDISPLAYIO_VIDEO_ON; 250 break; 251 252 default: 253 return EPASSTHROUGH; 254 } 255 return 0; 256 } 257 258 static paddr_t 259 hlcd_mmap(v, offset, prot) 260 void *v; 261 off_t offset; 262 int prot; 263 { 264 return -1; 265 } 266 267 static int 268 hlcd_alloc_screen(v, type, cookiep, curxp, curyp, defattrp) 269 void *v; 270 const struct wsscreen_descr *type; 271 void **cookiep; 272 int *curxp, *curyp; 273 long *defattrp; 274 { 275 struct hlcd_screen *hdscr = v, *new; 276 277 new = *cookiep = malloc(sizeof(struct hlcd_screen), M_DEVBUF, M_WAITOK); 278 bzero(*cookiep, sizeof(struct hlcd_screen)); 279 new->hlcd_sc = hdscr->hlcd_sc; 280 new->image = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK); 281 memset(new->image, ' ', PAGE_SIZE); 282 *curxp = *curyp = *defattrp = 0; 283 return 0; 284 } 285 286 static void 287 hlcd_free_screen(v, cookie) 288 void *v, *cookie; 289 { 290 } 291 292 static int 293 hlcd_show_screen(v, cookie, waitok, cb, cbarg) 294 void *v, *cookie, *cbarg; 295 int waitok; 296 void (*cb)(void *, int, int); 297 { 298 struct hlcd_screen *hdscr = v; 299 300 hdscr->hlcd_sc->sc_curscr = cookie; 301 callout_schedule(&hdscr->hlcd_sc->redraw, 1); 302 return (0); 303 } 304 305 static void 306 hlcd_updatechar(sc, daddr, c) 307 struct hd44780_chip *sc; 308 int daddr, c; 309 { 310 int curdaddr; 311 312 curdaddr = COORD_TO_DADDR(sc->sc_screen.hlcd_curx, 313 sc->sc_screen.hlcd_cury); 314 if (daddr != curdaddr) 315 hd44780_ir_write(sc, cmd_ddramset(daddr)); 316 317 hd44780_dr_write(sc, c); 318 319 daddr++; 320 sc->sc_screen.hlcd_curx = DADDR_TO_COL(daddr); 321 sc->sc_screen.hlcd_cury = DADDR_TO_ROW(daddr); 322 } 323 324 static void 325 hlcd_redraw(arg) 326 void *arg; 327 { 328 struct hd44780_chip *sc = arg; 329 int len, crsridx, startidx, x, y; 330 u_char *img, *curimg; 331 332 if (sc->sc_curscr == NULL) 333 return; 334 335 if (sc->sc_flags & HD_MULTILINE) 336 len = 2 * sc->sc_cols; 337 else 338 len = sc->sc_cols; 339 340 img = sc->sc_screen.image; 341 curimg = sc->sc_curscr->image; 342 startidx = crsridx = 343 COORD_TO_IDX(sc->sc_screen.hlcd_curx, sc->sc_screen.hlcd_cury); 344 do { 345 if (img[crsridx] != curimg[crsridx]) { 346 hlcd_updatechar(sc, IDX_TO_DDADDR(crsridx), 347 curimg[crsridx]); 348 img[crsridx] = curimg[crsridx]; 349 } 350 crsridx++; 351 if (crsridx == len) 352 crsridx = 0; 353 } while (crsridx != startidx); 354 355 if (sc->sc_screen.hlcd_curx != sc->sc_curscr->hlcd_curx || 356 sc->sc_screen.hlcd_cury != sc->sc_curscr->hlcd_cury) { 357 x = sc->sc_screen.hlcd_curx = sc->sc_curscr->hlcd_curx; 358 y = sc->sc_screen.hlcd_cury = sc->sc_curscr->hlcd_cury; 359 hd44780_ir_write(sc, cmd_ddramset(COORD_TO_DADDR(x, y))); 360 } 361 362 if (sc->sc_screen.hlcd_curon != sc->sc_curscr->hlcd_curon) { 363 sc->sc_screen.hlcd_curon = sc->sc_curscr->hlcd_curon; 364 if (sc->sc_screen.hlcd_curon) 365 hd44780_ir_write(sc, cmd_dispctl(1, 1, 1)); 366 else 367 hd44780_ir_write(sc, cmd_dispctl(1, 0, 0)); 368 } 369 370 callout_schedule(&sc->redraw, 1); 371 } 372 373 374 /* 375 * Finish device attach. sc_writereg, sc_readreg and sc_flags must be properly 376 * initialized prior to this call. 377 */ 378 void 379 hd44780_attach_subr(sc) 380 struct hd44780_chip *sc; 381 { 382 int err = 0; 383 /* Putc/getc are supposed to be set by platform-dependent code. */ 384 if ((sc->sc_writereg == NULL) || (sc->sc_readreg == NULL)) 385 sc->sc_dev_ok = 0; 386 387 /* Make sure that HD_MAX_CHARS is enough. */ 388 if ((sc->sc_flags & HD_MULTILINE) && (2 * sc->sc_cols > HD_MAX_CHARS)) 389 sc->sc_dev_ok = 0; 390 else if (sc->sc_cols > HD_MAX_CHARS) 391 sc->sc_dev_ok = 0; 392 393 if (sc->sc_dev_ok) { 394 if ((sc->sc_flags & HD_UP) == 0) 395 err = hd44780_init(sc); 396 if (err != 0) 397 printf("%s: LCD not responding or unconnected\n", sc->sc_dev->dv_xname); 398 399 } 400 401 sc->sc_screen.hlcd_sc = sc; 402 403 sc->sc_screen.image = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK); 404 memset(sc->sc_screen.image, ' ', PAGE_SIZE); 405 sc->sc_curscr = NULL; 406 callout_init(&sc->redraw); 407 callout_setfunc(&sc->redraw, hlcd_redraw, sc); 408 } 409 410 /* 411 * Initialize 4-bit or 8-bit connected device. 412 */ 413 int 414 hd44780_init(sc) 415 struct hd44780_chip *sc; 416 { 417 u_int8_t cmd, dat; 418 419 sc->sc_flags &= ~(HD_TIMEDOUT|HD_UP); 420 sc->sc_dev_ok = 1; 421 cmd = cmd_init(sc->sc_flags & HD_8BIT); 422 hd44780_ir_write(sc, cmd); 423 delay(HD_TIMEOUT_LONG); 424 hd44780_ir_write(sc, cmd); 425 hd44780_ir_write(sc, cmd); 426 427 cmd = cmd_funcset( 428 sc->sc_flags & HD_8BIT, 429 sc->sc_flags & HD_MULTILINE, 430 sc->sc_flags & HD_BIGFONT); 431 432 if ((sc->sc_flags & HD_8BIT) == 0) 433 hd44780_ir_write(sc, cmd); 434 435 sc->sc_flags |= HD_UP; 436 437 hd44780_ir_write(sc, cmd); 438 hd44780_ir_write(sc, cmd_dispctl(0, 0, 0)); 439 hd44780_ir_write(sc, cmd_clear()); 440 hd44780_ir_write(sc, cmd_modset(1, 0)); 441 442 if (sc->sc_flags & HD_TIMEDOUT) { 443 sc->sc_flags &= ~HD_UP; 444 return EIO; 445 } 446 447 /* Turn display on and clear it. */ 448 hd44780_ir_write(sc, cmd_clear()); 449 hd44780_ir_write(sc, cmd_dispctl(1, 0, 0)); 450 451 /* Attempt a simple probe for presence */ 452 hd44780_ir_write(sc, cmd_ddramset(0x5)); 453 hd44780_ir_write(sc, cmd_shift(0, 1)); 454 hd44780_busy_wait(sc); 455 if ((dat = hd44780_ir_read(sc) & 0x7f) != 0x6) { 456 sc->sc_dev_ok = 0; 457 sc->sc_flags &= ~HD_UP; 458 return EIO; 459 } 460 hd44780_ir_write(sc, cmd_ddramset(0)); 461 462 return 0; 463 } 464 465 /* 466 * Standard hd44780 ioctl() functions. 467 */ 468 int 469 hd44780_ioctl_subr(sc, cmd, data) 470 struct hd44780_chip *sc; 471 u_long cmd; 472 caddr_t data; 473 { 474 u_int8_t tmp; 475 int error = 0; 476 477 #define hd44780_io() ((struct hd44780_io *)data) 478 #define hd44780_info() ((struct hd44780_info*)data) 479 #define hd44780_ctrl() ((struct hd44780_dispctl*)data) 480 481 switch (cmd) { 482 /* Clear the LCD. */ 483 case HLCD_CLEAR: 484 hd44780_ir_write(sc, cmd_clear()); 485 break; 486 487 /* Move the cursor one position to the left. */ 488 case HLCD_CURSOR_LEFT: 489 hd44780_ir_write(sc, cmd_shift(0, 0)); 490 break; 491 492 /* Move the cursor one position to the right. */ 493 case HLCD_CURSOR_RIGHT: 494 hd44780_ir_write(sc, cmd_shift(0, 1)); 495 break; 496 497 /* Control the LCD. */ 498 case HLCD_DISPCTL: 499 hd44780_ir_write(sc, cmd_dispctl( 500 hd44780_ctrl()->display_on, 501 hd44780_ctrl()->cursor_on, 502 hd44780_ctrl()->blink_on)); 503 break; 504 505 /* Get LCD configuration. */ 506 case HLCD_GET_INFO: 507 hd44780_info()->lines 508 = (sc->sc_flags & HD_MULTILINE) ? 2 : 1; 509 hd44780_info()->phys_rows = sc->sc_cols; 510 hd44780_info()->virt_rows = sc->sc_vcols; 511 hd44780_info()->is_wide = sc->sc_flags & HD_8BIT; 512 hd44780_info()->is_bigfont = sc->sc_flags & HD_BIGFONT; 513 hd44780_info()->kp_present = sc->sc_flags & HD_KEYPAD; 514 break; 515 516 517 /* Reset the LCD. */ 518 case HLCD_RESET: 519 error = hd44780_init(sc); 520 break; 521 522 /* Get the current cursor position. */ 523 case HLCD_GET_CURSOR_POS: 524 hd44780_io()->dat = (hd44780_ir_read(sc) & 0x7f); 525 break; 526 527 /* Set the cursor position. */ 528 case HLCD_SET_CURSOR_POS: 529 hd44780_ir_write(sc, cmd_ddramset(hd44780_io()->dat)); 530 break; 531 532 /* Get the value at the current cursor position. */ 533 case HLCD_GETC: 534 tmp = (hd44780_ir_read(sc) & 0x7f); 535 hd44780_ir_write(sc, cmd_ddramset(tmp)); 536 hd44780_io()->dat = hd44780_dr_read(sc); 537 break; 538 539 /* Set the character at the cursor position + advance cursor. */ 540 case HLCD_PUTC: 541 hd44780_dr_write(sc, hd44780_io()->dat); 542 break; 543 544 /* Shift display left. */ 545 case HLCD_SHIFT_LEFT: 546 hd44780_ir_write(sc, cmd_shift(1, 0)); 547 break; 548 549 /* Shift display right. */ 550 case HLCD_SHIFT_RIGHT: 551 hd44780_ir_write(sc, cmd_shift(1, 1)); 552 break; 553 554 /* Return home. */ 555 case HLCD_HOME: 556 hd44780_ir_write(sc, cmd_rethome()); 557 break; 558 559 /* Write a string to the LCD virtual area. */ 560 case HLCD_WRITE: 561 error = hd44780_ddram_io(sc, hd44780_io(), HD_DDRAM_WRITE); 562 break; 563 564 /* Read LCD virtual area. */ 565 case HLCD_READ: 566 error = hd44780_ddram_io(sc, hd44780_io(), HD_DDRAM_READ); 567 break; 568 569 /* Write to the LCD visible area. */ 570 case HLCD_REDRAW: 571 hd44780_ddram_redraw(sc, hd44780_io()); 572 break; 573 574 /* Write raw instruction. */ 575 case HLCD_WRITE_INST: 576 hd44780_ir_write(sc, hd44780_io()->dat); 577 break; 578 579 /* Write raw data. */ 580 case HLCD_WRITE_DATA: 581 hd44780_dr_write(sc, hd44780_io()->dat); 582 break; 583 584 default: 585 error = EINVAL; 586 } 587 588 if (sc->sc_flags & HD_TIMEDOUT) 589 error = EIO; 590 591 return error; 592 } 593 594 /* 595 * Read/write particular area of the LCD screen. 596 */ 597 int 598 hd44780_ddram_io(sc, io, dir) 599 struct hd44780_chip *sc; 600 struct hd44780_io *io; 601 u_char dir; 602 { 603 u_int8_t hi; 604 u_int8_t addr; 605 606 int error = 0; 607 u_int8_t i = 0; 608 609 if (io->dat < sc->sc_vcols) { 610 hi = HD_ROW1_ADDR + sc->sc_vcols; 611 addr = HD_ROW1_ADDR + io->dat; 612 for (; (addr < hi) && (i < io->len); addr++, i++) { 613 hd44780_ir_write(sc, cmd_ddramset(addr)); 614 if (dir == HD_DDRAM_READ) 615 io->buf[i] = hd44780_dr_read(sc); 616 else 617 hd44780_dr_write(sc, io->buf[i]); 618 } 619 } 620 if (io->dat < 2 * sc->sc_vcols) { 621 hi = HD_ROW2_ADDR + sc->sc_vcols; 622 if (io->dat >= sc->sc_vcols) 623 addr = HD_ROW2_ADDR + io->dat - sc->sc_vcols; 624 else 625 addr = HD_ROW2_ADDR; 626 for (; (addr < hi) && (i < io->len); addr++, i++) { 627 hd44780_ir_write(sc, cmd_ddramset(addr)); 628 if (dir == HD_DDRAM_READ) 629 io->buf[i] = hd44780_dr_read(sc); 630 else 631 hd44780_dr_write(sc, io->buf[i]); 632 } 633 if (i < io->len) 634 io->len = i; 635 } else { 636 error = EINVAL; 637 } 638 return error; 639 } 640 641 /* 642 * Write to the visible area of the display. 643 */ 644 void 645 hd44780_ddram_redraw(sc, io) 646 struct hd44780_chip *sc; 647 struct hd44780_io *io; 648 { 649 u_int8_t i; 650 651 hd44780_ir_write(sc, cmd_clear()); 652 hd44780_ir_write(sc, cmd_rethome()); 653 for (i = 0; (i < io->len) && (i < sc->sc_cols); i++) { 654 hd44780_dr_write(sc, io->buf[i]); 655 } 656 hd44780_ir_write(sc, cmd_ddramset(HD_ROW2_ADDR)); 657 for (; (i < io->len); i++) 658 hd44780_dr_write(sc, io->buf[i]); 659 } 660 661 void 662 hd44780_busy_wait(sc) 663 struct hd44780_chip *sc; 664 { 665 int nloops = 100; 666 667 if (sc->sc_flags & HD_TIMEDOUT) 668 return; 669 670 while(nloops-- && (hd44780_ir_read(sc) & BUSY_FLAG) == BUSY_FLAG); 671 672 if (nloops == 0) { 673 sc->sc_flags |= HD_TIMEDOUT; 674 sc->sc_dev_ok = 0; 675 } 676 } 677 678 #if defined(HD44780_STD_WIDE) 679 /* 680 * Standard 8-bit version of 'sc_writereg' (8-bit port, 8-bit access) 681 */ 682 void 683 hd44780_writereg(sc, reg, cmd) 684 struct hd44780_chip *sc; 685 u_int32_t reg; 686 u_int8_t cmd; 687 { 688 bus_space_tag_t iot = sc->sc_iot; 689 bus_space_handle_t ioh; 690 691 if (sc->sc_dev_ok == 0) 692 return; 693 694 if (reg == 0) 695 ioh = sc->sc_ioir; 696 else 697 ioh = sc->sc_iodr; 698 699 bus_space_write_1(iot, ioh, 0x00, cmd); 700 delay(HD_TIMEOUT_NORMAL); 701 } 702 703 /* 704 * Standard 8-bit version of 'sc_readreg' (8-bit port, 8-bit access) 705 */ 706 u_int8_t 707 hd44780_readreg(sc, reg) 708 struct hd44780_chip *sc; 709 u_int32_t reg; 710 { 711 bus_space_tag_t iot = sc->sc_iot; 712 bus_space_handle_t ioh; 713 714 if (sc->sc_dev_ok == 0) 715 return; 716 717 if (reg == 0) 718 ioh = sc->sc_ioir; 719 else 720 ioh = sc->sc_iodr; 721 722 delay(HD_TIMEOUT_NORMAL); 723 return bus_space_read_1(iot, ioh, 0x00); 724 } 725 #elif defined(HD44780_STD_SHORT) 726 /* 727 * Standard 4-bit version of 'sc_writereg' (4-bit port, 8-bit access) 728 */ 729 void 730 hd44780_writereg(sc, reg, cmd) 731 struct hd44780_chip *sc; 732 u_int32_t reg; 733 u_int8_t cmd; 734 { 735 bus_space_tag_t iot = sc->sc_iot; 736 bus_space_handle_t ioh; 737 738 if (sc->sc_dev_ok == 0) 739 return; 740 741 if (reg == 0) 742 ioh = sc->sc_ioir; 743 else 744 ioh = sc->sc_iodr; 745 746 bus_space_write_1(iot, ioh, 0x00, hi_bits(cmd)); 747 if (sc->sc_flags & HD_UP) 748 bus_space_write_1(iot, ioh, 0x00, lo_bits(cmd)); 749 delay(HD_TIMEOUT_NORMAL); 750 } 751 752 /* 753 * Standard 4-bit version of 'sc_readreg' (4-bit port, 8-bit access) 754 */ 755 u_int8_t 756 hd44780_readreg(sc, reg) 757 struct hd44780_chip *sc; 758 u_int32_t reg; 759 { 760 bus_space_tag_t iot = sc->sc_iot; 761 bus_space_handle_t ioh; 762 u_int8_t rd, dat; 763 764 if (sc->sc_dev_ok == 0) 765 return; 766 767 if (reg == 0) 768 ioh = sc->sc_ioir; 769 else 770 ioh = sc->sc_iodr; 771 772 rd = bus_space_read_1(iot, ioh, 0x00); 773 dat = (rd & 0x0f) << 4; 774 rd = bus_space_read_1(iot, ioh, 0x00); 775 return (dat | (rd & 0x0f)); 776 } 777 #endif 778