Deleted Added
full compact
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);