Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_virtio_console.c
Show First 20 Lines • Show All 409 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
pci_vtcon_sock_rx(int fd __unused, enum ev_type t __unused, void *arg) | pci_vtcon_sock_rx(int fd __unused, enum ev_type t __unused, void *arg) | ||||
{ | { | ||||
struct pci_vtcon_port *port; | struct pci_vtcon_port *port; | ||||
struct pci_vtcon_sock *sock = (struct pci_vtcon_sock *)arg; | struct pci_vtcon_sock *sock = (struct pci_vtcon_sock *)arg; | ||||
struct vqueue_info *vq; | struct vqueue_info *vq; | ||||
struct vi_req req; | |||||
struct iovec iov; | struct iovec iov; | ||||
static char dummybuf[2048]; | static char dummybuf[2048]; | ||||
int len, n; | int len, n; | ||||
uint16_t idx; | |||||
port = sock->vss_port; | port = sock->vss_port; | ||||
vq = pci_vtcon_port_to_vq(port, true); | vq = pci_vtcon_port_to_vq(port, true); | ||||
if (!sock->vss_open || !port->vsp_rx_ready) { | if (!sock->vss_open || !port->vsp_rx_ready) { | ||||
len = read(sock->vss_conn_fd, dummybuf, sizeof(dummybuf)); | len = read(sock->vss_conn_fd, dummybuf, sizeof(dummybuf)); | ||||
if (len == 0) | if (len == 0) | ||||
goto close; | goto close; | ||||
return; | return; | ||||
} | } | ||||
if (!vq_has_descs(vq)) { | if (!vq_has_descs(vq)) { | ||||
len = read(sock->vss_conn_fd, dummybuf, sizeof(dummybuf)); | len = read(sock->vss_conn_fd, dummybuf, sizeof(dummybuf)); | ||||
vq_endchains(vq, 1); | vq_endchains(vq, 1); | ||||
if (len == 0) | if (len == 0) | ||||
goto close; | goto close; | ||||
return; | return; | ||||
} | } | ||||
do { | do { | ||||
n = vq_getchain(vq, &idx, &iov, 1, NULL); | n = vq_getchain(vq, &iov, 1, &req); | ||||
len = readv(sock->vss_conn_fd, &iov, n); | len = readv(sock->vss_conn_fd, &iov, n); | ||||
if (len == 0 || (len < 0 && errno == EWOULDBLOCK)) { | if (len == 0 || (len < 0 && errno == EWOULDBLOCK)) { | ||||
vq_retchains(vq, 1); | vq_retchains(vq, 1); | ||||
vq_endchains(vq, 0); | vq_endchains(vq, 0); | ||||
if (len == 0) | if (len == 0) | ||||
goto close; | goto close; | ||||
return; | return; | ||||
} | } | ||||
vq_relchain(vq, idx, len); | vq_relchain(vq, req.idx, len); | ||||
} while (vq_has_descs(vq)); | } while (vq_has_descs(vq)); | ||||
vq_endchains(vq, 1); | vq_endchains(vq, 1); | ||||
close: | close: | ||||
mevent_delete_close(sock->vss_conn_evp); | mevent_delete_close(sock->vss_conn_evp); | ||||
sock->vss_conn_fd = -1; | sock->vss_conn_fd = -1; | ||||
sock->vss_open = false; | sock->vss_open = false; | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | pci_vtcon_open_port(struct pci_vtcon_port *port, bool open) | ||||
pci_vtcon_control_send(port->vsp_sc, &event, NULL, 0); | pci_vtcon_control_send(port->vsp_sc, &event, NULL, 0); | ||||
} | } | ||||
static void | static void | ||||
pci_vtcon_control_send(struct pci_vtcon_softc *sc, | pci_vtcon_control_send(struct pci_vtcon_softc *sc, | ||||
struct pci_vtcon_control *ctrl, const void *payload, size_t len) | struct pci_vtcon_control *ctrl, const void *payload, size_t len) | ||||
{ | { | ||||
struct vqueue_info *vq; | struct vqueue_info *vq; | ||||
struct vi_req req; | |||||
struct iovec iov; | struct iovec iov; | ||||
uint16_t idx; | |||||
int n; | int n; | ||||
vq = pci_vtcon_port_to_vq(&sc->vsc_control_port, true); | vq = pci_vtcon_port_to_vq(&sc->vsc_control_port, true); | ||||
if (!vq_has_descs(vq)) | if (!vq_has_descs(vq)) | ||||
return; | return; | ||||
n = vq_getchain(vq, &idx, &iov, 1, NULL); | n = vq_getchain(vq, &iov, 1, &req); | ||||
assert(n == 1); | assert(n == 1); | ||||
memcpy(iov.iov_base, ctrl, sizeof(struct pci_vtcon_control)); | memcpy(iov.iov_base, ctrl, sizeof(struct pci_vtcon_control)); | ||||
if (payload != NULL && len > 0) | if (payload != NULL && len > 0) | ||||
memcpy(iov.iov_base + sizeof(struct pci_vtcon_control), | memcpy(iov.iov_base + sizeof(struct pci_vtcon_control), | ||||
payload, len); | payload, len); | ||||
vq_relchain(vq, idx, sizeof(struct pci_vtcon_control) + len); | vq_relchain(vq, req.idx, sizeof(struct pci_vtcon_control) + len); | ||||
vq_endchains(vq, 1); | vq_endchains(vq, 1); | ||||
} | } | ||||
static void | static void | ||||
pci_vtcon_notify_tx(void *vsc, struct vqueue_info *vq) | pci_vtcon_notify_tx(void *vsc, struct vqueue_info *vq) | ||||
{ | { | ||||
struct pci_vtcon_softc *sc; | struct pci_vtcon_softc *sc; | ||||
struct pci_vtcon_port *port; | struct pci_vtcon_port *port; | ||||
struct iovec iov[1]; | struct iovec iov[1]; | ||||
uint16_t idx, n; | struct vi_req req; | ||||
uint16_t flags[8]; | uint16_t n; | ||||
sc = vsc; | sc = vsc; | ||||
port = pci_vtcon_vq_to_port(sc, vq); | port = pci_vtcon_vq_to_port(sc, vq); | ||||
while (vq_has_descs(vq)) { | while (vq_has_descs(vq)) { | ||||
n = vq_getchain(vq, &idx, iov, 1, flags); | n = vq_getchain(vq, iov, 1, &req); | ||||
assert(n >= 1); | assert(n >= 1); | ||||
if (port != NULL) | if (port != NULL) | ||||
port->vsp_cb(port, port->vsp_arg, iov, 1); | port->vsp_cb(port, port->vsp_arg, iov, 1); | ||||
/* | /* | ||||
* Release this chain and handle more | * Release this chain and handle more | ||||
*/ | */ | ||||
vq_relchain(vq, idx, 0); | vq_relchain(vq, req.idx, 0); | ||||
} | } | ||||
vq_endchains(vq, 1); /* Generate interrupt if appropriate. */ | vq_endchains(vq, 1); /* Generate interrupt if appropriate. */ | ||||
} | } | ||||
static void | static void | ||||
pci_vtcon_notify_rx(void *vsc, struct vqueue_info *vq) | pci_vtcon_notify_rx(void *vsc, struct vqueue_info *vq) | ||||
{ | { | ||||
struct pci_vtcon_softc *sc; | struct pci_vtcon_softc *sc; | ||||
▲ Show 20 Lines • Show All 132 Lines • Show Last 20 Lines |