123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- /*
- * Copyright (C) 2006-2011 Free Software Foundation
- *
- * This program is free software ; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation ; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY ; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the program ; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <sys/types.h>
- #include <device/tty.h>
- #include <device/cons.h>
- #include <machine/pmap.h>
- #include <machine/machspl.h>
- #include <xen/public/io/console.h>
- #include "console.h"
- #include "ring.h"
- #include "evt.h"
- /* Hypervisor part */
- decl_simple_lock_data(static, outlock);
- decl_simple_lock_data(static, inlock);
- static struct xencons_interface *console;
- static int kd_pollc;
- int kb_mode; /* XXX: actually don't care. */
- #undef hyp_console_write
- void hyp_console_write(const char *str, int len)
- {
- hyp_console_io (CONSOLEIO_write, len, kvtolin(str));
- }
- int hypputc(int c)
- {
- if (!console) {
- char d = c;
- hyp_console_io(CONSOLEIO_write, 1, kvtolin(&d));
- } else {
- spl_t spl = splhigh();
- static int complain;
- simple_lock(&outlock);
- while (hyp_ring_smash(console->out, console->out_prod, console->out_cons)) {
- if (!complain) {
- complain = 1;
- hyp_console_put("ring smash\n");
- }
- /* TODO: are we allowed to sleep in putc? */
- hyp_yield();
- }
- hyp_ring_cell(console->out, console->out_prod) = c;
- wmb();
- console->out_prod++;
- hyp_event_channel_send(boot_info.console_evtchn);
- simple_unlock(&outlock);
- splx(spl);
- }
- return 0;
- }
- int hypcnputc(dev_t dev, int c)
- {
- return hypputc(c);
- }
- /* get char by polling, used by debugger */
- int hypcngetc(dev_t dev, int wait)
- {
- int ret;
- if (wait)
- while (console->in_prod == console->in_cons)
- hyp_yield();
- else
- if (console->in_prod == console->in_cons)
- return -1;
- ret = hyp_ring_cell(console->in, console->in_cons);
- mb();
- console->in_cons++;
- hyp_event_channel_send(boot_info.console_evtchn);
- return ret;
- }
- void cnpollc(boolean_t on) {
- if (on) {
- kd_pollc++;
- } else {
- --kd_pollc;
- }
- }
- void kd_setleds1(u_char val)
- {
- /* Can't do this. */
- }
- /* Mach part */
- struct tty hypcn_tty;
- static void hypcnintr(int unit, spl_t spl, void *ret_addr, void *regs) {
- struct tty *tp = &hypcn_tty;
- if (kd_pollc)
- return;
- simple_lock(&inlock);
- while (console->in_prod != console->in_cons) {
- int c = hyp_ring_cell(console->in, console->in_cons);
- mb();
- console->in_cons++;
- #if MACH_KDB
- if (c == (char)0xA3) {
- printf("pound pressed\n");
- kdb_kintr();
- continue;
- }
- #endif /* MACH_KDB */
- if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)))
- (*linesw[tp->t_line].l_rint)(c, tp);
- }
- hyp_event_channel_send(boot_info.console_evtchn);
- simple_unlock(&inlock);
- }
- int hypcnread(dev_t dev, io_req_t ior)
- {
- struct tty *tp = &hypcn_tty;
- tp->t_state |= TS_CARR_ON;
- return char_read(tp, ior);
- }
- int hypcnwrite(dev_t dev, io_req_t ior)
- {
- return char_write(&hypcn_tty, ior);
- }
- void hypcnstart(struct tty *tp)
- {
- spl_t o_pri;
- int ch;
- unsigned char c;
- if (tp->t_state & TS_TTSTOP)
- return;
- while (1) {
- tp->t_state &= ~TS_BUSY;
- if (tp->t_state & TS_TTSTOP)
- break;
- if ((tp->t_outq.c_cc <= 0) || (ch = getc(&tp->t_outq)) == -1)
- break;
- c = ch;
- o_pri = splsoftclock();
- hypputc(c);
- splx(o_pri);
- }
- if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
- tt_write_wakeup(tp);
- }
- }
- void hypcnstop()
- {
- }
- io_return_t hypcngetstat(dev_t dev, int flavor, int *data, unsigned int *count)
- {
- return tty_get_status(&hypcn_tty, flavor, data, count);
- }
- io_return_t hypcnsetstat(dev_t dev, int flavor, int *data, unsigned int count)
- {
- return tty_set_status(&hypcn_tty, flavor, data, count);
- }
- int hypcnportdeath(dev_t dev, mach_port_t port)
- {
- return tty_portdeath(&hypcn_tty, (ipc_port_t) port);
- }
- int hypcnopen(dev_t dev, int flag, io_req_t ior)
- {
- struct tty *tp = &hypcn_tty;
- spl_t o_pri;
- o_pri = spltty();
- simple_lock(&tp->t_lock);
- if (!(tp->t_state & (TS_ISOPEN|TS_WOPEN))) {
- /* XXX ttychars allocates memory */
- simple_unlock(&tp->t_lock);
- ttychars(tp);
- simple_lock(&tp->t_lock);
- tp->t_oproc = hypcnstart;
- tp->t_stop = hypcnstop;
- tp->t_ospeed = tp->t_ispeed = B9600;
- tp->t_flags = ODDP|EVENP|ECHO|CRMOD|XTABS;
- }
- tp->t_state |= TS_CARR_ON;
- simple_unlock(&tp->t_lock);
- splx(o_pri);
- return (char_open(dev, tp, flag, ior));
- }
- void hypcnclose(dev_t dev, int flag)
- {
- struct tty *tp = &hypcn_tty;
- spl_t s = spltty();
- simple_lock(&tp->t_lock);
- ttyclose(tp);
- simple_unlock(&tp->t_lock);
- splx(s);
- }
- int hypcnprobe(struct consdev *cp)
- {
- cp->cn_dev = makedev(0, 0);
- cp->cn_pri = CN_INTERNAL;
- return 0;
- }
- int hypcninit(struct consdev *cp)
- {
- if (console)
- return 0;
- simple_lock_init(&outlock);
- simple_lock_init(&inlock);
- console = (void*) mfn_to_kv(boot_info.console_mfn);
- #ifdef MACH_PV_PAGETABLES
- pmap_set_page_readwrite(console);
- #endif /* MACH_PV_PAGETABLES */
- hyp_evt_handler(boot_info.console_evtchn, hypcnintr, 0, SPL6);
- return 0;
- }
|