Sun Jun 3 19:47:35 2018 UTC ()
add feature/register definitions from virtio-v1.0-cs04


(jakllsch)
diff -r1.17 -r1.18 src/sys/dev/pci/ld_virtio.c

cvs diff -r1.17 -r1.18 src/sys/dev/pci/ld_virtio.c (switch to unified diff)

--- src/sys/dev/pci/ld_virtio.c 2018/06/03 02:13:09 1.17
+++ src/sys/dev/pci/ld_virtio.c 2018/06/03 19:47:35 1.18
@@ -1,645 +1,652 @@ @@ -1,645 +1,652 @@
1/* $NetBSD: ld_virtio.c,v 1.17 2018/06/03 02:13:09 jakllsch Exp $ */ 1/* $NetBSD: ld_virtio.c,v 1.18 2018/06/03 19:47:35 jakllsch Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010 Minoura Makoto. 4 * Copyright (c) 2010 Minoura Makoto.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.17 2018/06/03 02:13:09 jakllsch Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.18 2018/06/03 19:47:35 jakllsch Exp $");
30 30
31#include <sys/param.h> 31#include <sys/param.h>
32#include <sys/systm.h> 32#include <sys/systm.h>
33#include <sys/kernel.h> 33#include <sys/kernel.h>
34#include <sys/buf.h> 34#include <sys/buf.h>
35#include <sys/bufq.h> 35#include <sys/bufq.h>
36#include <sys/bus.h> 36#include <sys/bus.h>
37#include <sys/device.h> 37#include <sys/device.h>
38#include <sys/disk.h> 38#include <sys/disk.h>
39#include <sys/mutex.h> 39#include <sys/mutex.h>
40#include <sys/module.h> 40#include <sys/module.h>
41 41
42#include <dev/pci/pcidevs.h> 42#include <dev/pci/pcidevs.h>
43#include <dev/pci/pcireg.h> 43#include <dev/pci/pcireg.h>
44#include <dev/pci/pcivar.h> 44#include <dev/pci/pcivar.h>
45 45
46#include <dev/ldvar.h> 46#include <dev/ldvar.h>
47#include <dev/pci/virtioreg.h> 47#include <dev/pci/virtioreg.h>
48#include <dev/pci/virtiovar.h> 48#include <dev/pci/virtiovar.h>
49 49
50#include "ioconf.h" 50#include "ioconf.h"
51 51
52/* 52/*
53 * ld_virtioreg: 53 * ld_virtioreg:
54 */ 54 */
55/* Configuration registers */ 55/* Configuration registers */
56#define VIRTIO_BLK_CONFIG_CAPACITY 0 /* 64bit */ 56#define VIRTIO_BLK_CONFIG_CAPACITY 0 /* 64bit */
57#define VIRTIO_BLK_CONFIG_SIZE_MAX 8 /* 32bit */ 57#define VIRTIO_BLK_CONFIG_SIZE_MAX 8 /* 32bit */
58#define VIRTIO_BLK_CONFIG_SEG_MAX 12 /* 32bit */ 58#define VIRTIO_BLK_CONFIG_SEG_MAX 12 /* 32bit */
59#define VIRTIO_BLK_CONFIG_GEOMETRY_C 16 /* 16bit */ 59#define VIRTIO_BLK_CONFIG_GEOMETRY_C 16 /* 16bit */
60#define VIRTIO_BLK_CONFIG_GEOMETRY_H 18 /* 8bit */ 60#define VIRTIO_BLK_CONFIG_GEOMETRY_H 18 /* 8bit */
61#define VIRTIO_BLK_CONFIG_GEOMETRY_S 19 /* 8bit */ 61#define VIRTIO_BLK_CONFIG_GEOMETRY_S 19 /* 8bit */
62#define VIRTIO_BLK_CONFIG_BLK_SIZE 20 /* 32bit */ 62#define VIRTIO_BLK_CONFIG_BLK_SIZE 20 /* 32bit */
 63#define VIRTIO_BLK_CONFIG_WRITEBACK 32 /* 8bit */
63 64
64/* Feature bits */ 65/* Feature bits */
65#define VIRTIO_BLK_F_BARRIER (1<<0) 66#define VIRTIO_BLK_F_BARRIER (1<<0)
66#define VIRTIO_BLK_F_SIZE_MAX (1<<1) 67#define VIRTIO_BLK_F_SIZE_MAX (1<<1)
67#define VIRTIO_BLK_F_SEG_MAX (1<<2) 68#define VIRTIO_BLK_F_SEG_MAX (1<<2)
68#define VIRTIO_BLK_F_GEOMETRY (1<<4) 69#define VIRTIO_BLK_F_GEOMETRY (1<<4)
69#define VIRTIO_BLK_F_RO (1<<5) 70#define VIRTIO_BLK_F_RO (1<<5)
70#define VIRTIO_BLK_F_BLK_SIZE (1<<6) 71#define VIRTIO_BLK_F_BLK_SIZE (1<<6)
71#define VIRTIO_BLK_F_SCSI (1<<7) 72#define VIRTIO_BLK_F_SCSI (1<<7)
72#define VIRTIO_BLK_F_FLUSH (1<<9) 73#define VIRTIO_BLK_F_FLUSH (1<<9)
 74#define VIRTIO_BLK_F_TOPOLOGY (1<<10)
 75#define VIRTIO_BLK_F_CONFIG_WCE (1<<11)
73 76
74/* 77/*
75 * Each block request uses at least two segments - one for the header 78 * Each block request uses at least two segments - one for the header
76 * and one for the status. 79 * and one for the status.
77*/ 80*/
78#define VIRTIO_BLK_MIN_SEGMENTS 2 81#define VIRTIO_BLK_MIN_SEGMENTS 2
79 82
80#define VIRTIO_BLK_FLAG_BITS \ 83#define VIRTIO_BLK_FLAG_BITS \
81 VIRTIO_COMMON_FLAG_BITS \ 84 VIRTIO_COMMON_FLAG_BITS \
 85 "\x0c""CONFIG_WCE" \
 86 "\x0b""TOPOLOGY" \
