1 /* $OpenBSD: virtio_mmio.c,v 1.23 2025/01/14 14:28:38 sf Exp $ */ 2 /* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */ 3 4 /* 5 * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se> 6 * Copyright (c) 2012 Stefan Fritsch. 7 * Copyright (c) 2010 Minoura Makoto. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/device.h> 35 #include <sys/mutex.h> 36 37 #include <dev/pv/virtioreg.h> 38 #include <dev/pv/virtiovar.h> 39 40 #include <machine/fdt.h> 41 42 #include <dev/ofw/fdt.h> 43 #include <dev/ofw/openfirm.h> 44 45 #define VIRTIO_MMIO_MAGIC ('v' | 'i' << 8 | 'r' << 16 | 't' << 24) 46 47 #define VIRTIO_MMIO_MAGIC_VALUE 0x000 48 #define VIRTIO_MMIO_VERSION 0x004 49 #define VIRTIO_MMIO_DEVICE_ID 0x008 50 #define VIRTIO_MMIO_VENDOR_ID 0x00c 51 #define VIRTIO_MMIO_HOST_FEATURES 0x010 52 #define VIRTIO_MMIO_HOST_FEATURES_SEL 0x014 53 #define VIRTIO_MMIO_GUEST_FEATURES 0x020 54 #define VIRTIO_MMIO_GUEST_FEATURES_SEL 0x024 55 #define VIRTIO_MMIO_GUEST_PAGE_SIZE 0x028 56 #define VIRTIO_MMIO_QUEUE_SEL 0x030 57 #define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034 58 #define VIRTIO_MMIO_QUEUE_NUM 0x038 59 #define VIRTIO_MMIO_QUEUE_ALIGN 0x03c 60 #define VIRTIO_MMIO_QUEUE_PFN 0x040 61 #define VIRTIO_MMIO_QUEUE_READY 0x044 62 #define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 63 #define VIRTIO_MMIO_INTERRUPT_STATUS 0x060 64 #define VIRTIO_MMIO_INTERRUPT_ACK 0x064 65 #define VIRTIO_MMIO_STATUS 0x070 66 #define VIRTIO_MMIO_QUEUE_DESC_LOW 0x080 67 #define VIRTIO_MMIO_QUEUE_DESC_HIGH 0x084 68 #define VIRTIO_MMIO_QUEUE_AVAIL_LOW 0x090 69 #define VIRTIO_MMIO_QUEUE_AVAIL_HIGH 0x094 70 #define VIRTIO_MMIO_QUEUE_USED_LOW 0x0a0 71 #define VIRTIO_MMIO_QUEUE_USED_HIGH 0x0a4 72 #define VIRTIO_MMIO_CONFIG 0x100 73 74 #define VIRTIO_MMIO_INT_VRING (1 << 0) 75 #define VIRTIO_MMIO_INT_CONFIG (1 << 1) 76 77 #define DEVNAME(sc) (sc)->sc_dev.dv_xname 78 79 /* 80 * XXX: Before being used on big endian arches, the access to config registers 81 * XXX: needs to be reviewed/fixed. The non-device specific registers are 82 * XXX: PCI-endian while the device specific registers are native endian. 83 */ 84 85 int virtio_mmio_match(struct device *, void *, void *); 86 void virtio_mmio_attach(struct device *, struct device *, void *); 87 int virtio_mmio_detach(struct device *, int); 88 89 void virtio_mmio_kick(struct virtio_softc *, uint16_t); 90 uint8_t virtio_mmio_read_device_config_1(struct virtio_softc *, int); 91 uint16_t virtio_mmio_read_device_config_2(struct virtio_softc *, int); 92 uint32_t virtio_mmio_read_device_config_4(struct virtio_softc *, int); 93 uint64_t virtio_mmio_read_device_config_8(struct virtio_softc *, int); 94 void virtio_mmio_write_device_config_1(struct virtio_softc *, int, uint8_t); 95 void virtio_mmio_write_device_config_2(struct virtio_softc *, int, uint16_t); 96 void virtio_mmio_write_device_config_4(struct virtio_softc *, int, uint32_t); 97 void virtio_mmio_write_device_config_8(struct virtio_softc *, int, uint64_t); 98 uint16_t virtio_mmio_read_queue_size(struct virtio_softc *, uint16_t); 99 void virtio_mmio_setup_queue(struct virtio_softc *, struct virtqueue *, uint64_t); 100 void virtio_mmio_setup_intrs(struct virtio_softc *); 101 int virtio_mmio_attach_finish(struct virtio_softc *, struct virtio_attach_args *); 102 int virtio_mmio_get_status(struct virtio_softc *); 103 void virtio_mmio_set_status(struct virtio_softc *, int); 104 int virtio_mmio_negotiate_features(struct virtio_softc *, 105 const struct virtio_feature_name *); 106 int virtio_mmio_intr(void *); 107 void virtio_mmio_intr_barrier(struct virtio_softc *); 108 int virtio_mmio_intr_establish(struct virtio_softc *, struct virtio_attach_args *, 109 int, struct cpu_info *, int (*)(void *), void *); 110 111 struct virtio_mmio_softc { 112 struct virtio_softc sc_sc; 113 114 bus_space_tag_t sc_iot; 115 bus_space_handle_t sc_ioh; 116 bus_size_t sc_iosize; 117 bus_dma_tag_t sc_dmat; 118 119 void *sc_ih; 120 121 int sc_config_offset; 122 uint32_t sc_version; 123 }; 124 125 struct virtio_mmio_attach_args { 126 struct virtio_attach_args vma_va; 127 struct fdt_attach_args *vma_fa; 128 }; 129 130 const struct cfattach virtio_mmio_ca = { 131 sizeof(struct virtio_mmio_softc), 132 virtio_mmio_match, 133 virtio_mmio_attach, 134 virtio_mmio_detach, 135 NULL 136 }; 137 138 const struct cfattach virtio_mmio_fdt_ca = { 139 sizeof(struct virtio_mmio_softc), 140 NULL, 141 virtio_mmio_attach, 142 virtio_mmio_detach, 143 NULL 144 }; 145 146 const struct virtio_ops virtio_mmio_ops = { 147 virtio_mmio_kick, 148 virtio_mmio_read_device_config_1, 149 virtio_mmio_read_device_config_2, 150 virtio_mmio_read_device_config_4, 151 virtio_mmio_read_device_config_8, 152 virtio_mmio_write_device_config_1, 153 virtio_mmio_write_device_config_2, 154 virtio_mmio_write_device_config_4, 155 virtio_mmio_write_device_config_8, 156 virtio_mmio_read_queue_size, 157 virtio_mmio_setup_queue, 158 virtio_mmio_setup_intrs, 159 virtio_mmio_get_status, 160 virtio_mmio_set_status, 161 virtio_mmio_negotiate_features, 162 virtio_mmio_attach_finish, 163 virtio_mmio_intr, 164 virtio_mmio_intr_barrier, 165 virtio_mmio_intr_establish, 166 }; 167 168 uint16_t 169 virtio_mmio_read_queue_size(struct virtio_softc *vsc, uint16_t idx) 170 { 171 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 172 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_SEL, idx); 173 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, 174 VIRTIO_MMIO_QUEUE_NUM_MAX); 175 } 176 177 void 178 virtio_mmio_setup_queue(struct virtio_softc *vsc, struct virtqueue *vq, 179 uint64_t addr) 180 { 181 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 182 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_SEL, 183 vq->vq_index); 184 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_NUM, 185 bus_space_read_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_NUM_MAX)); 186 if (sc->sc_version == 1) { 187 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 188 VIRTIO_MMIO_QUEUE_ALIGN, PAGE_SIZE); 189 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 190 VIRTIO_MMIO_QUEUE_PFN, addr / VIRTIO_PAGE_SIZE); 191 } else { 192 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 193 VIRTIO_MMIO_QUEUE_DESC_LOW, addr); 194 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 195 VIRTIO_MMIO_QUEUE_DESC_HIGH, addr >> 32); 196 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 197 VIRTIO_MMIO_QUEUE_AVAIL_LOW, 198 addr + vq->vq_availoffset); 199 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 200 VIRTIO_MMIO_QUEUE_AVAIL_HIGH, 201 (addr + vq->vq_availoffset) >> 32); 202 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 203 VIRTIO_MMIO_QUEUE_USED_LOW, 204 addr + vq->vq_usedoffset); 205 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 206 VIRTIO_MMIO_QUEUE_USED_HIGH, 207 (addr + vq->vq_usedoffset) >> 32); 208 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 209 VIRTIO_MMIO_QUEUE_READY, 1); 210 } 211 } 212 213 void 214 virtio_mmio_setup_intrs(struct virtio_softc *vsc) 215 { 216 } 217 218 int 219 virtio_mmio_get_status(struct virtio_softc *vsc) 220 { 221 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 222 223 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, 224 VIRTIO_MMIO_STATUS); 225 } 226 227 void 228 virtio_mmio_set_status(struct virtio_softc *vsc, int status) 229 { 230 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 231 int old = 0; 232 233 if (status == 0) { 234 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_STATUS, 235 0); 236 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, 237 VIRTIO_MMIO_STATUS) != 0) { 238 CPU_BUSY_CYCLE(); 239 } 240 } else { 241 old = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 242 VIRTIO_MMIO_STATUS); 243 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_STATUS, 244 status|old); 245 } 246 } 247 248 int 249 virtio_mmio_match(struct device *parent, void *cfdata, void *aux) 250 { 251 struct fdt_attach_args *faa = aux; 252 253 return OF_is_compatible(faa->fa_node, "virtio,mmio"); 254 } 255 256 void 257 virtio_mmio_attach(struct device *parent, struct device *self, void *aux) 258 { 259 struct fdt_attach_args *faa = aux; 260 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)self; 261 struct virtio_softc *vsc = &sc->sc_sc; 262 uint32_t id, magic; 263 struct virtio_mmio_attach_args vma = { { 0 }, faa }; 264 265 if (faa->fa_nreg < 1) { 266 printf(": no register data\n"); 267 return; 268 } 269 270 sc->sc_iosize = faa->fa_reg[0].size; 271 sc->sc_iot = faa->fa_iot; 272 sc->sc_dmat = faa->fa_dmat; 273 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size, 274 0, &sc->sc_ioh)) 275 panic("%s: bus_space_map failed!", __func__); 276 277 magic = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 278 VIRTIO_MMIO_MAGIC_VALUE); 279 if (magic != VIRTIO_MMIO_MAGIC) { 280 printf(": wrong magic value 0x%08x; giving up\n", magic); 281 return; 282 } 283 284 sc->sc_version = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 285 VIRTIO_MMIO_VERSION); 286 if (sc->sc_version < 1 || sc->sc_version > 2) { 287 printf(": unknown version 0x%02x; giving up\n", sc->sc_version); 288 return; 289 } 290 291 id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_DEVICE_ID); 292 printf(": Virtio %s Device", virtio_device_string(id)); 293 294 printf("\n"); 295 296 /* No device connected. */ 297 if (id == 0) 298 return; 299 300 if (sc->sc_version == 1) 301 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 302 VIRTIO_MMIO_GUEST_PAGE_SIZE, PAGE_SIZE); 303 304 vsc->sc_ops = &virtio_mmio_ops; 305 vsc->sc_dmat = sc->sc_dmat; 306 sc->sc_config_offset = VIRTIO_MMIO_CONFIG; 307 308 virtio_device_reset(vsc); 309 virtio_mmio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK); 310 virtio_mmio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER); 311 312 vma.vma_va.va_devid = id; 313 vma.vma_va.va_nintr = 1; 314 vsc->sc_child = NULL; 315 config_found(self, &vma, NULL); 316 if (vsc->sc_child == NULL) { 317 printf("%s: no matching child driver; not configured\n", 318 vsc->sc_dev.dv_xname); 319 goto fail; 320 } 321 if (vsc->sc_child == VIRTIO_CHILD_ERROR) { 322 printf("%s: virtio configuration failed\n", 323 vsc->sc_dev.dv_xname); 324 goto fail; 325 } 326 327 return; 328 329 fail: 330 virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED); 331 } 332 333 int 334 virtio_mmio_attach_finish(struct virtio_softc *vsc, 335 struct virtio_attach_args *va) 336 { 337 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 338 struct virtio_mmio_attach_args *vma = 339 (struct virtio_mmio_attach_args *)va; 340 341 sc->sc_ih = fdt_intr_establish(vma->vma_fa->fa_node, vsc->sc_ipl, 342 virtio_mmio_intr, sc, vsc->sc_dev.dv_xname); 343 if (sc->sc_ih == NULL) { 344 printf("%s: couldn't establish interrupt\n", 345 vsc->sc_dev.dv_xname); 346 return -EIO; 347 } 348 return 0; 349 } 350 351 int 352 virtio_mmio_detach(struct device *self, int flags) 353 { 354 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)self; 355 struct virtio_softc *vsc = &sc->sc_sc; 356 int r; 357 358 if (vsc->sc_child != 0 && vsc->sc_child != VIRTIO_CHILD_ERROR) { 359 r = config_detach(vsc->sc_child, flags); 360 if (r) 361 return r; 362 } 363 KASSERT(vsc->sc_child == 0 || vsc->sc_child == VIRTIO_CHILD_ERROR); 364 KASSERT(vsc->sc_vqs == 0); 365 fdt_intr_disestablish(sc->sc_ih); 366 sc->sc_ih = 0; 367 if (sc->sc_iosize) 368 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); 369 sc->sc_iosize = 0; 370 371 return 0; 372 } 373 374 /* 375 * Feature negotiation. 376 * Prints available / negotiated features if guest_feature_names != NULL and 377 * VIRTIO_DEBUG is 1 378 */ 379 int 380 virtio_mmio_negotiate_features(struct virtio_softc *vsc, 381 const struct virtio_feature_name *guest_feature_names) 382 { 383 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 384 uint64_t host, neg; 385 386 vsc->sc_active_features = 0; 387 388 /* 389 * We enable indirect descriptors by default. They can be switched 390 * off by setting bit 1 in the driver flags, see config(8). 391 */ 392 if (!(vsc->sc_dev.dv_cfdata->cf_flags & VIRTIO_CF_NO_INDIRECT) && 393 !(vsc->sc_child->dv_cfdata->cf_flags & VIRTIO_CF_NO_INDIRECT)) { 394 vsc->sc_driver_features |= VIRTIO_F_RING_INDIRECT_DESC; 395 } else if (guest_feature_names != NULL) { 396 printf("RingIndirectDesc disabled by UKC\n"); 397 } 398 /* 399 * The driver must add VIRTIO_F_RING_EVENT_IDX if it supports it. 400 * If it did, check if it is disabled by bit 2 in the driver flags. 401 */ 402 if ((vsc->sc_driver_features & VIRTIO_F_RING_EVENT_IDX) && 403 ((vsc->sc_dev.dv_cfdata->cf_flags & VIRTIO_CF_NO_EVENT_IDX) || 404 (vsc->sc_child->dv_cfdata->cf_flags & VIRTIO_CF_NO_EVENT_IDX))) { 405 if (guest_feature_names != NULL) 406 printf(" RingEventIdx disabled by UKC"); 407 vsc->sc_driver_features &= ~(VIRTIO_F_RING_EVENT_IDX); 408 } 409 410 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 411 VIRTIO_MMIO_HOST_FEATURES_SEL, 0); 412 host = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 413 VIRTIO_MMIO_HOST_FEATURES); 414 neg = host & vsc->sc_driver_features; 415 #if VIRTIO_DEBUG 416 if (guest_feature_names) 417 virtio_log_features(host, neg, guest_feature_names); 418 #endif 419 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 420 VIRTIO_MMIO_GUEST_FEATURES_SEL, 0); 421 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 422 VIRTIO_MMIO_GUEST_FEATURES, neg); 423 vsc->sc_active_features = neg; 424 if (neg & VIRTIO_F_RING_INDIRECT_DESC) 425 vsc->sc_indirect = 1; 426 else 427 vsc->sc_indirect = 0; 428 429 return 0; 430 } 431 432 /* 433 * Device configuration registers. 434 */ 435 uint8_t 436 virtio_mmio_read_device_config_1(struct virtio_softc *vsc, int index) 437 { 438 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 439 return bus_space_read_1(sc->sc_iot, sc->sc_ioh, 440 sc->sc_config_offset + index); 441 } 442 443 uint16_t 444 virtio_mmio_read_device_config_2(struct virtio_softc *vsc, int index) 445 { 446 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 447 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, 448 sc->sc_config_offset + index); 449 } 450 451 uint32_t 452 virtio_mmio_read_device_config_4(struct virtio_softc *vsc, int index) 453 { 454 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 455 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, 456 sc->sc_config_offset + index); 457 } 458 459 uint64_t 460 virtio_mmio_read_device_config_8(struct virtio_softc *vsc, int index) 461 { 462 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 463 uint64_t r; 464 465 r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 466 sc->sc_config_offset + index + sizeof(uint32_t)); 467 r <<= 32; 468 r += bus_space_read_4(sc->sc_iot, sc->sc_ioh, 469 sc->sc_config_offset + index); 470 return r; 471 } 472 473 void 474 virtio_mmio_write_device_config_1(struct virtio_softc *vsc, 475 int index, uint8_t value) 476 { 477 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 478 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 479 sc->sc_config_offset + index, value); 480 } 481 482 void 483 virtio_mmio_write_device_config_2(struct virtio_softc *vsc, 484 int index, uint16_t value) 485 { 486 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 487 bus_space_write_2(sc->sc_iot, sc->sc_ioh, 488 sc->sc_config_offset + index, value); 489 } 490 491 void 492 virtio_mmio_write_device_config_4(struct virtio_softc *vsc, 493 int index, uint32_t value) 494 { 495 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 496 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 497 sc->sc_config_offset + index, value); 498 } 499 500 void 501 virtio_mmio_write_device_config_8(struct virtio_softc *vsc, 502 int index, uint64_t value) 503 { 504 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 505 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 506 sc->sc_config_offset + index, 507 value & 0xffffffff); 508 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 509 sc->sc_config_offset + index + sizeof(uint32_t), 510 value >> 32); 511 } 512 513 /* 514 * Interrupt handler. 515 */ 516 int 517 virtio_mmio_intr(void *arg) 518 { 519 struct virtio_mmio_softc *sc = arg; 520 struct virtio_softc *vsc = &sc->sc_sc; 521 int isr, r = 0; 522 523 /* check and ack the interrupt */ 524 isr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 525 VIRTIO_MMIO_INTERRUPT_STATUS); 526 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 527 VIRTIO_MMIO_INTERRUPT_ACK, isr); 528 if ((isr & VIRTIO_MMIO_INT_CONFIG) && 529 (vsc->sc_config_change != NULL)) 530 r = (vsc->sc_config_change)(vsc); 531 if ((isr & VIRTIO_MMIO_INT_VRING)) 532 r |= virtio_check_vqs(vsc); 533 534 return r; 535 } 536 537 void 538 virtio_mmio_kick(struct virtio_softc *vsc, uint16_t idx) 539 { 540 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 541 bus_space_write_4(sc->sc_iot, sc->sc_ioh, VIRTIO_MMIO_QUEUE_NOTIFY, 542 idx); 543 } 544 545 void 546 virtio_mmio_intr_barrier(struct virtio_softc *vsc) 547 { 548 struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc; 549 if (sc->sc_ih) 550 intr_barrier(sc->sc_ih); 551 } 552 553 int 554 virtio_mmio_intr_establish(struct virtio_softc *vsc, 555 struct virtio_attach_args *va, int vec, struct cpu_info *ci, 556 int (*func)(void *), void *arg) 557 { 558 return ENXIO; 559 } 560