1#include <sys/cdefs.h> 2__FBSDID("$FreeBSD: releng/10.3/sys/dev/xen/console/xencons_ring.c 255040 2013-08-29 19:52:18Z gibbs $"); 3 4#include <sys/param.h> 5#include <sys/module.h> 6#include <sys/systm.h> 7#include <sys/consio.h> 8#include <sys/proc.h> 9#include <sys/uio.h> 10#include <sys/tty.h> 11#include <sys/systm.h> 12#include <sys/taskqueue.h> 13#include <sys/conf.h> 14#include <sys/kernel.h> 15#include <sys/bus.h> 16#include <sys/cons.h> 17 18#include <machine/stdarg.h> 19 20#include <xen/xen-os.h> 21#include <xen/hypervisor.h> 22#include <xen/xen_intr.h> 23#include <sys/cons.h> 24 25#include <xen/xen_intr.h> 26#include <xen/evtchn.h> 27#include <xen/interface/io/console.h> 28 29#include <dev/xen/console/xencons_ring.h> 30#include <xen/evtchn.h> 31#include <xen/interface/io/console.h> 32 33#define console_evtchn console.domU.evtchn 34xen_intr_handle_t console_handle; 35extern char *console_page; 36extern struct mtx cn_mtx; 37extern device_t xencons_dev; 38 39static inline struct xencons_interface * 40xencons_interface(void) 41{ 42 return (struct xencons_interface *)console_page; 43} 44 45 46int 47xencons_has_input(void) 48{ 49 struct xencons_interface *intf; 50 51 intf = xencons_interface(); 52 53 return (intf->in_cons != intf->in_prod); 54} 55 56 57int 58xencons_ring_send(const char *data, unsigned len) 59{ 60 struct xencons_interface *intf; 61 XENCONS_RING_IDX cons, prod; 62 int sent; 63 64 intf = xencons_interface(); 65 cons = intf->out_cons; 66 prod = intf->out_prod; 67 sent = 0; 68 69 mb(); 70 KASSERT((prod - cons) <= sizeof(intf->out), 71 ("console send ring inconsistent")); 72 73 while ((sent < len) && ((prod - cons) < sizeof(intf->out))) 74 intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++]; 75 76 wmb(); 77 intf->out_prod = prod; 78 79 xen_intr_signal(console_handle); 80 81 return sent; 82 83} 84 85 86static xencons_receiver_func *xencons_receiver; 87 88void 89xencons_handle_input(void *unused) 90{ 91 struct xencons_interface *intf; 92 XENCONS_RING_IDX cons, prod; 93 94 CN_LOCK(cn_mtx); 95 intf = xencons_interface(); 96 97 cons = intf->in_cons; 98 prod = intf->in_prod; 99 CN_UNLOCK(cn_mtx); 100 101 /* XXX needs locking */ 102 while (cons != prod) { 103 xencons_rx(intf->in + MASK_XENCONS_IDX(cons, intf->in), 1); 104 cons++; 105 } 106 107 mb(); 108 intf->in_cons = cons; 109 110 CN_LOCK(cn_mtx); 111 xen_intr_signal(console_handle); 112 113 xencons_tx(); 114 CN_UNLOCK(cn_mtx); 115} 116 117void 118xencons_ring_register_receiver(xencons_receiver_func *f) 119{ 120 xencons_receiver = f; 121} 122 123int 124xencons_ring_init(void) 125{ 126 int err; 127 128 if (!xen_start_info->console_evtchn) 129 return 0; 130 131 err = xen_intr_bind_local_port(xencons_dev, 132 xen_start_info->console_evtchn, NULL, xencons_handle_input, NULL, 133 INTR_TYPE_MISC | INTR_MPSAFE, &console_handle); 134 if (err) { 135 return err; 136 } 137 138 return 0; 139} 140 141extern void xencons_suspend(void); 142extern void xencons_resume(void); 143 144void 145xencons_suspend(void) 146{ 147 148 if (!xen_start_info->console_evtchn) 149 return; 150 151 xen_intr_unbind(&console_handle); 152} 153 154void 155xencons_resume(void) 156{ 157 158 (void)xencons_ring_init(); 159} 160 161/* 162 * Local variables: 163 * mode: C 164 * c-set-style: "BSD" 165 * c-basic-offset: 8 166 * tab-width: 4 167 * indent-tabs-mode: t 168 * End: 169 */ 170