82 "\x0a""FLUSH" \ 87 "\x0a""FLUSH" \
83 "\x08""SCSI" \ 88 "\x08""SCSI" \
84 "\x07""BLK_SIZE" \ 89 "\x07""BLK_SIZE" \
85 "\x06""RO" \ 90 "\x06""RO" \
86 "\x05""GEOMETRY" \ 91 "\x05""GEOMETRY" \
87 "\x03""SEG_MAX" \ 92 "\x03""SEG_MAX" \
88 "\x02""SIZE_MAX" \ 93 "\x02""SIZE_MAX" \
89 "\x01""BARRIER" 94 "\x01""BARRIER"
90 95
91/* Command */ 96/* Command */
92#define VIRTIO_BLK_T_IN 0 97#define VIRTIO_BLK_T_IN 0
93#define VIRTIO_BLK_T_OUT 1 98#define VIRTIO_BLK_T_OUT 1
 99#define VIRTIO_BLK_T_FLUSH 4
94#define VIRTIO_BLK_T_BARRIER 0x80000000 100#define VIRTIO_BLK_T_BARRIER 0x80000000
95 101
96/* Status */ 102/* Status */
97#define VIRTIO_BLK_S_OK 0 103#define VIRTIO_BLK_S_OK 0
98#define VIRTIO_BLK_S_IOERR 1 104#define VIRTIO_BLK_S_IOERR 1
 105#define VIRTIO_BLK_S_UNSUPP 2
