dcons.c (135799) | dcons.c (136467) |
---|---|
1/* | 1/* |
2 * Copyright (C) 2003 | 2 * Copyright (C) 2003,2004 |
3 * Hidetoshi Shimokawa. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright --- 16 unchanged lines hidden (view full) --- 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $Id: dcons.c,v 1.65 2003/10/24 03:24:55 simokawa Exp $ | 3 * Hidetoshi Shimokawa. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright --- 16 unchanged lines hidden (view full) --- 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $Id: dcons.c,v 1.65 2003/10/24 03:24:55 simokawa Exp $ |
35 * $FreeBSD: head/sys/dev/dcons/dcons.c 135799 2004-09-26 01:15:38Z simokawa $ | 35 * $FreeBSD: head/sys/dev/dcons/dcons.c 136467 2004-10-13 05:38:42Z simokawa $ |
36 */ 37 38#include <sys/param.h> | 36 */ 37 38#include <sys/param.h> |
39#if __FreeBSD_version >= 502122 40#include <sys/kdb.h> 41#include <gdb/gdb.h> 42#endif 43#include <sys/kernel.h> 44#include <sys/module.h> 45#include <sys/systm.h> 46#include <sys/types.h> 47#include <sys/conf.h> 48#include <sys/cons.h> 49#include <sys/consio.h> 50#include <sys/tty.h> 51#include <sys/malloc.h> 52#include <sys/proc.h> 53#include <sys/ucred.h> | |
54 | 39 |
55#include <machine/bus.h> 56 57#ifdef __DragonFly__ | 40#if defined(__DragonFly__) || defined(_BOOT) |
58#include "dcons.h" 59#else 60#include <dev/dcons/dcons.h> 61#endif 62 | 41#include "dcons.h" 42#else 43#include <dev/dcons/dcons.h> 44#endif 45 |
63#include <ddb/ddb.h> 64#include <sys/reboot.h> 65 66#include <sys/sysctl.h> 67 68#include "opt_ddb.h" 69#include "opt_comconsole.h" 70#include "opt_dcons.h" 71 72#ifndef DCONS_POLL_HZ 73#define DCONS_POLL_HZ 100 74#endif 75 76#ifndef DCONS_BUF_SIZE 77#define DCONS_BUF_SIZE (16*1024) 78#endif 79 80#ifndef DCONS_FORCE_CONSOLE 81#define DCONS_FORCE_CONSOLE 0 /* Mostly for FreeBSD-4/DragonFly */ 82#endif 83 84#ifndef DCONS_FORCE_GDB 85#define DCONS_FORCE_GDB 1 86#endif 87 88#if __FreeBSD_version >= 500101 89#define CONS_NODEV 1 90#if __FreeBSD_version < 502122 91static struct consdev gdbconsdev; 92#endif 93#endif 94 95static d_open_t dcons_open; 96static d_close_t dcons_close; 97#if defined(__DragonFly__) || __FreeBSD_version < 500104 98static d_ioctl_t dcons_ioctl; 99#endif 100 101static struct cdevsw dcons_cdevsw = { 102#ifdef __DragonFly__ 103#define CDEV_MAJOR 184 104 "dcons", CDEV_MAJOR, D_TTY, NULL, 0, 105 dcons_open, dcons_close, ttyread, ttywrite, dcons_ioctl, 106 ttypoll, nommap, nostrategy, nodump, nopsize, 107#elif __FreeBSD_version >= 500104 108 .d_version = D_VERSION, 109 .d_open = dcons_open, 110 .d_close = dcons_close, 111 .d_name = "dcons", 112 .d_flags = D_TTY | D_NEEDGIANT, 113#else 114#define CDEV_MAJOR 184 115 /* open */ dcons_open, 116 /* close */ dcons_close, 117 /* read */ ttyread, 118 /* write */ ttywrite, 119 /* ioctl */ dcons_ioctl, 120 /* poll */ ttypoll, 121 /* mmap */ nommap, 122 /* strategy */ nostrategy, 123 /* name */ "dcons", 124 /* major */ CDEV_MAJOR, 125 /* dump */ nodump, 126 /* psize */ nopsize, 127 /* flags */ D_TTY, 128#endif 129}; 130 131#ifndef KLD_MODULE 132static char bssbuf[DCONS_BUF_SIZE]; /* buf in bss */ 133#endif 134 135/* global data */ 136static struct dcons_global dg; 137struct dcons_global *dcons_conf; 138static int poll_hz = DCONS_POLL_HZ; 139 140SYSCTL_NODE(_kern, OID_AUTO, dcons, CTLFLAG_RD, 0, "Dumb Console"); 141SYSCTL_INT(_kern_dcons, OID_AUTO, poll_hz, CTLFLAG_RW, &poll_hz, 0, 142 "dcons polling rate"); 143 144static int drv_init = 0; 145static struct callout dcons_callout; 146struct dcons_buf *dcons_buf; /* for local dconschat */ 147 148#ifdef __DragonFly__ 149#define DEV dev_t 150#define THREAD d_thread_t 151#elif __FreeBSD_version < 500000 152#define DEV dev_t 153#define THREAD struct proc 154#else 155#define DEV struct cdev * 156#define THREAD struct thread 157#endif 158 159/* per device data */ 160static struct dcons_softc { 161 DEV dev; 162 struct dcons_ch o, i; 163 int brk_state; 164#define DC_GDB 1 165 int flags; 166} sc[DCONS_NPORT]; 167static void dcons_tty_start(struct tty *); 168static int dcons_tty_param(struct tty *, struct termios *); 169static void dcons_timeout(void *); 170static int dcons_drv_init(int); 171static int dcons_getc(struct dcons_softc *); 172static int dcons_checkc(struct dcons_softc *); 173static void dcons_putc(struct dcons_softc *, int); 174 175static cn_probe_t dcons_cnprobe; 176static cn_init_t dcons_cninit; 177static cn_getc_t dcons_cngetc; 178static cn_checkc_t dcons_cncheckc; 179static cn_putc_t dcons_cnputc; 180 181CONS_DRIVER(dcons, dcons_cnprobe, dcons_cninit, NULL, dcons_cngetc, 182 dcons_cncheckc, dcons_cnputc, NULL); 183 184#if __FreeBSD_version >= 502122 185static gdb_probe_f dcons_dbg_probe; 186static gdb_init_f dcons_dbg_init; 187static gdb_term_f dcons_dbg_term; 188static gdb_getc_f dcons_dbg_getc; 189static gdb_checkc_f dcons_dbg_checkc; 190static gdb_putc_f dcons_dbg_putc; 191 192GDB_DBGPORT(dcons, dcons_dbg_probe, dcons_dbg_init, dcons_dbg_term, 193 dcons_dbg_checkc, dcons_dbg_getc, dcons_dbg_putc); 194 195extern struct gdb_dbgport *gdb_cur; 196#endif 197 198static int 199dcons_open(DEV dev, int flag, int mode, THREAD *td) | 46int 47dcons_ischar(struct dcons_softc *dc) |
200{ | 48{ |
201 struct tty *tp; 202 int unit, error, s; | 49 u_int32_t ptr, pos, gen, next_gen; 50 struct dcons_ch *ch; |
203 | 51 |
204 unit = minor(dev); 205 if (unit != 0) 206 return (ENXIO); | 52 ch = &dc->i; |
207 | 53 |
208 tp = dev->si_tty = ttymalloc(dev->si_tty); 209 tp->t_oproc = dcons_tty_start; 210 tp->t_param = dcons_tty_param; 211 tp->t_stop = nottystop; 212 tp->t_dev = dev; | 54 ptr = ntohl(*ch->ptr); 55 gen = ptr >> DCONS_GEN_SHIFT; 56 pos = ptr & DCONS_POS_MASK; 57 if (gen == ch->gen && pos == ch->pos) 58 return (0); |
213 | 59 |
214 error = 0; 215 216 s = spltty(); 217 if ((tp->t_state & TS_ISOPEN) == 0) { 218 tp->t_state |= TS_CARR_ON; 219 ttychars(tp); 220 tp->t_iflag = TTYDEF_IFLAG; 221 tp->t_oflag = TTYDEF_OFLAG; 222 tp->t_cflag = TTYDEF_CFLAG|CLOCAL; 223 tp->t_lflag = TTYDEF_LFLAG; 224 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 225 ttsetwater(tp); 226 } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { 227 splx(s); 228 return (EBUSY); | 60 next_gen = DCONS_NEXT_GEN(ch->gen); 61 /* XXX sanity check */ 62 if ((gen != ch->gen && gen != next_gen) 63 || (gen == ch->gen && pos < ch->pos)) { 64 /* generation skipped !! */ 65 /* XXX discard */ 66 ch->gen = gen; 67 ch->pos = pos; 68 return (0); |
229 } | 69 } |
230 splx(s); | |
231 | 70 |
232#if __FreeBSD_version < 502113 233 error = (*linesw[tp->t_line].l_open)(dev, tp); 234#else 235 error = ttyld_open(tp, dev); 236#endif 237 238 return (error); | 71 return (1); |
239} 240 | 72} 73 |
241static int 242dcons_close(DEV dev, int flag, int mode, THREAD *td) 243{ 244 int unit; 245 struct tty *tp; 246 247 unit = minor(dev); 248 if (unit != 0) 249 return (ENXIO); 250 251 tp = dev->si_tty; 252 if (tp->t_state & TS_ISOPEN) { 253#if __FreeBSD_version < 502113 254 (*linesw[tp->t_line].l_close)(tp, flag); 255 ttyclose(tp); 256#else 257 ttyld_close(tp, flag); 258 tty_close(tp); 259#endif 260 } 261 262 return (0); 263} 264 265#if defined(__DragonFly__) || __FreeBSD_version < 500104 266static int 267dcons_ioctl(DEV dev, u_long cmd, caddr_t data, int flag, THREAD *td) 268{ 269 int unit; 270 struct tty *tp; 271 int error; 272 273 unit = minor(dev); 274 if (unit != 0) 275 return (ENXIO); 276 277 tp = dev->si_tty; 278 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); 279 if (error != ENOIOCTL) 280 return (error); 281 282 error = ttioctl(tp, cmd, data, flag); 283 if (error != ENOIOCTL) 284 return (error); 285 286 return (ENOTTY); 287} 288#endif 289 290static int 291dcons_tty_param(struct tty *tp, struct termios *t) 292{ 293 tp->t_ispeed = t->c_ispeed; 294 tp->t_ospeed = t->c_ospeed; 295 tp->t_cflag = t->c_cflag; 296 return 0; 297} 298 299static void 300dcons_tty_start(struct tty *tp) 301{ 302 struct dcons_softc *dc; 303 int s; 304 305 dc = (struct dcons_softc *)tp->t_dev->si_drv1; 306 s = spltty(); 307 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 308 ttwwakeup(tp); 309 return; 310 } 311 312 tp->t_state |= TS_BUSY; 313 while (tp->t_outq.c_cc != 0) 314 dcons_putc(dc, getc(&tp->t_outq)); 315 tp->t_state &= ~TS_BUSY; 316 317 ttwwakeup(tp); 318 splx(s); 319} 320 321static void 322dcons_timeout(void *v) 323{ 324 struct tty *tp; 325 struct dcons_softc *dc; 326 int i, c, polltime; 327 328 for (i = 0; i < DCONS_NPORT; i ++) { 329 dc = &sc[i]; 330 tp = dc->dev->si_tty; 331 while ((c = dcons_checkc(dc)) != -1) 332 if (tp->t_state & TS_ISOPEN) 333#if __FreeBSD_version < 502113 334 (*linesw[tp->t_line].l_rint)(c, tp); 335#else 336 ttyld_rint(tp, c); 337#endif 338 } 339 polltime = hz / poll_hz; 340 if (polltime < 1) 341 polltime = 1; 342 callout_reset(&dcons_callout, polltime, dcons_timeout, tp); 343} 344 345static void 346dcons_cnprobe(struct consdev *cp) 347{ 348#ifdef __DragonFly__ 349 cp->cn_dev = make_dev(&dcons_cdevsw, DCONS_CON, 350 UID_ROOT, GID_WHEEL, 0600, "dcons"); 351#elif __FreeBSD_version >= 501109 352 sprintf(cp->cn_name, "dcons"); 353#else 354 cp->cn_dev = makedev(CDEV_MAJOR, DCONS_CON); 355#endif 356#if DCONS_FORCE_CONSOLE 357 cp->cn_pri = CN_REMOTE; 358#else 359 cp->cn_pri = CN_NORMAL; 360#endif 361} 362 363static void 364dcons_cninit(struct consdev *cp) 365{ 366 dcons_drv_init(0); 367#if CONS_NODEV 368 cp->cn_arg 369#else 370 cp->cn_dev->si_drv1 371#endif 372 = (void *)&sc[DCONS_CON]; /* share port0 with unit0 */ 373} 374 375#if CONS_NODEV 376static int 377dcons_cngetc(struct consdev *cp) 378{ 379 return(dcons_getc((struct dcons_softc *)cp->cn_arg)); 380} 381static int 382dcons_cncheckc(struct consdev *cp) 383{ 384 return(dcons_checkc((struct dcons_softc *)cp->cn_arg)); 385} 386static void 387dcons_cnputc(struct consdev *cp, int c) 388{ 389 dcons_putc((struct dcons_softc *)cp->cn_arg, c); 390} 391#else 392static int 393dcons_cngetc(DEV dev) 394{ 395 return(dcons_getc((struct dcons_softc *)dev->si_drv1)); 396} 397static int 398dcons_cncheckc(DEV dev) 399{ 400 return(dcons_checkc((struct dcons_softc *)dev->si_drv1)); 401} 402static void 403dcons_cnputc(DEV dev, int c) 404{ 405 dcons_putc((struct dcons_softc *)dev->si_drv1, c); 406} 407#endif 408 409static int 410dcons_getc(struct dcons_softc *dc) 411{ 412 int c; 413 414 while ((c = dcons_checkc(dc)) == -1); 415 416 return (c & 0xff); 417} 418 419static int | 74int |
420dcons_checkc(struct dcons_softc *dc) 421{ 422 unsigned char c; 423 u_int32_t ptr, pos, gen, next_gen; 424 struct dcons_ch *ch; 425 426 ch = &dc->i; 427 | 75dcons_checkc(struct dcons_softc *dc) 76{ 77 unsigned char c; 78 u_int32_t ptr, pos, gen, next_gen; 79 struct dcons_ch *ch; 80 81 ch = &dc->i; 82 |
428 if (dg.dma_tag != NULL) 429 bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_POSTREAD); | |
430 ptr = ntohl(*ch->ptr); 431 gen = ptr >> DCONS_GEN_SHIFT; 432 pos = ptr & DCONS_POS_MASK; 433 if (gen == ch->gen && pos == ch->pos) 434 return (-1); 435 436 next_gen = DCONS_NEXT_GEN(ch->gen); 437 /* XXX sanity check */ --- 8 unchanged lines hidden (view full) --- 446 447 c = ch->buf[ch->pos]; 448 ch->pos ++; 449 if (ch->pos >= ch->size) { 450 ch->gen = next_gen; 451 ch->pos = 0; 452 } 453 | 83 ptr = ntohl(*ch->ptr); 84 gen = ptr >> DCONS_GEN_SHIFT; 85 pos = ptr & DCONS_POS_MASK; 86 if (gen == ch->gen && pos == ch->pos) 87 return (-1); 88 89 next_gen = DCONS_NEXT_GEN(ch->gen); 90 /* XXX sanity check */ --- 8 unchanged lines hidden (view full) --- 99 100 c = ch->buf[ch->pos]; 101 ch->pos ++; 102 if (ch->pos >= ch->size) { 103 ch->gen = next_gen; 104 ch->pos = 0; 105 } 106 |
454#if __FreeBSD_version >= 502122 455#if KDB && ALT_BREAK_TO_DEBUGGER 456 if (kdb_alt_break(c, &dc->brk_state)) { 457 if ((dc->flags & DC_GDB) != 0) { 458 if (gdb_cur == &dcons_gdb_dbgport) { 459 kdb_dbbe_select("gdb"); 460 breakpoint(); 461 } 462 } else 463 breakpoint(); 464 } 465#endif 466#else 467#if DDB && ALT_BREAK_TO_DEBUGGER 468 switch (dc->brk_state) { 469 case STATE1: 470 if (c == KEY_TILDE) 471 dc->brk_state = STATE2; 472 else 473 dc->brk_state = STATE0; 474 break; 475 case STATE2: 476 dc->brk_state = STATE0; 477 if (c == KEY_CTRLB) { 478#if DCONS_FORCE_GDB 479 if (dc->flags & DC_GDB) 480 boothowto |= RB_GDB; 481#endif 482 breakpoint(); 483 } 484 } 485 if (c == KEY_CR) 486 dc->brk_state = STATE1; 487#endif 488#endif | |
489 return (c); 490} 491 | 107 return (c); 108} 109 |
492static void | 110void |
493dcons_putc(struct dcons_softc *dc, int c) 494{ 495 struct dcons_ch *ch; 496 497 ch = &dc->o; 498 499 ch->buf[ch->pos] = c; 500 ch->pos ++; 501 if (ch->pos >= ch->size) { 502 ch->gen = DCONS_NEXT_GEN(ch->gen); 503 ch->pos = 0; 504 } 505 *ch->ptr = DCONS_MAKE_PTR(ch); | 111dcons_putc(struct dcons_softc *dc, int c) 112{ 113 struct dcons_ch *ch; 114 115 ch = &dc->o; 116 117 ch->buf[ch->pos] = c; 118 ch->pos ++; 119 if (ch->pos >= ch->size) { 120 ch->gen = DCONS_NEXT_GEN(ch->gen); 121 ch->pos = 0; 122 } 123 *ch->ptr = DCONS_MAKE_PTR(ch); |
506 if (dg.dma_tag != NULL) 507 bus_dmamap_sync(dg.dma_tag, dg.dma_map, BUS_DMASYNC_PREWRITE); | |
508} 509 510static int | 124} 125 126static int |
511dcons_init_port(int port, int offset, int size) | 127dcons_init_port(int port, int offset, int size, struct dcons_buf *buf, 128 struct dcons_softc *sc) |
512{ 513 int osize; 514 struct dcons_softc *dc; 515 516 dc = &sc[port]; 517 518 osize = size * 3 / 4; 519 520 dc->o.size = osize; 521 dc->i.size = size - osize; | 129{ 130 int osize; 131 struct dcons_softc *dc; 132 133 dc = &sc[port]; 134 135 osize = size * 3 / 4; 136 137 dc->o.size = osize; 138 dc->i.size = size - osize; |
522 dc->o.buf = (char *)dg.buf + offset; | 139 dc->o.buf = (char *)buf + offset; |
523 dc->i.buf = dc->o.buf + osize; 524 dc->o.gen = dc->i.gen = 0; 525 dc->o.pos = dc->i.pos = 0; | 140 dc->i.buf = dc->o.buf + osize; 141 dc->o.gen = dc->i.gen = 0; 142 dc->o.pos = dc->i.pos = 0; |
526 dc->o.ptr = &dg.buf->optr[port]; 527 dc->i.ptr = &dg.buf->iptr[port]; | 143 dc->o.ptr = &buf->optr[port]; 144 dc->i.ptr = &buf->iptr[port]; |
528 dc->brk_state = STATE0; | 145 dc->brk_state = STATE0; |
529 dg.buf->osize[port] = htonl(osize); 530 dg.buf->isize[port] = htonl(size - osize); 531 dg.buf->ooffset[port] = htonl(offset); 532 dg.buf->ioffset[port] = htonl(offset + osize); 533 dg.buf->optr[port] = DCONS_MAKE_PTR(&dc->o); 534 dg.buf->iptr[port] = DCONS_MAKE_PTR(&dc->i); | 146 buf->osize[port] = htonl(osize); 147 buf->isize[port] = htonl(size - osize); 148 buf->ooffset[port] = htonl(offset); 149 buf->ioffset[port] = htonl(offset + osize); 150 buf->optr[port] = DCONS_MAKE_PTR(&dc->o); 151 buf->iptr[port] = DCONS_MAKE_PTR(&dc->i); |
535 536 return(0); 537} 538 | 152 153 return(0); 154} 155 |
539static int 540dcons_drv_init(int stage) | 156int 157dcons_load_buffer(struct dcons_buf *buf, int size, struct dcons_softc *sc) |
541{ | 158{ |
542 int size, size0, offset; 543 544 if (drv_init) 545 return(drv_init); 546 547 drv_init = -1; 548 549 bzero(&dg, sizeof(dg)); 550 dcons_conf = &dg; 551 dg.cdev = &dcons_consdev; 552 dg.size = DCONS_BUF_SIZE; 553 554#ifndef KLD_MODULE 555 if (stage == 0) /* XXX or cold */ 556 /* 557 * DCONS_FORCE_CONSOLE == 1 and statically linked. 558 * called from cninit(). can't use contigmalloc yet . 559 */ 560 dg.buf = (struct dcons_buf *) bssbuf; 561 else 562#endif 563 /* 564 * DCONS_FORCE_CONSOLE == 0 or kernel module case. 565 * if the module is loaded after boot, 566 * bssbuf could be non-continuous. 567 */ 568 dg.buf = (struct dcons_buf *) contigmalloc(dg.size, 569 M_DEVBUF, 0, 0x10000, 0xffffffff, PAGE_SIZE, 0ul); 570 571 dcons_buf = dg.buf; 572 offset = DCONS_HEADER_SIZE; 573 size = (dg.size - offset); 574 size0 = size * 3 / 4; 575 576 dcons_init_port(0, offset, size0); 577 offset += size0; 578 dcons_init_port(1, offset, size - size0); 579 dg.buf->version = htonl(DCONS_VERSION); 580 dg.buf->magic = ntohl(DCONS_MAGIC); 581 582#if __FreeBSD_version < 502122 583#if DDB && DCONS_FORCE_GDB 584#if CONS_NODEV 585 gdbconsdev.cn_arg = (void *)&sc[DCONS_GDB]; 586#if __FreeBSD_version >= 501109 587 sprintf(gdbconsdev.cn_name, "dgdb"); 588#endif 589 gdb_arg = &gdbconsdev; 590#elif defined(__DragonFly__) 591 gdbdev = make_dev(&dcons_cdevsw, DCONS_GDB, 592 UID_ROOT, GID_WHEEL, 0600, "dgdb"); 593#else 594 gdbdev = makedev(CDEV_MAJOR, DCONS_GDB); 595#endif 596 gdb_getc = dcons_cngetc; 597 gdb_putc = dcons_cnputc; 598#endif 599#endif 600 drv_init = 1; 601 602 return 0; 603} 604 605 606static int 607dcons_attach_port(int port, char *name, int flags) 608{ | 159 int port, s; |
609 struct dcons_softc *dc; | 160 struct dcons_softc *dc; |
610 struct tty *tp; | |
611 | 161 |
612 dc = &sc[port]; 613 dc->flags = flags; 614 dc->dev = make_dev(&dcons_cdevsw, port, 615 UID_ROOT, GID_WHEEL, 0600, name); 616 tp = ttymalloc(NULL); | 162 if (buf->version != htonl(DCONS_VERSION)) 163 return (-1); |
617 | 164 |
618 dc->dev->si_drv1 = (void *)dc; 619 dc->dev->si_tty = tp; | 165 s = DCONS_HEADER_SIZE; 166 for (port = 0; port < DCONS_NPORT; port ++) { 167 dc = &sc[port]; 168 dc->o.size = ntohl(buf->osize[port]); 169 dc->i.size = ntohl(buf->isize[port]); 170 dc->o.buf = (char *)buf + ntohl(buf->ooffset[port]); 171 dc->i.buf = (char *)buf + ntohl(buf->ioffset[port]); 172 dc->o.gen = ntohl(buf->optr[port]) >> DCONS_GEN_SHIFT; 173 dc->i.gen = ntohl(buf->iptr[port]) >> DCONS_GEN_SHIFT; 174 dc->o.pos = ntohl(buf->optr[port]) & DCONS_POS_MASK; 175 dc->i.pos = ntohl(buf->iptr[port]) & DCONS_POS_MASK; 176 dc->o.ptr = &buf->optr[port]; 177 dc->i.ptr = &buf->iptr[port]; 178 dc->brk_state = STATE0; |
620 | 179 |
621 tp->t_oproc = dcons_tty_start; 622 tp->t_param = dcons_tty_param; 623 tp->t_stop = nottystop; 624 tp->t_dev = dc->dev; 625 626 return(0); 627} 628 629static int 630dcons_attach(void) 631{ 632 int polltime; 633 634#ifdef __DragonFly__ 635 cdevsw_add(&dcons_cdevsw, -1, 0); 636#endif 637 dcons_attach_port(DCONS_CON, "dcons", 0); 638 dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB); 639#if __FreeBSD_version < 500000 640 callout_init(&dcons_callout); 641#else 642 callout_init(&dcons_callout, 0); 643#endif 644 polltime = hz / poll_hz; 645 if (polltime < 1) 646 polltime = 1; 647 callout_reset(&dcons_callout, polltime, dcons_timeout, NULL); 648 return(0); 649} 650 651static int 652dcons_detach(int port) 653{ 654 struct tty *tp; 655 struct dcons_softc *dc; 656 657 dc = &sc[port]; 658 659 tp = dc->dev->si_tty; 660 661 if (tp->t_state & TS_ISOPEN) { 662 printf("dcons: still opened\n"); 663#if __FreeBSD_version < 502113 664 (*linesw[tp->t_line].l_close)(tp, 0); 665 tp->t_gen++; 666 ttyclose(tp); 667 ttwakeup(tp); 668 ttwwakeup(tp); 669#else 670 ttyld_close(tp, 0); 671 tty_close(tp); 672#endif | 180 s += dc->o.size + dc->i.size; |
673 } | 181 } |
674 /* XXX 675 * must wait until all device are closed. 676 */ 677#ifdef __DragonFly__ 678 tsleep((void *)dc, 0, "dcodtc", hz/4); 679#else 680 tsleep((void *)dc, PWAIT, "dcodtc", hz/4); 681#endif 682 destroy_dev(dc->dev); | |
683 | 182 |
684 return(0); 685} | 183 /* sanity check */ 184 if (s > size) 185 return (-1); |
686 | 186 |
187 buf->magic = ntohl(DCONS_MAGIC); |
|
687 | 188 |
688/* cnXXX works only for FreeBSD-5 */ 689static int 690dcons_modevent(module_t mode, int type, void *data) 691{ 692 int err = 0, ret; 693 694 switch (type) { 695 case MOD_LOAD: 696 ret = dcons_drv_init(1); 697 dcons_attach(); 698#if __FreeBSD_version >= 500000 699 if (ret == 0) { 700 dcons_cnprobe(&dcons_consdev); 701 dcons_cninit(&dcons_consdev); 702 cnadd(&dcons_consdev); 703 } 704#endif 705 break; 706 case MOD_UNLOAD: 707 printf("dcons: unload\n"); 708 callout_stop(&dcons_callout); 709#if __FreeBSD_version < 502122 710#if DDB && DCONS_FORCE_GDB 711#if CONS_NODEV 712 gdb_arg = NULL; 713#else 714 gdbdev = NULL; 715#endif 716#endif 717#endif 718#if __FreeBSD_version >= 500000 719 cnremove(&dcons_consdev); 720#endif 721 dcons_detach(DCONS_CON); 722 dcons_detach(DCONS_GDB); 723 dg.buf->magic = 0; 724 725 contigfree(dg.buf, DCONS_BUF_SIZE, M_DEVBUF); 726 727 break; 728 case MOD_SHUTDOWN: 729 dg.buf->magic = 0; 730 break; 731 default: 732 err = EOPNOTSUPP; 733 break; 734 } 735 return(err); | 189 return (0); |
736} 737 | 190} 191 |
738#if __FreeBSD_version >= 502122 739/* Debugger interface */ 740 741static int 742dcons_dbg_probe(void) | 192void 193dcons_init(struct dcons_buf *buf, int size, struct dcons_softc *sc) |
743{ | 194{ |
744 return(DCONS_FORCE_GDB); 745} | 195 int size0, size1, offset; |
746 | 196 |
747static void 748dcons_dbg_init(void) 749{ 750} | 197 offset = DCONS_HEADER_SIZE; 198 size0 = (size - offset); 199 size1 = size0 * 3 / 4; /* console port buffer */ |
751 | 200 |
752static void 753dcons_dbg_term(void) 754{ | 201 dcons_init_port(0, offset, size1, buf, sc); 202 offset += size1; 203 dcons_init_port(1, offset, size0 - size1, buf, sc); 204 buf->version = htonl(DCONS_VERSION); 205 buf->magic = ntohl(DCONS_MAGIC); |
755} | 206} |
756 757static void 758dcons_dbg_putc(int c) 759{ 760 dcons_putc(&sc[DCONS_GDB], c); 761} 762 763static int 764dcons_dbg_checkc(void) 765{ 766 return (dcons_checkc(&sc[DCONS_GDB])); 767} 768 769static int 770dcons_dbg_getc(void) 771{ 772 return (dcons_getc(&sc[DCONS_GDB])); 773} 774#endif 775 776DEV_MODULE(dcons, dcons_modevent, NULL); 777MODULE_VERSION(dcons, DCONS_VERSION); | |