1 /******************************************************************************
2 * Copyright (c) 2016 IBM Corporation
3 * All rights reserved.
4 * This program and the accompanying materials
5 * are made available under the terms of the BSD License
6 * which accompanies this distribution, and is available at
7 * http://www.opensource.org/licenses/bsd-license.php
8 *
9 * Contributors:
10 * IBM Corporation - initial implementation
11 *****************************************************************************/
12
13 /*
14 * Virtio serial device definitions.
15 * See Virtio 1.0 - 5.3 Console Device, for details
16 */
17 #include <stdio.h>
18 #include <string.h>
19 #include <cpu.h>
20 #include <helpers.h>
21 #include <byteorder.h>
22 #include "virtio.h"
23 #include "virtio-serial.h"
24 #include "virtio-internal.h"
25
26 #define DRIVER_FEATURE_SUPPORT VIRTIO_F_VERSION_1
27 #define RX_ELEM_SIZE 4
28 #define RX_NUM_ELEMS 128
29
30 #define RX_Q 0
31 #define TX_Q 1
32
33 static struct vqs vq_rx;
34 static struct vqs vq_tx;
35 static uint16_t last_rx_idx; /* Last index in RX "used" ring */
36
virtio_serial_init(struct virtio_device * dev)37 int virtio_serial_init(struct virtio_device *dev)
38 {
39 struct vring_avail *vq_avail;
40 int status = VIRTIO_STAT_ACKNOWLEDGE;
41 int i;
42
43 /* Reset device */
44 virtio_reset_device(dev);
45
46 /* Acknowledge device. */
47 virtio_set_status(dev, status);
48
49 /* Tell HV that we know how to drive the device. */
50 status |= VIRTIO_STAT_DRIVER;
51 virtio_set_status(dev, status);
52
53 if (dev->is_modern) {
54 /* Negotiate features and sets FEATURES_OK if successful */
55 if (virtio_negotiate_guest_features(dev, DRIVER_FEATURE_SUPPORT))
56 goto dev_error;
57
58 virtio_get_status(dev, &status);
59 }
60
61 if (virtio_queue_init_vq(dev, &vq_rx, RX_Q))
62 goto dev_error;
63
64 /* Allocate memory for multiple receive buffers */
65 vq_rx.buf_mem = SLOF_alloc_mem(RX_ELEM_SIZE * RX_NUM_ELEMS);
66 if (!vq_rx.buf_mem) {
67 printf("virtio-serial: Failed to allocate buffers!\n");
68 goto dev_error;
69 }
70
71 /* Prepare receive buffer queue */
72 for (i = 0; i < RX_NUM_ELEMS; i++) {
73 uint64_t addr = (uint64_t)vq_rx.buf_mem + i * RX_ELEM_SIZE;
74
75 /* Descriptor for data: */
76 virtio_fill_desc(&vq_rx.desc[i], dev->is_modern, addr, 1, VRING_DESC_F_WRITE, 0);
77 vq_rx.avail->ring[i] = virtio_cpu_to_modern16(dev, i);
78 }
79 vq_rx.avail->flags = virtio_cpu_to_modern16(dev, VRING_AVAIL_F_NO_INTERRUPT);
80 vq_rx.avail->idx = virtio_cpu_to_modern16(dev, RX_NUM_ELEMS);
81 sync();
82
83 last_rx_idx = virtio_modern16_to_cpu(dev, vq_rx.used->idx);
84
85 if (virtio_queue_init_vq(dev, &vq_tx, TX_Q))
86 goto dev_error;
87
88 vq_avail = virtio_get_vring_avail(dev, TX_Q);
89 vq_avail->flags = virtio_cpu_to_modern16(dev, VRING_AVAIL_F_NO_INTERRUPT);
90 vq_avail->idx = 0;
91
92 /* Tell HV that setup succeeded */
93 status |= VIRTIO_STAT_DRIVER_OK;
94 virtio_set_status(dev, status);
95
96 return 1;
97 dev_error:
98 printf("%s: failed\n", __func__);
99 status |= VIRTIO_STAT_FAILED;
100 virtio_set_status(dev, status);
101 return 0;
102 }
103
virtio_serial_shutdown(struct virtio_device * dev)104 void virtio_serial_shutdown(struct virtio_device *dev)
105 {
106 /* Quiesce device */
107 virtio_set_status(dev, VIRTIO_STAT_FAILED);
108
109 /* Reset device */
110 virtio_reset_device(dev);
111 }
112
virtio_serial_putchar(struct virtio_device * dev,char c)113 int virtio_serial_putchar(struct virtio_device *dev, char c)
114 {
115 struct vring_desc *desc;
116 int id;
117 uint32_t vq_size, time;
118 struct vring_desc *vq_desc;
119 struct vring_avail *vq_avail;
120 struct vring_used *vq_used;
121 volatile uint16_t *current_used_idx;
122 uint16_t last_used_idx, avail_idx;
123
124 vq_size = virtio_get_qsize(dev, TX_Q);
125 vq_desc = virtio_get_vring_desc(dev, TX_Q);
126 vq_avail = virtio_get_vring_avail(dev, TX_Q);
127 vq_used = virtio_get_vring_used(dev, TX_Q);
128
129 avail_idx = virtio_modern16_to_cpu(dev, vq_avail->idx);
130
131 last_used_idx = vq_used->idx;
132 current_used_idx = &vq_used->idx;
133
134 /* Determine descriptor index */
135 id = avail_idx % vq_size;
136
137 /* Set up virtqueue descriptor for header */
138 desc = &vq_desc[id];
139 virtio_fill_desc(desc, dev->is_modern, (uint64_t)&c, 1, 0, 0);
140
141 vq_avail->ring[avail_idx % vq_size] = virtio_cpu_to_modern16 (dev, id);
142 mb();
143 vq_avail->idx = virtio_cpu_to_modern16(dev, avail_idx + 1);
144
145 /* Tell HV that the queue is ready */
146 virtio_queue_notify(dev, TX_Q);
147
148 /* Wait for host to consume the descriptor */
149 time = SLOF_GetTimer() + VIRTIO_TIMEOUT;
150 while (*current_used_idx == last_used_idx) {
151 // do something better
152 mb();
153 if (time < SLOF_GetTimer()) {
154 printf("virtio_serial_putchar failed! \n");
155 return 0;
156 }
157 }
158
159 return 1;
160 }
161
162 static uint16_t last_rx_idx; /* Last index in RX "used" ring */
163
virtio_serial_getchar(struct virtio_device * dev)164 char virtio_serial_getchar(struct virtio_device *dev)
165 {
166 int id, idx;
167 char buf[RX_NUM_ELEMS] = {0};
168 uint16_t avail_idx;
169
170 idx = virtio_modern16_to_cpu(dev, vq_rx.used->idx);
171 if (last_rx_idx == idx) {
172 /* Nothing received yet */
173 return 0;
174 }
175
176 id = (virtio_modern32_to_cpu(dev, vq_rx.used->ring[last_rx_idx % vq_rx.size].id) + 1)
177 % vq_rx.size;
178
179 /* Copy data to destination buffer */
180 memcpy(buf, (void *)virtio_modern64_to_cpu(dev, vq_rx.desc[id - 1].addr), RX_ELEM_SIZE);
181
182 /* Move indices to next entries */
183 last_rx_idx = last_rx_idx + 1;
184
185 avail_idx = virtio_modern16_to_cpu(dev, vq_rx.avail->idx);
186 vq_rx.avail->ring[avail_idx % vq_rx.size] = virtio_cpu_to_modern16(dev, id - 1);
187 sync();
188 vq_rx.avail->idx = virtio_cpu_to_modern16(dev, avail_idx + 1);
189 sync();
190
191 /* Tell HV that RX queue entry is ready */
192 virtio_queue_notify(dev, RX_Q);
193
194 return buf[0];
195 }
196
virtio_serial_haschar(struct virtio_device * dev)197 int virtio_serial_haschar(struct virtio_device *dev)
198 {
199 if (last_rx_idx == virtio_modern16_to_cpu(dev, vq_rx.used->idx))
200 return 0;
201 else
202 return 1;
203 }
204