99 106
100/* Request header structure */ 107/* Request header structure */
101struct virtio_blk_req_hdr { 108struct virtio_blk_req_hdr {
102 uint32_t type; /* VIRTIO_BLK_T_* */ 109 uint32_t type; /* VIRTIO_BLK_T_* */
103 uint32_t ioprio; 110 uint32_t ioprio;
104 uint64_t sector; 111 uint64_t sector;
105} __packed; 112} __packed;
106/* 512*virtio_blk_req_hdr.sector byte payload and 1 byte status follows */ 113/* 512*virtio_blk_req_hdr.sector byte payload and 1 byte status follows */
107 114
108 115
109/* 116/*
110 * ld_virtiovar: 117 * ld_virtiovar:
111 */ 118 */
112struct virtio_blk_req { 119struct virtio_blk_req {
113 struct virtio_blk_req_hdr vr_hdr; 120 struct virtio_blk_req_hdr vr_hdr;
114 uint8_t vr_status; 121 uint8_t vr_status;
115 struct buf *vr_bp; 122 struct buf *vr_bp;
116 bus_dmamap_t vr_cmdsts; 123 bus_dmamap_t vr_cmdsts;
117 bus_dmamap_t vr_payload; 124 bus_dmamap_t vr_payload;
118}; 125};
119 126
120struct ld_virtio_softc { 127struct ld_virtio_softc {
121 struct ld_softc sc_ld; 128 struct ld_softc sc_ld;
122 device_t sc_dev; 129 device_t sc_dev;
123 130
124 struct virtio_softc *sc_virtio; 131 struct virtio_softc *sc_virtio;
125 struct virtqueue sc_vq; 132 struct virtqueue sc_vq;
126 133
127 struct virtio_blk_req *sc_reqs; 134 struct virtio_blk_req *sc_reqs;
128 bus_dma_segment_t sc_reqs_seg; 135 bus_dma_segment_t sc_reqs_seg;
129 136
130 int sc_readonly; 137 int sc_readonly;
131}; 138};
132 139
133static int ld_virtio_match(device_t, cfdata_t, void *); 140static int ld_virtio_match(device_t, cfdata_t, void *);
134static void ld_virtio_attach(device_t, device_t, void *); 141static void ld_virtio_attach(device_t, device_t, void *);
135static int ld_virtio_detach(device_t, int); 142static int ld_virtio_detach(device_t, int);
136 143
137CFATTACH_DECL_NEW(ld_virtio, sizeof(struct ld_virtio_softc), 144CFATTACH_DECL_NEW(ld_virtio, sizeof(struct ld_virtio_softc),
138 ld_virtio_match, ld_virtio_attach, ld_virtio_detach, NULL); 145 ld_virtio_match, ld_virtio_attach, ld_virtio_detach, NULL);
139 146
140static int 147static int
141ld_virtio_match(device_t parent, cfdata_t match, void *aux) 148ld_virtio_match(device_t parent, cfdata_t match, void *aux)
142{ 149{
143 struct virtio_attach_args *va = aux; 150 struct virtio_attach_args *va = aux;
144 151
145 if (va->sc_childdevid == PCI_PRODUCT_VIRTIO_BLOCK) 152 if (va->sc_childdevid == PCI_PRODUCT_VIRTIO_BLOCK)
146 return 1; 153 return 1;
147 154
148 return 0; 155 return 0;
149} 156}
150 157
151static int ld_virtio_vq_done(struct virtqueue *); 158static int ld_virtio_vq_done(struct virtqueue *);
152static int ld_virtio_dump(struct ld_softc *, void *, int, int); 159static int ld_virtio_dump(struct ld_softc *, void *, int, int);
153static int ld_virtio_start(struct ld_softc *, struct buf *); 160static int ld_virtio_start(struct ld_softc *, struct buf *);
154 161
155static int 162static int
156ld_virtio_alloc_reqs(struct ld_virtio_softc *sc, int qsize) 163ld_virtio_alloc_reqs(struct ld_virtio_softc *sc, int qsize)
157{ 164{
158 int allocsize, r, rsegs, i; 165 int allocsize, r, rsegs, i;
159 struct ld_softc *ld = &sc->sc_ld; 166 struct ld_softc *ld = &sc->sc_ld;
160 void *vaddr; 167 void *vaddr;
161 168
162 allocsize = sizeof(struct virtio_blk_req) * qsize; 169 allocsize = sizeof(struct virtio_blk_req) * qsize;
163 r = bus_dmamem_alloc(virtio_dmat(sc->sc_virtio), allocsize, 0, 0, 170 r = bus_dmamem_alloc(virtio_dmat(sc->sc_virtio), allocsize, 0, 0,
164 &sc->sc_reqs_seg, 1, &rsegs, BUS_DMA_NOWAIT); 171 &sc->sc_reqs_seg, 1, &rsegs, BUS_DMA_NOWAIT);
165 if (r != 0) { 172 if (r != 0) {
166 aprint_error_dev(sc->sc_dev, 173 aprint_error_dev(sc->sc_dev,
167 "DMA memory allocation failed, size %d, " 174 "DMA memory allocation failed, size %d, "
168 "error code %d\n", allocsize, r); 175 "error code %d\n", allocsize, r);
169 goto err_none; 176 goto err_none;
170 } 177 }
171 r = bus_dmamem_map(virtio_dmat(sc->sc_virtio), 178 r = bus_dmamem_map(virtio_dmat(sc->sc_virtio),
172 &sc->sc_reqs_seg, 1, allocsize, 179 &sc->sc_reqs_seg, 1, allocsize,
173 &vaddr, BUS_DMA_NOWAIT); 180 &vaddr, BUS_DMA_NOWAIT);
174 if (r != 0) { 181 if (r != 0) {
175 aprint_error_dev(sc->sc_dev, 182 aprint_error_dev(sc->sc_dev,
176 "DMA memory map failed, " 183 "DMA memory map failed, "
177 "error code %d\n", r); 184 "error code %d\n", r);
178 goto err_dmamem_alloc; 185 goto err_dmamem_alloc;
179 } 186 }
180 sc->sc_reqs = vaddr; 187 sc->sc_reqs = vaddr;
181 memset(vaddr, 0, allocsize); 188 memset(vaddr, 0, allocsize);
182 for (i = 0; i < qsize; i++) { 189 for (i = 0; i < qsize; i++) {
183 struct virtio_blk_req *vr = &sc->sc_reqs[i]; 190 struct virtio_blk_req *vr = &sc->sc_reqs[i];
184 r = bus_dmamap_create(virtio_dmat(sc->sc_virtio), 191 r = bus_dmamap_create(virtio_dmat(sc->sc_virtio),
185 offsetof(struct virtio_blk_req, vr_bp), 192 offsetof(struct virtio_blk_req, vr_bp),
186 1, 193 1,
187 offsetof(struct virtio_blk_req, vr_bp), 194 offsetof(struct virtio_blk_req, vr_bp),
188 0, 195 0,
189 BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, 196 BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
190 &vr->vr_cmdsts); 197 &vr->vr_cmdsts);
191 if (r != 0) { 198 if (r != 0) {
192 aprint_error_dev(sc->sc_dev, 199 aprint_error_dev(sc->sc_dev,
193 "command dmamap creation failed, " 200 "command dmamap creation failed, "
194 "error code %d\n", r); 201 "error code %d\n", r);
195 goto err_reqs; 202 goto err_reqs;
196 } 203 }
197 r = bus_dmamap_load(virtio_dmat(sc->sc_virtio), vr->vr_cmdsts, 204 r = bus_dmamap_load(virtio_dmat(sc->sc_virtio), vr->vr_cmdsts,
198 &vr->vr_hdr, 205 &vr->vr_hdr,
199 offsetof(struct virtio_blk_req, vr_bp), 206 offsetof(struct virtio_blk_req, vr_bp),
200 NULL, BUS_DMA_NOWAIT); 207 NULL, BUS_DMA_NOWAIT);
201 if (r != 0) { 208 if (r != 0) {
202 aprint_error_dev(sc->sc_dev, 209 aprint_error_dev(sc->sc_dev,
203 "command dmamap load failed, " 210 "command dmamap load failed, "
204 "error code %d\n", r); 211 "error code %d\n", r);
205 goto err_reqs; 212 goto err_reqs;
206 } 213 }
207 r = bus_dmamap_create(virtio_dmat(sc->sc_virtio), 214 r = bus_dmamap_create(virtio_dmat(sc->sc_virtio),
208 ld->sc_maxxfer, 215 ld->sc_maxxfer,
209 (ld->sc_maxxfer / NBPG) + 216 (ld->sc_maxxfer / NBPG) +
210 VIRTIO_BLK_MIN_SEGMENTS, 217 VIRTIO_BLK_MIN_SEGMENTS,
211 ld->sc_maxxfer, 218 ld->sc_maxxfer,
212 0, 219 0,
213 BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, 220 BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
214 &vr->vr_payload); 221 &vr->vr_payload);
215 if (r != 0) { 222 if (r != 0) {
216 aprint_error_dev(sc->sc_dev, 223 aprint_error_dev(sc->sc_dev,
217 "payload dmamap creation failed, " 224 "payload dmamap creation failed, "
218 "error code %d\n", r); 225 "error code %d\n", r);
219 goto err_reqs; 226 goto err_reqs;
220 } 227 }
221 } 228 }
222 return 0; 229 return 0;
223 230
224err_reqs: 231err_reqs:
225 for (i = 0; i < qsize; i++) { 232 for (i = 0; i < qsize; i++) {
226 struct virtio_blk_req *vr = &sc->sc_reqs[i]; 233 struct virtio_blk_req *vr = &sc->sc_reqs[i];
227 if (vr->vr_cmdsts) { 234 if (vr->vr_cmdsts) {
228 bus_dmamap_destroy(virtio_dmat(sc->sc_virtio), 235 bus_dmamap_destroy(virtio_dmat(sc->sc_virtio),
229 vr->vr_cmdsts); 236 vr->vr_cmdsts);
230 vr->vr_cmdsts = 0; 237 vr->vr_cmdsts = 0;
231 } 238 }
232 if (vr->vr_payload) { 239 if (vr->vr_payload) {
233 bus_dmamap_destroy(virtio_dmat(sc->sc_virtio), 240 bus_dmamap_destroy(virtio_dmat(sc->sc_virtio),
234 vr->vr_payload); 241 vr->vr_payload);
235 vr->vr_payload = 0; 242 vr->vr_payload = 0;
236 } 243 }
237 } 244 }
238 bus_dmamem_unmap(virtio_dmat(sc->sc_virtio), sc->sc_reqs, allocsize); 245 bus_dmamem_unmap(virtio_dmat(sc->sc_virtio), sc->sc_reqs, allocsize);
239err_dmamem_alloc: 246err_dmamem_alloc:
240 bus_dmamem_free(virtio_dmat(sc->sc_virtio), &sc->sc_reqs_seg, 1); 247 bus_dmamem_free(virtio_dmat(sc->sc_virtio), &sc->sc_reqs_seg, 1);
241err_none: 248err_none:
242 return -1; 249 return -1;
243} 250}
244 251
245static void 252static void
246ld_virtio_attach(device_t parent, device_t self, void *aux) 253ld_virtio_attach(device_t parent, device_t self, void *aux)
247{ 254{
248 struct ld_virtio_softc *sc = device_private(self); 255 struct ld_virtio_softc *sc = device_private(self);
249 struct ld_softc *ld = &sc->sc_ld; 256 struct ld_softc *ld = &sc->sc_ld;
250 struct virtio_softc *vsc = device_private(parent); 257 struct virtio_softc *vsc = device_private(parent);
251 uint32_t features; 258 uint32_t features;
252 int qsize, maxxfersize, maxnsegs; 259 int qsize, maxxfersize, maxnsegs;
253 260
254 if (virtio_child(vsc) != NULL) { 261 if (virtio_child(vsc) != NULL) {
255 aprint_normal(": child already attached for %s; " 262 aprint_normal(": child already attached for %s; "
256 "something wrong...\n", device_xname(parent)); 263 "something wrong...\n", device_xname(parent));
257 return; 264 return;
258 } 265 }
259 266
260 sc->sc_dev = self; 267 sc->sc_dev = self;
261 sc->sc_virtio = vsc; 268 sc->sc_virtio = vsc;
262 269
263 virtio_child_attach_start(vsc, self, IPL_BIO, &sc->sc_vq, 270 virtio_child_attach_start(vsc, self, IPL_BIO, &sc->sc_vq,
264 NULL, virtio_vq_intr, 0, 271 NULL, virtio_vq_intr, 0,
265 (VIRTIO_BLK_F_SIZE_MAX | VIRTIO_BLK_F_SEG_MAX | 272 (VIRTIO_BLK_F_SIZE_MAX | VIRTIO_BLK_F_SEG_MAX |
266 VIRTIO_BLK_F_GEOMETRY | VIRTIO_BLK_F_RO | VIRTIO_BLK_F_BLK_SIZE), 273 VIRTIO_BLK_F_GEOMETRY | VIRTIO_BLK_F_RO | VIRTIO_BLK_F_BLK_SIZE),
267 VIRTIO_BLK_FLAG_BITS); 274 VIRTIO_BLK_FLAG_BITS);
268 275
269 features = virtio_features(vsc); 276 features = virtio_features(vsc);
270 277
271 if (features & VIRTIO_BLK_F_RO) 278 if (features & VIRTIO_BLK_F_RO)
272 sc->sc_readonly = 1; 279 sc->sc_readonly = 1;
273 else 280 else
274 sc->sc_readonly = 0; 281 sc->sc_readonly = 0;
275 282
276 if (features & VIRTIO_BLK_F_BLK_SIZE) { 283 if (features & VIRTIO_BLK_F_BLK_SIZE) {
277 ld->sc_secsize = virtio_read_device_config_4(vsc, 284 ld->sc_secsize = virtio_read_device_config_4(vsc,
278 VIRTIO_BLK_CONFIG_BLK_SIZE); 285 VIRTIO_BLK_CONFIG_BLK_SIZE);
279 } else 286 } else
280 ld->sc_secsize = 512; 287 ld->sc_secsize = 512;
281 288
282 /* At least genfs_io assumes maxxfer == MAXPHYS. */ 289 /* At least genfs_io assumes maxxfer == MAXPHYS. */
283 if (features & VIRTIO_BLK_F_SIZE_MAX) { 290 if (features & VIRTIO_BLK_F_SIZE_MAX) {
284 maxxfersize = virtio_read_device_config_4(vsc, 291 maxxfersize = virtio_read_device_config_4(vsc,
285 VIRTIO_BLK_CONFIG_SIZE_MAX); 292 VIRTIO_BLK_CONFIG_SIZE_MAX);
286 if (maxxfersize < MAXPHYS) { 293 if (maxxfersize < MAXPHYS) {
287 aprint_error_dev(sc->sc_dev, 294 aprint_error_dev(sc->sc_dev,
288 "Too small SIZE_MAX %dK minimum is %dK\n", 295 "Too small SIZE_MAX %dK minimum is %dK\n",
289 maxxfersize / 1024, MAXPHYS / 1024); 296 maxxfersize / 1024, MAXPHYS / 1024);
290 // goto err; 297 // goto err;
291 maxxfersize = MAXPHYS; 298 maxxfersize = MAXPHYS;
292 } else if (maxxfersize > MAXPHYS) { 299 } else if (maxxfersize > MAXPHYS) {
293 aprint_normal_dev(sc->sc_dev, 300 aprint_normal_dev(sc->sc_dev,
294 "Clip SEG_MAX from %dK to %dK\n", 301 "Clip SEG_MAX from %dK to %dK\n",
295 maxxfersize / 1024, 302 maxxfersize / 1024,
296 MAXPHYS / 1024); 303 MAXPHYS / 1024);
297 maxxfersize = MAXPHYS; 304 maxxfersize = MAXPHYS;
298 } 305 }
299 } else 306 } else
300 maxxfersize = MAXPHYS; 307 maxxfersize = MAXPHYS;
301 308
302 if (features & VIRTIO_BLK_F_SEG_MAX) { 309 if (features & VIRTIO_BLK_F_SEG_MAX) {
303 maxnsegs = virtio_read_device_config_4(vsc, 310 maxnsegs = virtio_read_device_config_4(vsc,
304 VIRTIO_BLK_CONFIG_SEG_MAX); 311 VIRTIO_BLK_CONFIG_SEG_MAX);
305 if (maxnsegs < VIRTIO_BLK_MIN_SEGMENTS) { 312 if (maxnsegs < VIRTIO_BLK_MIN_SEGMENTS) {
306 aprint_error_dev(sc->sc_dev, 313 aprint_error_dev(sc->sc_dev,
307 "Too small SEG_MAX %d minimum is %d\n", 314 "Too small SEG_MAX %d minimum is %d\n",
308 maxnsegs, VIRTIO_BLK_MIN_SEGMENTS); 315 maxnsegs, VIRTIO_BLK_MIN_SEGMENTS);
309 maxnsegs = maxxfersize / NBPG; 316 maxnsegs = maxxfersize / NBPG;
310 // goto err; 317 // goto err;
311 } 318 }
312 } else 319 } else
313 maxnsegs = maxxfersize / NBPG; 320 maxnsegs = maxxfersize / NBPG;
314 321
315 /* 2 for the minimum size */ 322 /* 2 for the minimum size */
316 maxnsegs += VIRTIO_BLK_MIN_SEGMENTS; 323 maxnsegs += VIRTIO_BLK_MIN_SEGMENTS;
317 324
318 if (virtio_alloc_vq(vsc, &sc->sc_vq, 0, maxxfersize, maxnsegs, 325 if (virtio_alloc_vq(vsc, &sc->sc_vq, 0, maxxfersize, maxnsegs,
319 "I/O request") != 0) { 326 "I/O request") != 0) {
320 goto err; 327 goto err;
321 } 328 }
322 qsize = sc->sc_vq.vq_num; 329 qsize = sc->sc_vq.vq_num;
323 sc->sc_vq.vq_done = ld_virtio_vq_done; 330 sc->sc_vq.vq_done = ld_virtio_vq_done;
324 331
325 if (virtio_child_attach_finish(vsc) != 0) 332 if (virtio_child_attach_finish(vsc) != 0)
326 goto err; 333 goto err;
327 334
328 ld->sc_dv = self; 335 ld->sc_dv = self;
329 ld->sc_secperunit = virtio_read_device_config_8(vsc, 336 ld->sc_secperunit = virtio_read_device_config_8(vsc,
330 VIRTIO_BLK_CONFIG_CAPACITY); 337 VIRTIO_BLK_CONFIG_CAPACITY);
331 ld->sc_maxxfer = maxxfersize; 338 ld->sc_maxxfer = maxxfersize;
332 if (features & VIRTIO_BLK_F_GEOMETRY) { 339 if (features & VIRTIO_BLK_F_GEOMETRY) {
333 ld->sc_ncylinders = virtio_read_device_config_2(vsc, 340 ld->sc_ncylinders = virtio_read_device_config_2(vsc,
334 VIRTIO_BLK_CONFIG_GEOMETRY_C); 341 VIRTIO_BLK_CONFIG_GEOMETRY_C);
335 ld->sc_nheads = virtio_read_device_config_1(vsc, 342 ld->sc_nheads = virtio_read_device_config_1(vsc,
336 VIRTIO_BLK_CONFIG_GEOMETRY_H); 343 VIRTIO_BLK_CONFIG_GEOMETRY_H);
337 ld->sc_nsectors = virtio_read_device_config_1(vsc, 344 ld->sc_nsectors = virtio_read_device_config_1(vsc,
338 VIRTIO_BLK_CONFIG_GEOMETRY_S); 345 VIRTIO_BLK_CONFIG_GEOMETRY_S);
339 } 346 }
340 ld->sc_maxqueuecnt = qsize; 347 ld->sc_maxqueuecnt = qsize;
341 348
342 if (ld_virtio_alloc_reqs(sc, qsize) < 0) 349 if (ld_virtio_alloc_reqs(sc, qsize) < 0)
343 goto err; 350 goto err;
344 351
345 ld->sc_dump = ld_virtio_dump; 352 ld->sc_dump = ld_virtio_dump;
346 ld->sc_start = ld_virtio_start; 353 ld->sc_start = ld_virtio_start;
347 354
348 ld->sc_flags = LDF_ENABLED | LDF_MPSAFE; 355 ld->sc_flags = LDF_ENABLED | LDF_MPSAFE;
349 ldattach(ld, BUFQ_DISK_DEFAULT_STRAT); 356 ldattach(ld, BUFQ_DISK_DEFAULT_STRAT);
350 357
351 return; 358 return;
352 359
353err: 360err:
354 virtio_child_attach_failed(vsc); 361 virtio_child_attach_failed(vsc);
355 return; 362 return;
356} 363}
357 364
358static int 365static int
359ld_virtio_start(struct ld_softc *ld, struct buf *bp) 366ld_virtio_start(struct ld_softc *ld, struct buf *bp)
360{ 367{
361 /* splbio */ 368 /* splbio */
362 struct ld_virtio_softc *sc = device_private(ld->sc_dv); 369 struct ld_virtio_softc *sc = device_private(ld->sc_dv);
363 struct virtio_softc *vsc = sc->sc_virtio; 370 struct virtio_softc *vsc = sc->sc_virtio;
364 struct virtqueue *vq = &sc->sc_vq; 371 struct virtqueue *vq = &sc->sc_vq;
365 struct virtio_blk_req *vr; 372 struct virtio_blk_req *vr;
366 int r; 373 int r;
367 int isread = (bp->b_flags & B_READ); 374 int isread = (bp->b_flags & B_READ);
368 int slot; 375 int slot;
369 376
370 if (sc->sc_readonly && !isread) 377 if (sc->sc_readonly && !isread)
371 return EIO; 378 return EIO;
372 379
373 r = virtio_enqueue_prep(vsc, vq, &slot); 380 r = virtio_enqueue_prep(vsc, vq, &slot);
374 if (r != 0) 381 if (r != 0)
375 return r; 382 return r;
376 383
377 vr = &sc->sc_reqs[slot]; 384 vr = &sc->sc_reqs[slot];
378 KASSERT(vr->vr_bp == NULL); 385 KASSERT(vr->vr_bp == NULL);
379 386
380 r = bus_dmamap_load(virtio_dmat(vsc), vr->vr_payload, 387 r = bus_dmamap_load(virtio_dmat(vsc), vr->vr_payload,
381 bp->b_data, bp->b_bcount, NULL, 388 bp->b_data, bp->b_bcount, NULL,
382 ((isread?BUS_DMA_READ:BUS_DMA_WRITE) 389 ((isread?BUS_DMA_READ:BUS_DMA_WRITE)
383 |BUS_DMA_NOWAIT)); 390 |BUS_DMA_NOWAIT));
384 if (r != 0) { 391 if (r != 0) {
385 aprint_error_dev(sc->sc_dev, 392 aprint_error_dev(sc->sc_dev,
386 "payload dmamap failed, error code %d\n", r); 393 "payload dmamap failed, error code %d\n", r);
387 virtio_enqueue_abort(vsc, vq, slot); 394 virtio_enqueue_abort(vsc, vq, slot);
388 return r; 395 return r;
389 } 396 }
390 397
391 r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs + 398 r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs +
392 VIRTIO_BLK_MIN_SEGMENTS); 399 VIRTIO_BLK_MIN_SEGMENTS);
393 if (r != 0) { 400 if (r != 0) {
394 bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload); 401 bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload);
395 return r; 402 return r;
396 } 403 }
397 404
398 vr->vr_bp = bp; 405 vr->vr_bp = bp;
399 vr->vr_hdr.type = isread?VIRTIO_BLK_T_IN:VIRTIO_BLK_T_OUT; 406 vr->vr_hdr.type = isread?VIRTIO_BLK_T_IN:VIRTIO_BLK_T_OUT;
400 vr->vr_hdr.ioprio = 0; 407 vr->vr_hdr.ioprio = 0;
401 vr->vr_hdr.sector = bp->b_rawblkno * sc->sc_ld.sc_secsize / 512; 408 vr->vr_hdr.sector = bp->b_rawblkno * sc->sc_ld.sc_secsize / 512;
402 409
403 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 410 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
404 0, sizeof(struct virtio_blk_req_hdr), 411 0, sizeof(struct virtio_blk_req_hdr),
405 BUS_DMASYNC_PREWRITE); 412 BUS_DMASYNC_PREWRITE);
406 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 413 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload,
407 0, bp->b_bcount, 414 0, bp->b_bcount,
408 isread?BUS_DMASYNC_PREREAD:BUS_DMASYNC_PREWRITE); 415 isread?BUS_DMASYNC_PREREAD:BUS_DMASYNC_PREWRITE);
409 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 416 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
410 offsetof(struct virtio_blk_req, vr_status), 417 offsetof(struct virtio_blk_req, vr_status),
411 sizeof(uint8_t), 418 sizeof(uint8_t),
412 BUS_DMASYNC_PREREAD); 419 BUS_DMASYNC_PREREAD);
413 420
414 virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 421 virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts,
415 0, sizeof(struct virtio_blk_req_hdr), 422 0, sizeof(struct virtio_blk_req_hdr),
416 true); 423 true);
417 virtio_enqueue(vsc, vq, slot, vr->vr_payload, !isread); 424 virtio_enqueue(vsc, vq, slot, vr->vr_payload, !isread);
418 virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 425 virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts,
419 offsetof(struct virtio_blk_req, vr_status), 426 offsetof(struct virtio_blk_req, vr_status),
420 sizeof(uint8_t), 427 sizeof(uint8_t),
421 false); 428 false);
422 virtio_enqueue_commit(vsc, vq, slot, true); 429 virtio_enqueue_commit(vsc, vq, slot, true);
423 430
424 return 0; 431 return 0;
425} 432}
426 433
427static void 434static void
428ld_virtio_vq_done1(struct ld_virtio_softc *sc, struct virtio_softc *vsc, 435ld_virtio_vq_done1(struct ld_virtio_softc *sc, struct virtio_softc *vsc,
429 struct virtqueue *vq, int slot) 436 struct virtqueue *vq, int slot)
430{ 437{
431 struct virtio_blk_req *vr = &sc->sc_reqs[slot]; 438 struct virtio_blk_req *vr = &sc->sc_reqs[slot];
432 struct buf *bp = vr->vr_bp; 439 struct buf *bp = vr->vr_bp;
433 440
434 vr->vr_bp = NULL; 441 vr->vr_bp = NULL;
435 442
436 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 443 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
437 0, sizeof(struct virtio_blk_req_hdr), 444 0, sizeof(struct virtio_blk_req_hdr),
438 BUS_DMASYNC_POSTWRITE); 445 BUS_DMASYNC_POSTWRITE);
439 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 446 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload,
440 0, bp->b_bcount, 447 0, bp->b_bcount,
441 (bp->b_flags & B_READ)?BUS_DMASYNC_POSTREAD 448 (bp->b_flags & B_READ)?BUS_DMASYNC_POSTREAD
442 :BUS_DMASYNC_POSTWRITE); 449 :BUS_DMASYNC_POSTWRITE);
443 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 450 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
444 sizeof(struct virtio_blk_req_hdr), sizeof(uint8_t), 451 sizeof(struct virtio_blk_req_hdr), sizeof(uint8_t),
445 BUS_DMASYNC_POSTREAD); 452 BUS_DMASYNC_POSTREAD);
446 453
447 if (vr->vr_status != VIRTIO_BLK_S_OK) { 454 if (vr->vr_status != VIRTIO_BLK_S_OK) {
448 bp->b_error = EIO; 455 bp->b_error = EIO;
449 bp->b_resid = bp->b_bcount; 456 bp->b_resid = bp->b_bcount;
450 } else { 457 } else {
451 bp->b_error = 0; 458 bp->b_error = 0;
452 bp->b_resid = 0; 459 bp->b_resid = 0;
453 } 460 }
454 461
455 virtio_dequeue_commit(vsc, vq, slot); 462 virtio_dequeue_commit(vsc, vq, slot);
456 463
457 lddone(&sc->sc_ld, bp); 464 lddone(&sc->sc_ld, bp);
458} 465}
459 466
460static int 467static int
461ld_virtio_vq_done(struct virtqueue *vq) 468ld_virtio_vq_done(struct virtqueue *vq)
462{ 469{
463 struct virtio_softc *vsc = vq->vq_owner; 470 struct virtio_softc *vsc = vq->vq_owner;
464 struct ld_virtio_softc *sc = device_private(virtio_child(vsc)); 471 struct ld_virtio_softc *sc = device_private(virtio_child(vsc));
465 int r = 0; 472 int r = 0;
466 int slot; 473 int slot;
467 474
468again: 475again:
469 if (virtio_dequeue(vsc, vq, &slot, NULL)) 476 if (virtio_dequeue(vsc, vq, &slot, NULL))
470 return r; 477 return r;
471 r = 1; 478 r = 1;
472 479
473 ld_virtio_vq_done1(sc, vsc, vq, slot); 480 ld_virtio_vq_done1(sc, vsc, vq, slot);
474 goto again; 481 goto again;
475} 482}
476 483
477static int 484static int
478ld_virtio_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt) 485ld_virtio_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt)
479{ 486{
480 struct ld_virtio_softc *sc = device_private(ld->sc_dv); 487 struct ld_virtio_softc *sc = device_private(ld->sc_dv);
481 struct virtio_softc *vsc = sc->sc_virtio; 488 struct virtio_softc *vsc = sc->sc_virtio;
482 struct virtqueue *vq = &sc->sc_vq; 489 struct virtqueue *vq = &sc->sc_vq;
483 struct virtio_blk_req *vr; 490 struct virtio_blk_req *vr;
484 int slot, r; 491 int slot, r;
485 492
486 if (sc->sc_readonly) 493 if (sc->sc_readonly)
487 return EIO; 494 return EIO;
488 495
489 r = virtio_enqueue_prep(vsc, vq, &slot); 496 r = virtio_enqueue_prep(vsc, vq, &slot);
490 if (r != 0) { 497 if (r != 0) {
491 if (r == EAGAIN) { /* no free slot; dequeue first */ 498 if (r == EAGAIN) { /* no free slot; dequeue first */
492 delay(100); 499 delay(100);
493 ld_virtio_vq_done(vq); 500 ld_virtio_vq_done(vq);
494 r = virtio_enqueue_prep(vsc, vq, &slot); 501 r = virtio_enqueue_prep(vsc, vq, &slot);
495 if (r != 0) 502 if (r != 0)
496 return r; 503 return r;
497 } 504 }
498 return r; 505 return r;
499 } 506 }
500 vr = &sc->sc_reqs[slot]; 507 vr = &sc->sc_reqs[slot];
501 r = bus_dmamap_load(virtio_dmat(vsc), vr->vr_payload, 508 r = bus_dmamap_load(virtio_dmat(vsc), vr->vr_payload,
502 data, blkcnt*ld->sc_secsize, NULL, 509 data, blkcnt*ld->sc_secsize, NULL,
503 BUS_DMA_WRITE|BUS_DMA_NOWAIT); 510 BUS_DMA_WRITE|BUS_DMA_NOWAIT);
504 if (r != 0) 511 if (r != 0)
505 return r; 512 return r;
506 513
507 r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs + 514 r = virtio_enqueue_reserve(vsc, vq, slot, vr->vr_payload->dm_nsegs +
508 VIRTIO_BLK_MIN_SEGMENTS); 515 VIRTIO_BLK_MIN_SEGMENTS);
509 if (r != 0) { 516 if (r != 0) {
510 bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload); 517 bus_dmamap_unload(virtio_dmat(vsc), vr->vr_payload);
511 return r; 518 return r;
512 } 519 }
513 520
514 vr->vr_bp = (void*)0xdeadbeef; 521 vr->vr_bp = (void*)0xdeadbeef;
515 vr->vr_hdr.type = VIRTIO_BLK_T_OUT; 522 vr->vr_hdr.type = VIRTIO_BLK_T_OUT;
516 vr->vr_hdr.ioprio = 0; 523 vr->vr_hdr.ioprio = 0;
517 vr->vr_hdr.sector = (daddr_t) blkno * ld->sc_secsize / 512; 524 vr->vr_hdr.sector = (daddr_t) blkno * ld->sc_secsize / 512;
518 525
519 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 526 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
520 0, sizeof(struct virtio_blk_req_hdr), 527 0, sizeof(struct virtio_blk_req_hdr),
521 BUS_DMASYNC_PREWRITE); 528 BUS_DMASYNC_PREWRITE);
522 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 529 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload,
523 0, blkcnt*ld->sc_secsize, 530 0, blkcnt*ld->sc_secsize,
524 BUS_DMASYNC_PREWRITE); 531 BUS_DMASYNC_PREWRITE);
525 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 532 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
526 offsetof(struct virtio_blk_req, vr_status), 533 offsetof(struct virtio_blk_req, vr_status),
527 sizeof(uint8_t), 534 sizeof(uint8_t),
528 BUS_DMASYNC_PREREAD); 535 BUS_DMASYNC_PREREAD);
529 536
530 virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 537 virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts,
531 0, sizeof(struct virtio_blk_req_hdr), 538 0, sizeof(struct virtio_blk_req_hdr),
532 true); 539 true);
533 virtio_enqueue(vsc, vq, slot, vr->vr_payload, true); 540 virtio_enqueue(vsc, vq, slot, vr->vr_payload, true);
534 virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts, 541 virtio_enqueue_p(vsc, vq, slot, vr->vr_cmdsts,
535 offsetof(struct virtio_blk_req, vr_status), 542 offsetof(struct virtio_blk_req, vr_status),
536 sizeof(uint8_t), 543 sizeof(uint8_t),
537 false); 544 false);
538 virtio_enqueue_commit(vsc, vq, slot, true); 545 virtio_enqueue_commit(vsc, vq, slot, true);
539 546
540 for ( ; ; ) { 547 for ( ; ; ) {
541 int dslot; 548 int dslot;
542 549
543 r = virtio_dequeue(vsc, vq, &dslot, NULL); 550 r = virtio_dequeue(vsc, vq, &dslot, NULL);
544 if (r != 0) 551 if (r != 0)
545 continue; 552 continue;
546 if (dslot != slot) { 553 if (dslot != slot) {
547 ld_virtio_vq_done1(sc, vsc, vq, dslot); 554 ld_virtio_vq_done1(sc, vsc, vq, dslot);
548 continue; 555 continue;
549 } else 556 } else
550 break; 557 break;
551 } 558 }
552 559
553 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 560 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
554 0, sizeof(struct virtio_blk_req_hdr), 561 0, sizeof(struct virtio_blk_req_hdr),
555 BUS_DMASYNC_POSTWRITE); 562 BUS_DMASYNC_POSTWRITE);
556 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload, 563 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_payload,
557 0, blkcnt*ld->sc_secsize, 564 0, blkcnt*ld->sc_secsize,
558 BUS_DMASYNC_POSTWRITE); 565 BUS_DMASYNC_POSTWRITE);
559 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts, 566 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_cmdsts,
560 offsetof(struct virtio_blk_req, vr_status), 567 offsetof(struct virtio_blk_req, vr_status),
561 sizeof(uint8_t), 568 sizeof(uint8_t),
562 BUS_DMASYNC_POSTREAD); 569 BUS_DMASYNC_POSTREAD);
563 if (vr->vr_status == VIRTIO_BLK_S_OK) 570 if (vr->vr_status == VIRTIO_BLK_S_OK)
564 r = 0; 571 r = 0;
565 else 572 else
566 r = EIO; 573 r = EIO;
567 virtio_dequeue_commit(vsc, vq, slot); 574 virtio_dequeue_commit(vsc, vq, slot);
568 575
569 return r; 576 return r;
570} 577}
571 578
572static int 579static int
573ld_virtio_detach(device_t self, int flags) 580ld_virtio_detach(device_t self, int flags)
574{ 581{
575 struct ld_virtio_softc *sc = device_private(self); 582 struct ld_virtio_softc *sc = device_private(self);
576 struct ld_softc *ld = &sc->sc_ld; 583 struct ld_softc *ld = &sc->sc_ld;
577 bus_dma_tag_t dmat = virtio_dmat(sc->sc_virtio); 584 bus_dma_tag_t dmat = virtio_dmat(sc->sc_virtio);
578 int r, i, qsize; 585 int r, i, qsize;
579 586
580 qsize = sc->sc_vq.vq_num; 587 qsize = sc->sc_vq.vq_num;
581 r = ldbegindetach(ld, flags); 588 r = ldbegindetach(ld, flags);
582 if (r != 0) 589 if (r != 0)
583 return r; 590 return r;
584 virtio_reset(sc->sc_virtio); 591 virtio_reset(sc->sc_virtio);
585 virtio_free_vq(sc->sc_virtio, &sc->sc_vq); 592 virtio_free_vq(sc->sc_virtio, &sc->sc_vq);
586 593
587 for (i = 0; i < qsize; i++) { 594 for (i = 0; i < qsize; i++) {
588 bus_dmamap_destroy(dmat, 595 bus_dmamap_destroy(dmat,
589 sc->sc_reqs[i].vr_cmdsts); 596 sc->sc_reqs[i].vr_cmdsts);
590 bus_dmamap_destroy(dmat, 597 bus_dmamap_destroy(dmat,
591 sc->sc_reqs[i].vr_payload); 598 sc->sc_reqs[i].vr_payload);
592 } 599 }
593 bus_dmamem_unmap(dmat, sc->sc_reqs, 600 bus_dmamem_unmap(dmat, sc->sc_reqs,
594 sizeof(struct virtio_blk_req) * qsize); 601 sizeof(struct virtio_blk_req) * qsize);
595 bus_dmamem_free(dmat, &sc->sc_reqs_seg, 1); 602 bus_dmamem_free(dmat, &sc->sc_reqs_seg, 1);
596 603
597 ldenddetach(ld); 604 ldenddetach(ld);
598 605
599 virtio_child_detach(sc->sc_virtio); 606 virtio_child_detach(sc->sc_virtio);
600 607
601 return 0; 608 return 0;
602} 609}
603 610
604MODULE(MODULE_CLASS_DRIVER, ld_virtio, "ld,virtio"); 611MODULE(MODULE_CLASS_DRIVER, ld_virtio, "ld,virtio");
605 612
606#ifdef _MODULE 613#ifdef _MODULE
607/* 614/*
608 * XXX Don't allow ioconf.c to redefine the "struct cfdriver ld_cd" 615 * XXX Don't allow ioconf.c to redefine the "struct cfdriver ld_cd"
609 * XXX it will be defined in the common-code module 616 * XXX it will be defined in the common-code module
610 */ 617 */
611#undef CFDRIVER_DECL 618#undef CFDRIVER_DECL
612#define CFDRIVER_DECL(name, class, attr) 619#define CFDRIVER_DECL(name, class, attr)
613#include "ioconf.c" 620#include "ioconf.c"
614#endif 621#endif
615 622
616static int 623static int
617ld_virtio_modcmd(modcmd_t cmd, void *opaque) 624ld_virtio_modcmd(modcmd_t cmd, void *opaque)
618{ 625{
619#ifdef _MODULE 626#ifdef _MODULE
620 /* 627 /*
621 * We ignore the cfdriver_vec[] that ioconf provides, since 628 * We ignore the cfdriver_vec[] that ioconf provides, since
622 * the cfdrivers are attached already. 629 * the cfdrivers are attached already.
623 */ 630 */
624 static struct cfdriver * const no_cfdriver_vec[] = { NULL }; 631 static struct cfdriver * const no_cfdriver_vec[] = { NULL };
625#endif 632#endif
626 int error = 0; 633 int error = 0;
627 634
628#ifdef _MODULE 635#ifdef _MODULE
629 switch (cmd) { 636 switch (cmd) {
630 case MODULE_CMD_INIT: 637 case MODULE_CMD_INIT:
631 error = config_init_component(no_cfdriver_vec, 638 error = config_init_component(no_cfdriver_vec,
632 cfattach_ioconf_ld_virtio, cfdata_ioconf_ld_virtio); 639 cfattach_ioconf_ld_virtio, cfdata_ioconf_ld_virtio);
633 break; 640 break;
634 case MODULE_CMD_FINI: 641 case MODULE_CMD_FINI:
635 error = config_fini_component(no_cfdriver_vec, 642 error = config_fini_component(no_cfdriver_vec,
636 cfattach_ioconf_ld_virtio, cfdata_ioconf_ld_virtio); 643 cfattach_ioconf_ld_virtio, cfdata_ioconf_ld_virtio);
637 break; 644 break;
638 default: 645 default:
639 error = ENOTTY; 646 error = ENOTTY;
640 break; 647 break;
641 } 648 }
642#endif 649#endif
643 650
644 return error; 651 return error;
645} 652}