1 /* $OpenBSD: vdsp.c,v 1.27 2014/07/12 18:44:43 tedu Exp $ */ 2 /* 3 * Copyright (c) 2009, 2011, 2014 Mark Kettenis 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/conf.h> 20 #include <sys/proc.h> 21 #include <sys/buf.h> 22 #include <sys/device.h> 23 #include <sys/disklabel.h> 24 #include <sys/fcntl.h> 25 #include <sys/malloc.h> 26 #include <sys/namei.h> 27 #include <sys/systm.h> 28 #include <sys/task.h> 29 #include <sys/vnode.h> 30 31 #include <machine/autoconf.h> 32 #include <machine/conf.h> 33 #include <machine/hypervisor.h> 34 #include <machine/mdesc.h> 35 36 #include <uvm/uvm_extern.h> 37 38 #include <scsi/scsi_all.h> 39 #include <scsi/scsi_disk.h> 40 #include <scsi/scsiconf.h> 41 42 #include <isofs/cd9660/iso.h> 43 44 #include <dev/sun/disklabel.h> 45 46 #include <sparc64/dev/cbusvar.h> 47 #include <sparc64/dev/ldcvar.h> 48 #include <sparc64/dev/viovar.h> 49 50 #ifdef VDSP_DEBUG 51 #define DPRINTF(x) printf x 52 #else 53 #define DPRINTF(x) 54 #endif 55 56 #define VDSK_TX_ENTRIES 64 57 #define VDSK_RX_ENTRIES 64 58 59 #define VDSK_MAX_DESCRIPTORS 1024 60 #define VDSK_MAX_DESCRIPTOR_SIZE 512 61 62 struct vd_attr_info { 63 struct vio_msg_tag tag; 64 uint8_t xfer_mode; 65 uint8_t vd_type; 66 uint8_t vd_mtype; 67 uint8_t _reserved1; 68 uint32_t vdisk_block_size; 69 uint64_t operations; 70 uint64_t vdisk_size; 71 uint64_t max_xfer_sz; 72 uint64_t _reserved2[2]; 73 }; 74 75 #define VD_DISK_TYPE_SLICE 0x01 76 #define VD_DISK_TYPE_DISK 0x02 77 78 #define VD_MEDIA_TYPE_FIXED 0x01 79 #define VD_MEDIA_TYPE_CD 0x02 80 #define VD_MEDIA_TYPE_DVD 0x03 81 82 /* vDisk version 1.0. */ 83 #define VD_OP_BREAD 0x01 84 #define VD_OP_BWRITE 0x02 85 #define VD_OP_FLUSH 0x03 86 #define VD_OP_GET_WCE 0x04 87 #define VD_OP_SET_WCE 0x05 88 #define VD_OP_GET_VTOC 0x06 89 #define VD_OP_SET_VTOC 0x07 90 #define VD_OP_GET_DISKGEOM 0x08 91 #define VD_OP_SET_DISKGEOM 0x09 92 #define VD_OP_GET_DEVID 0x0b 93 #define VD_OP_GET_EFI 0x0c 94 #define VD_OP_SET_EFI 0x0d 95 96 /* vDisk version 1.1 */ 97 #define VD_OP_SCSICMD 0x0a 98 #define VD_OP_RESET 0x0e 99 #define VD_OP_GET_ACCESS 0x0f 100 #define VD_OP_SET_ACCESS 0x10 101 #define VD_OP_GET_CAPACITY 0x11 102 103 /* Sun standard fields. */ 104 struct sun_vtoc_preamble { 105 char sl_text[128]; 106 u_int sl_version; /* label version */ 107 char sl_volume[8]; /* short volume name */ 108 u_short sl_nparts; /* partition count */ 109 110 struct sun_partinfo sl_part[8]; 111 112 u_int sl_bootinfo[3]; 113 u_int sl_sanity; 114 }; 115 116 struct vd_vtoc_part { 117 uint16_t id_tag; 118 uint16_t perm; 119 uint32_t reserved; 120 uint64_t start; 121 uint64_t nblocks; 122 123 }; 124 struct vd_vtoc { 125 uint8_t volume_name[8]; 126 uint16_t sector_size; 127 uint16_t num_partitions; 128 uint32_t reserved; 129 uint8_t ascii_label[128]; 130 struct vd_vtoc_part partition[8]; 131 }; 132 133 struct vd_diskgeom { 134 uint16_t ncyl; 135 uint16_t acyl; 136 uint16_t bcyl; 137 uint16_t nhead; 138 uint16_t nsect; 139 uint16_t intrlv; 140 uint16_t apc; 141 uint16_t rpm; 142 uint16_t pcyl; 143 uint16_t write_reinstruct; 144 uint16_t read_reinstruct; 145 }; 146 147 struct vd_desc { 148 struct vio_dring_hdr hdr; 149 uint64_t req_id; 150 uint8_t operation; 151 uint8_t slice; 152 uint16_t _reserved1; 153 uint32_t status; 154 uint64_t offset; 155 uint64_t size; 156 uint32_t ncookies; 157 uint32_t _reserved2; 158 struct ldc_cookie cookie[1]; 159 }; 160 161 #define VD_SLICE_NONE 0xff 162 163 struct vdsk_desc_msg { 164 struct vio_msg_tag tag; 165 uint64_t seq_no; 166 uint64_t desc_handle; 167 uint64_t req_id; 168 uint8_t operation; 169 uint8_t slice; 170 uint16_t _reserved1; 171 uint32_t status; 172 uint64_t offset; 173 uint64_t size; 174 uint32_t ncookies; 175 uint32_t _reserved2; 176 struct ldc_cookie cookie[1]; 177 }; 178 179 /* 180 * We support vDisk 1.1. 181 */ 182 #define VDSK_MAJOR 1 183 #define VDSK_MINOR 1 184 185 /* 186 * But we only support a subset of the defined commands. 187 */ 188 #define VD_OP_MASK \ 189 ((1 << VD_OP_BREAD) | (1 << VD_OP_BWRITE) | (1 << VD_OP_FLUSH) | \ 190 (1 << VD_OP_GET_WCE) | (1 << VD_OP_SET_WCE) | \ 191 (1 << VD_OP_GET_VTOC) | (1 << VD_OP_SET_VTOC) | \ 192 (1 << VD_OP_GET_DISKGEOM)) 193 194 struct vdsp_softc { 195 struct device sc_dv; 196 int sc_idx; 197 bus_space_tag_t sc_bustag; 198 bus_dma_tag_t sc_dmatag; 199 200 uint64_t sc_tx_sysino; 201 uint64_t sc_rx_sysino; 202 void *sc_tx_ih; 203 void *sc_rx_ih; 204 205 struct ldc_conn sc_lc; 206 207 uint16_t sc_vio_state; 208 #define VIO_SND_VER_INFO 0x0001 209 #define VIO_ACK_VER_INFO 0x0002 210 #define VIO_RCV_VER_INFO 0x0004 211 #define VIO_SND_ATTR_INFO 0x0008 212 #define VIO_ACK_ATTR_INFO 0x0010 213 #define VIO_RCV_ATTR_INFO 0x0020 214 #define VIO_SND_DRING_REG 0x0040 215 #define VIO_ACK_DRING_REG 0x0080 216 #define VIO_RCV_DRING_REG 0x0100 217 #define VIO_SND_RDX 0x0200 218 #define VIO_ACK_RDX 0x0400 219 #define VIO_RCV_RDX 0x0800 220 221 uint16_t sc_major; 222 uint16_t sc_minor; 223 224 uint8_t sc_xfer_mode; 225 226 uint32_t sc_local_sid; 227 uint64_t sc_seq_no; 228 229 uint64_t sc_dring_ident; 230 uint32_t sc_num_descriptors; 231 uint32_t sc_descriptor_size; 232 struct ldc_cookie sc_dring_cookie; 233 234 struct task sc_open_task; 235 struct task sc_alloc_task; 236 struct task sc_close_task; 237 238 struct vdsk_desc_msg *sc_desc_msg[VDSK_RX_ENTRIES]; 239 int sc_desc_head; 240 int sc_desc_tail; 241 242 struct task sc_read_task; 243 244 caddr_t sc_vd; 245 struct task *sc_vd_task; 246 247 uint32_t sc_vdisk_block_size; 248 uint64_t sc_vdisk_size; 249 250 struct vnode *sc_vp; 251 252 struct sun_disklabel *sc_label; 253 uint16_t sc_ncyl; 254 uint16_t sc_acyl; 255 uint16_t sc_nhead; 256 uint16_t sc_nsect; 257 }; 258 259 int vdsp_match(struct device *, void *, void *); 260 void vdsp_attach(struct device *, struct device *, void *); 261 262 struct cfattach vdsp_ca = { 263 sizeof(struct vdsp_softc), vdsp_match, vdsp_attach 264 }; 265 266 struct cfdriver vdsp_cd = { 267 NULL, "vdsp", DV_DULL 268 }; 269 270 int vdsp_tx_intr(void *); 271 int vdsp_rx_intr(void *); 272 273 void vdsp_rx_data(struct ldc_conn *, struct ldc_pkt *); 274 void vdsp_rx_vio_ctrl(struct vdsp_softc *, struct vio_msg *); 275 void vdsp_rx_vio_ver_info(struct vdsp_softc *, struct vio_msg_tag *); 276 void vdsp_rx_vio_attr_info(struct vdsp_softc *, struct vio_msg_tag *); 277 void vdsp_rx_vio_dring_reg(struct vdsp_softc *, struct vio_msg_tag *); 278 void vdsp_rx_vio_rdx(struct vdsp_softc *sc, struct vio_msg_tag *); 279 void vdsp_rx_vio_data(struct vdsp_softc *sc, struct vio_msg *); 280 void vdsp_rx_vio_dring_data(struct vdsp_softc *sc, 281 struct vio_msg_tag *); 282 void vdsp_rx_vio_desc_data(struct vdsp_softc *sc, struct vio_msg_tag *); 283 284 void vdsp_ldc_reset(struct ldc_conn *); 285 void vdsp_ldc_start(struct ldc_conn *); 286 287 void vdsp_sendmsg(struct vdsp_softc *, void *, size_t, int dowait); 288 289 void vdsp_open(void *, void *); 290 void vdsp_close(void *, void *); 291 void vdsp_alloc(void *, void *); 292 void vdsp_readlabel(struct vdsp_softc *); 293 int vdsp_writelabel(struct vdsp_softc *); 294 int vdsp_is_iso(struct vdsp_softc *); 295 void vdsp_read(void *, void *); 296 void vdsp_read_desc(struct vdsp_softc *, struct vdsk_desc_msg *); 297 void vdsp_read_dring(void *, void *); 298 void vdsp_write_dring(void *, void *); 299 void vdsp_flush_dring(void *, void *); 300 void vdsp_get_vtoc(void *, void *); 301 void vdsp_set_vtoc(void *, void *); 302 void vdsp_get_diskgeom(void *, void *); 303 void vdsp_unimp(void *, void *); 304 305 void vdsp_ack_desc(struct vdsp_softc *, struct vd_desc *); 306 307 int 308 vdsp_match(struct device *parent, void *match, void *aux) 309 { 310 struct cbus_attach_args *ca = aux; 311 312 if (strcmp(ca->ca_name, "vds-port") == 0) 313 return (1); 314 315 return (0); 316 } 317 318 void 319 vdsp_attach(struct device *parent, struct device *self, void *aux) 320 { 321 struct vdsp_softc *sc = (struct vdsp_softc *)self; 322 struct cbus_attach_args *ca = aux; 323 struct ldc_conn *lc; 324 325 sc->sc_idx = ca->ca_idx; 326 sc->sc_bustag = ca->ca_bustag; 327 sc->sc_dmatag = ca->ca_dmatag; 328 329 if (cbus_intr_map(ca->ca_node, ca->ca_tx_ino, &sc->sc_tx_sysino) || 330 cbus_intr_map(ca->ca_node, ca->ca_rx_ino, &sc->sc_rx_sysino)) { 331 printf(": can't map interrupt\n"); 332 return; 333 } 334 printf(": ivec 0x%llx, 0x%llx", sc->sc_tx_sysino, sc->sc_rx_sysino); 335 336 /* 337 * Un-configure queues before registering interrupt handlers, 338 * such that we dont get any stale LDC packets or events. 339 */ 340 hv_ldc_tx_qconf(ca->ca_id, 0, 0); 341 hv_ldc_rx_qconf(ca->ca_id, 0, 0); 342 343 sc->sc_tx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_tx_sysino, 344 IPL_BIO, 0, vdsp_tx_intr, sc, sc->sc_dv.dv_xname); 345 sc->sc_rx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_rx_sysino, 346 IPL_BIO, 0, vdsp_rx_intr, sc, sc->sc_dv.dv_xname); 347 if (sc->sc_tx_ih == NULL || sc->sc_rx_ih == NULL) { 348 printf(", can't establish interrupt\n"); 349 return; 350 } 351 352 lc = &sc->sc_lc; 353 lc->lc_id = ca->ca_id; 354 lc->lc_sc = sc; 355 lc->lc_reset = vdsp_ldc_reset; 356 lc->lc_start = vdsp_ldc_start; 357 lc->lc_rx_data = vdsp_rx_data; 358 359 lc->lc_txq = ldc_queue_alloc(sc->sc_dmatag, VDSK_TX_ENTRIES); 360 if (lc->lc_txq == NULL) { 361 printf(", can't allocate tx queue\n"); 362 return; 363 } 364 365 lc->lc_rxq = ldc_queue_alloc(sc->sc_dmatag, VDSK_RX_ENTRIES); 366 if (lc->lc_rxq == NULL) { 367 printf(", can't allocate rx queue\n"); 368 goto free_txqueue; 369 } 370 371 task_set(&sc->sc_open_task, vdsp_open, sc, NULL); 372 task_set(&sc->sc_alloc_task, vdsp_alloc, sc, NULL); 373 task_set(&sc->sc_close_task, vdsp_close, sc, NULL); 374 task_set(&sc->sc_read_task, vdsp_read, sc, NULL); 375 376 printf("\n"); 377 378 return; 379 380 #if 0 381 free_rxqueue: 382 ldc_queue_free(sc->sc_dmatag, lc->lc_rxq); 383 #endif 384 free_txqueue: 385 ldc_queue_free(sc->sc_dmatag, lc->lc_txq); 386 } 387 388 int 389 vdsp_tx_intr(void *arg) 390 { 391 struct vdsp_softc *sc = arg; 392 struct ldc_conn *lc = &sc->sc_lc; 393 uint64_t tx_head, tx_tail, tx_state; 394 int err; 395 396 err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state); 397 if (err != H_EOK) { 398 printf("hv_ldc_rx_get_state %d\n", err); 399 return (0); 400 } 401 402 if (tx_state != lc->lc_tx_state) { 403 switch (tx_state) { 404 case LDC_CHANNEL_DOWN: 405 DPRINTF(("Tx link down\n")); 406 break; 407 case LDC_CHANNEL_UP: 408 DPRINTF(("Tx link up\n")); 409 break; 410 case LDC_CHANNEL_RESET: 411 DPRINTF(("Tx link reset\n")); 412 break; 413 } 414 lc->lc_tx_state = tx_state; 415 } 416 417 wakeup(lc->lc_txq); 418 return (1); 419 } 420 421 int 422 vdsp_rx_intr(void *arg) 423 { 424 struct vdsp_softc *sc = arg; 425 struct ldc_conn *lc = &sc->sc_lc; 426 uint64_t rx_head, rx_tail, rx_state; 427 struct ldc_pkt *lp; 428 int err; 429 430 err = hv_ldc_rx_get_state(lc->lc_id, &rx_head, &rx_tail, &rx_state); 431 if (err == H_EINVAL) 432 return (0); 433 if (err != H_EOK) { 434 printf("hv_ldc_rx_get_state %d\n", err); 435 return (0); 436 } 437 438 if (rx_state != lc->lc_rx_state) { 439 switch (rx_state) { 440 case LDC_CHANNEL_DOWN: 441 DPRINTF(("Rx link down\n")); 442 lc->lc_tx_seqid = 0; 443 lc->lc_state = 0; 444 lc->lc_reset(lc); 445 break; 446 case LDC_CHANNEL_UP: 447 DPRINTF(("Rx link up\n")); 448 break; 449 case LDC_CHANNEL_RESET: 450 DPRINTF(("Rx link reset\n")); 451 lc->lc_tx_seqid = 0; 452 lc->lc_state = 0; 453 lc->lc_reset(lc); 454 break; 455 } 456 lc->lc_rx_state = rx_state; 457 return (1); 458 } 459 460 if (lc->lc_rx_state == LDC_CHANNEL_DOWN) 461 return (1); 462 463 lp = (struct ldc_pkt *)(lc->lc_rxq->lq_va + rx_head); 464 switch (lp->type) { 465 case LDC_CTRL: 466 ldc_rx_ctrl(lc, lp); 467 break; 468 469 case LDC_DATA: 470 ldc_rx_data(lc, lp); 471 break; 472 473 default: 474 DPRINTF(("0x%02x/0x%02x/0x%02x\n", lp->type, lp->stype, 475 lp->ctrl)); 476 ldc_reset(lc); 477 break; 478 } 479 480 rx_head += sizeof(*lp); 481 rx_head &= ((lc->lc_rxq->lq_nentries * sizeof(*lp)) - 1); 482 err = hv_ldc_rx_set_qhead(lc->lc_id, rx_head); 483 if (err != H_EOK) 484 printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err); 485 486 return (1); 487 } 488 489 void 490 vdsp_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp) 491 { 492 struct vio_msg *vm = (struct vio_msg *)lp; 493 494 switch (vm->type) { 495 case VIO_TYPE_CTRL: 496 if ((lp->env & LDC_FRAG_START) == 0 && 497 (lp->env & LDC_FRAG_STOP) == 0) 498 return; 499 vdsp_rx_vio_ctrl(lc->lc_sc, vm); 500 break; 501 502 case VIO_TYPE_DATA: 503 if((lp->env & LDC_FRAG_START) == 0) 504 return; 505 vdsp_rx_vio_data(lc->lc_sc, vm); 506 break; 507 508 default: 509 DPRINTF(("Unhandled packet type 0x%02x\n", vm->type)); 510 ldc_reset(lc); 511 break; 512 } 513 } 514 515 void 516 vdsp_rx_vio_ctrl(struct vdsp_softc *sc, struct vio_msg *vm) 517 { 518 struct vio_msg_tag *tag = (struct vio_msg_tag *)&vm->type; 519 520 switch (tag->stype_env) { 521 case VIO_VER_INFO: 522 vdsp_rx_vio_ver_info(sc, tag); 523 break; 524 case VIO_ATTR_INFO: 525 vdsp_rx_vio_attr_info(sc, tag); 526 break; 527 case VIO_DRING_REG: 528 vdsp_rx_vio_dring_reg(sc, tag); 529 break; 530 case VIO_RDX: 531 vdsp_rx_vio_rdx(sc, tag); 532 break; 533 default: 534 DPRINTF(("CTRL/0x%02x/0x%04x\n", tag->stype, tag->stype_env)); 535 break; 536 } 537 } 538 539 void 540 vdsp_rx_vio_ver_info(struct vdsp_softc *sc, struct vio_msg_tag *tag) 541 { 542 struct vio_ver_info *vi = (struct vio_ver_info *)tag; 543 544 switch (vi->tag.stype) { 545 case VIO_SUBTYPE_INFO: 546 DPRINTF(("CTRL/INFO/VER_INFO\n")); 547 548 /* Make sure we're talking to a virtual disk. */ 549 if (vi->dev_class != VDEV_DISK) { 550 /* Huh, we're not talking to a disk device? */ 551 printf("%s: peer is not a disk device\n", 552 sc->sc_dv.dv_xname); 553 vi->tag.stype = VIO_SUBTYPE_NACK; 554 vi->major = 0; 555 vdsp_sendmsg(sc, vi, sizeof(*vi), 0); 556 return; 557 } 558 559 if (vi->major != VDSK_MAJOR) { 560 vi->tag.stype = VIO_SUBTYPE_NACK; 561 vi->major = VDSK_MAJOR; 562 vi->minor = VDSK_MINOR; 563 vdsp_sendmsg(sc, vi, sizeof(*vi), 0); 564 return; 565 } 566 567 sc->sc_major = vi->major; 568 sc->sc_minor = vi->minor; 569 sc->sc_local_sid = vi->tag.sid; 570 571 vi->tag.stype = VIO_SUBTYPE_ACK; 572 if (vi->minor > VDSK_MINOR) 573 vi->minor = VDSK_MINOR; 574 vi->dev_class = VDEV_DISK_SERVER; 575 vdsp_sendmsg(sc, vi, sizeof(*vi), 0); 576 sc->sc_vio_state |= VIO_RCV_VER_INFO; 577 break; 578 579 case VIO_SUBTYPE_ACK: 580 DPRINTF(("CTRL/ACK/VER_INFO\n")); 581 break; 582 583 default: 584 DPRINTF(("CTRL/0x%02x/VER_INFO\n", vi->tag.stype)); 585 break; 586 } 587 } 588 589 void 590 vdsp_rx_vio_attr_info(struct vdsp_softc *sc, struct vio_msg_tag *tag) 591 { 592 struct vd_attr_info *ai = (struct vd_attr_info *)tag; 593 594 switch (ai->tag.stype) { 595 case VIO_SUBTYPE_INFO: 596 DPRINTF(("CTRL/INFO/ATTR_INFO\n")); 597 598 if (ai->xfer_mode != VIO_DESC_MODE && 599 ai->xfer_mode != VIO_DRING_MODE) { 600 printf("%s: peer uses unsupported xfer mode 0x%02x\n", 601 sc->sc_dv.dv_xname, ai->xfer_mode); 602 ai->tag.stype = VIO_SUBTYPE_NACK; 603 vdsp_sendmsg(sc, ai, sizeof(*ai), 0); 604 return; 605 } 606 sc->sc_xfer_mode = ai->xfer_mode; 607 sc->sc_vio_state |= VIO_RCV_ATTR_INFO; 608 609 task_add(systq, &sc->sc_open_task); 610 break; 611 612 case VIO_SUBTYPE_ACK: 613 DPRINTF(("CTRL/ACK/ATTR_INFO\n")); 614 break; 615 616 default: 617 DPRINTF(("CTRL/0x%02x/ATTR_INFO\n", ai->tag.stype)); 618 break; 619 } 620 } 621 622 void 623 vdsp_rx_vio_dring_reg(struct vdsp_softc *sc, struct vio_msg_tag *tag) 624 { 625 struct vio_dring_reg *dr = (struct vio_dring_reg *)tag; 626 627 switch (dr->tag.stype) { 628 case VIO_SUBTYPE_INFO: 629 DPRINTF(("CTRL/INFO/DRING_REG\n")); 630 631 if (dr->num_descriptors > VDSK_MAX_DESCRIPTORS || 632 dr->descriptor_size > VDSK_MAX_DESCRIPTOR_SIZE || 633 dr->ncookies > 1) { 634 dr->tag.stype = VIO_SUBTYPE_NACK; 635 vdsp_sendmsg(sc, dr, sizeof(*dr), 0); 636 return; 637 } 638 sc->sc_num_descriptors = dr->num_descriptors; 639 sc->sc_descriptor_size = dr->descriptor_size; 640 sc->sc_dring_cookie = dr->cookie[0]; 641 sc->sc_vio_state |= VIO_RCV_DRING_REG; 642 643 task_add(systq, &sc->sc_alloc_task); 644 break; 645 646 case VIO_SUBTYPE_ACK: 647 DPRINTF(("CTRL/ACK/DRING_REG\n")); 648 break; 649 650 default: 651 DPRINTF(("CTRL/0x%02x/DRING_REG\n", dr->tag.stype)); 652 break; 653 } 654 } 655 656 void 657 vdsp_rx_vio_rdx(struct vdsp_softc *sc, struct vio_msg_tag *tag) 658 { 659 switch(tag->stype) { 660 case VIO_SUBTYPE_INFO: 661 DPRINTF(("CTRL/INFO/RDX\n")); 662 663 tag->stype = VIO_SUBTYPE_ACK; 664 tag->sid = sc->sc_local_sid; 665 vdsp_sendmsg(sc, tag, sizeof(*tag), 0); 666 sc->sc_vio_state |= VIO_RCV_RDX; 667 break; 668 669 case VIO_SUBTYPE_ACK: 670 DPRINTF(("CTRL/ACK/RDX\n")); 671 break; 672 673 default: 674 DPRINTF(("CTRL/0x%02x/RDX (VIO)\n", tag->stype)); 675 break; 676 } 677 } 678 679 void 680 vdsp_rx_vio_data(struct vdsp_softc *sc, struct vio_msg *vm) 681 { 682 struct vio_msg_tag *tag = (struct vio_msg_tag *)&vm->type; 683 684 if (!ISSET(sc->sc_vio_state, VIO_RCV_RDX)) { 685 DPRINTF(("Spurious DATA/0x%02x/0x%04x\n", tag->stype, 686 tag->stype_env)); 687 return; 688 } 689 690 switch(tag->stype_env) { 691 case VIO_DESC_DATA: 692 vdsp_rx_vio_desc_data(sc, tag); 693 break; 694 695 case VIO_DRING_DATA: 696 vdsp_rx_vio_dring_data(sc, tag); 697 break; 698 699 default: 700 DPRINTF(("DATA/0x%02x/0x%04x\n", tag->stype, tag->stype_env)); 701 break; 702 } 703 } 704 705 void 706 vdsp_rx_vio_dring_data(struct vdsp_softc *sc, struct vio_msg_tag *tag) 707 { 708 struct vio_dring_msg *dm = (struct vio_dring_msg *)tag; 709 struct vd_desc *vd; 710 struct task *task; 711 vaddr_t va; 712 paddr_t pa; 713 uint64_t size, off; 714 psize_t nbytes; 715 int err; 716 717 switch(tag->stype) { 718 case VIO_SUBTYPE_INFO: 719 DPRINTF(("DATA/INFO/DRING_DATA\n")); 720 721 if (dm->dring_ident != sc->sc_dring_ident || 722 dm->start_idx >= sc->sc_num_descriptors) { 723 dm->tag.stype = VIO_SUBTYPE_NACK; 724 vdsp_sendmsg(sc, dm, sizeof(*dm), 0); 725 return; 726 } 727 728 off = dm->start_idx * sc->sc_descriptor_size; 729 vd = (struct vd_desc *)(sc->sc_vd + off); 730 va = (vaddr_t)vd; 731 size = sc->sc_descriptor_size; 732 while (size > 0) { 733 pmap_extract(pmap_kernel(), va, &pa); 734 nbytes = MIN(size, PAGE_SIZE - (off & PAGE_MASK)); 735 err = hv_ldc_copy(sc->sc_lc.lc_id, LDC_COPY_IN, 736 sc->sc_dring_cookie.addr + off, pa, 737 nbytes, &nbytes); 738 if (err != H_EOK) { 739 printf("%s: hv_ldc_copy %d\n", __func__, err); 740 return; 741 } 742 va += nbytes; 743 size -= nbytes; 744 off += nbytes; 745 } 746 task = &sc->sc_vd_task[dm->start_idx]; 747 748 DPRINTF(("%s: start_idx %d, end_idx %d, operation %x\n", 749 sc->sc_dv.dv_xname, dm->start_idx, dm->end_idx, 750 vd->operation)); 751 switch (vd->operation) { 752 case VD_OP_BREAD: 753 task_set(task, vdsp_read_dring, sc, vd); 754 break; 755 case VD_OP_BWRITE: 756 task_set(task, vdsp_write_dring, sc, vd); 757 break; 758 case VD_OP_FLUSH: 759 task_set(task, vdsp_flush_dring, sc, vd); 760 break; 761 case VD_OP_GET_VTOC: 762 task_set(task, vdsp_get_vtoc, sc, vd); 763 break; 764 case VD_OP_SET_VTOC: 765 task_set(task, vdsp_set_vtoc, sc, vd); 766 break; 767 case VD_OP_GET_DISKGEOM: 768 task_set(task, vdsp_get_diskgeom, sc, vd); 769 break; 770 case VD_OP_GET_WCE: 771 case VD_OP_SET_WCE: 772 case VD_OP_GET_DEVID: 773 /* 774 * Solaris issues VD_OP_GET_DEVID despite the 775 * fact that we don't advertise it. It seems 776 * to be able to handle failure just fine, so 777 * we silently ignore it. 778 */ 779 task_set(task, vdsp_unimp, sc, vd); 780 break; 781 default: 782 printf("%s: unsupported operation 0x%02x\n", 783 sc->sc_dv.dv_xname, vd->operation); 784 task_set(task, vdsp_unimp, sc, vd); 785 break; 786 } 787 task_add(systq, task); 788 break; 789 790 case VIO_SUBTYPE_ACK: 791 DPRINTF(("DATA/ACK/DRING_DATA\n")); 792 break; 793 794 case VIO_SUBTYPE_NACK: 795 DPRINTF(("DATA/NACK/DRING_DATA\n")); 796 break; 797 798 default: 799 DPRINTF(("DATA/0x%02x/DRING_DATA\n", tag->stype)); 800 break; 801 } 802 } 803 804 void 805 vdsp_rx_vio_desc_data(struct vdsp_softc *sc, struct vio_msg_tag *tag) 806 { 807 struct vdsk_desc_msg *dm = (struct vdsk_desc_msg *)tag; 808 809 switch(tag->stype) { 810 case VIO_SUBTYPE_INFO: 811 DPRINTF(("DATA/INFO/DESC_DATA\n")); 812 813 switch (dm->operation) { 814 case VD_OP_BREAD: 815 sc->sc_desc_msg[sc->sc_desc_head++] = dm; 816 sc->sc_desc_head &= (VDSK_RX_ENTRIES - 1); 817 KASSERT(sc->sc_desc_head != sc->sc_desc_tail); 818 task_add(systq, &sc->sc_read_task); 819 break; 820 default: 821 printf("%s: unsupported operation 0x%02x\n", 822 sc->sc_dv.dv_xname, dm->operation); 823 break; 824 } 825 break; 826 827 case VIO_SUBTYPE_ACK: 828 DPRINTF(("DATA/ACK/DESC_DATA\n")); 829 break; 830 831 case VIO_SUBTYPE_NACK: 832 DPRINTF(("DATA/NACK/DESC_DATA\n")); 833 break; 834 835 default: 836 DPRINTF(("DATA/0x%02x/DESC_DATA\n", tag->stype)); 837 break; 838 } 839 } 840 841 void 842 vdsp_ldc_reset(struct ldc_conn *lc) 843 { 844 struct vdsp_softc *sc = lc->lc_sc; 845 846 sc->sc_desc_head = sc->sc_desc_tail = 0; 847 848 sc->sc_vio_state = 0; 849 sc->sc_seq_no = 0; 850 if (sc->sc_vd) { 851 free(sc->sc_vd, M_DEVBUF, 0); 852 sc->sc_vd = NULL; 853 } 854 if (sc->sc_vd_task) { 855 free(sc->sc_vd_task, M_DEVBUF, 0); 856 sc->sc_vd_task = NULL; 857 } 858 if (sc->sc_label) { 859 free(sc->sc_label, M_DEVBUF, 0); 860 sc->sc_label = NULL; 861 } 862 863 task_add(systq, &sc->sc_close_task); 864 } 865 866 void 867 vdsp_ldc_start(struct ldc_conn *lc) 868 { 869 /* The vDisk client is supposed to initiate the handshake. */ 870 } 871 872 void 873 vdsp_sendmsg(struct vdsp_softc *sc, void *msg, size_t len, int dowait) 874 { 875 struct ldc_conn *lc = &sc->sc_lc; 876 int err; 877 878 do { 879 err = ldc_send_unreliable(lc, msg, len); 880 if (dowait && err == EWOULDBLOCK) { 881 /* 882 * Seems like the hypervisor doesn't actually 883 * generate interrupts for transmit queues, so 884 * we specify a timeout such that we don't 885 * block forever. 886 */ 887 err = tsleep(lc->lc_txq, PWAIT, "vdsp", 1); 888 } 889 } while (dowait && err == EWOULDBLOCK); 890 } 891 892 void 893 vdsp_open(void *arg1, void *arg2) 894 { 895 struct vdsp_softc *sc = arg1; 896 struct proc *p = curproc; 897 struct vd_attr_info ai; 898 899 if (sc->sc_vp == NULL) { 900 struct nameidata nd; 901 struct vattr va; 902 const char *name; 903 int error; 904 905 name = mdesc_get_prop_str(sc->sc_idx, "vds-block-device"); 906 if (name == NULL) 907 return; 908 909 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p); 910 error = vn_open(&nd, FREAD | FWRITE, 0); 911 if (error) { 912 printf("VOP_OPEN: %s, %d\n", name, error); 913 return; 914 } 915 916 error = VOP_GETATTR(nd.ni_vp, &va, p->p_ucred, p); 917 if (error) 918 printf("VOP_GETATTR: %s, %d\n", name, error); 919 sc->sc_vdisk_block_size = DEV_BSIZE; 920 sc->sc_vdisk_size = va.va_size / DEV_BSIZE; 921 922 VOP_UNLOCK(nd.ni_vp, 0, p); 923 sc->sc_vp = nd.ni_vp; 924 925 vdsp_readlabel(sc); 926 } 927 928 bzero(&ai, sizeof(ai)); 929 ai.tag.type = VIO_TYPE_CTRL; 930 ai.tag.stype = VIO_SUBTYPE_ACK; 931 ai.tag.stype_env = VIO_ATTR_INFO; 932 ai.tag.sid = sc->sc_local_sid; 933 ai.xfer_mode = sc->sc_xfer_mode; 934 ai.vd_type = VD_DISK_TYPE_DISK; 935 if (sc->sc_major > 1 || sc->sc_minor >= 1) { 936 if (vdsp_is_iso(sc)) 937 ai.vd_mtype = VD_MEDIA_TYPE_CD; 938 else 939 ai.vd_mtype = VD_MEDIA_TYPE_FIXED; 940 } 941 ai.vdisk_block_size = sc->sc_vdisk_block_size; 942 ai.operations = VD_OP_MASK; 943 ai.vdisk_size = sc->sc_vdisk_size; 944 ai.max_xfer_sz = MAXPHYS / sc->sc_vdisk_block_size; 945 vdsp_sendmsg(sc, &ai, sizeof(ai), 1); 946 } 947 948 void 949 vdsp_close(void *arg1, void *arg2) 950 { 951 struct vdsp_softc *sc = arg1; 952 struct proc *p = curproc; 953 954 if (sc->sc_vp) { 955 vn_close(sc->sc_vp, FREAD | FWRITE, p->p_ucred, p); 956 sc->sc_vp = NULL; 957 } 958 } 959 960 void 961 vdsp_readlabel(struct vdsp_softc *sc) 962 { 963 struct proc *p = curproc; 964 struct iovec iov; 965 struct uio uio; 966 int err; 967 968 if (sc->sc_vp == NULL) 969 return; 970 971 sc->sc_label = malloc(sizeof(*sc->sc_label), M_DEVBUF, M_WAITOK); 972 973 iov.iov_base = sc->sc_label; 974 iov.iov_len = sizeof(*sc->sc_label); 975 uio.uio_iov = &iov; 976 uio.uio_iovcnt = 1; 977 uio.uio_offset = 0; 978 uio.uio_resid = sizeof(*sc->sc_label); 979 uio.uio_segflg = UIO_SYSSPACE; 980 uio.uio_rw = UIO_READ; 981 uio.uio_procp = p; 982 983 vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p); 984 err = VOP_READ(sc->sc_vp, &uio, 0, p->p_ucred); 985 VOP_UNLOCK(sc->sc_vp, 0, p); 986 if (err) { 987 free(sc->sc_label, M_DEVBUF, 0); 988 sc->sc_label = NULL; 989 } 990 } 991 992 int 993 vdsp_writelabel(struct vdsp_softc *sc) 994 { 995 struct proc *p = curproc; 996 struct iovec iov; 997 struct uio uio; 998 int err; 999 1000 if (sc->sc_vp == NULL || sc->sc_label == NULL) 1001 return (EINVAL); 1002 1003 iov.iov_base = sc->sc_label; 1004 iov.iov_len = sizeof(*sc->sc_label); 1005 uio.uio_iov = &iov; 1006 uio.uio_iovcnt = 1; 1007 uio.uio_offset = 0; 1008 uio.uio_resid = sizeof(*sc->sc_label); 1009 uio.uio_segflg = UIO_SYSSPACE; 1010 uio.uio_rw = UIO_WRITE; 1011 uio.uio_procp = p; 1012 1013 vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p); 1014 err = VOP_WRITE(sc->sc_vp, &uio, 0, p->p_ucred); 1015 VOP_UNLOCK(sc->sc_vp, 0, p); 1016 1017 return (err); 1018 } 1019 1020 int 1021 vdsp_is_iso(struct vdsp_softc *sc) 1022 { 1023 struct proc *p = curproc; 1024 struct iovec iov; 1025 struct uio uio; 1026 struct iso_volume_descriptor *vdp; 1027 int err; 1028 1029 if (sc->sc_vp == NULL) 1030 return (0); 1031 1032 vdp = malloc(sizeof(*vdp), M_DEVBUF, M_WAITOK); 1033 1034 iov.iov_base = vdp; 1035 iov.iov_len = sizeof(*vdp); 1036 uio.uio_iov = &iov; 1037 uio.uio_iovcnt = 1; 1038 uio.uio_offset = 16 * ISO_DEFAULT_BLOCK_SIZE; 1039 uio.uio_resid = sizeof(*vdp); 1040 uio.uio_segflg = UIO_SYSSPACE; 1041 uio.uio_rw = UIO_READ; 1042 uio.uio_procp = p; 1043 1044 vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p); 1045 err = VOP_READ(sc->sc_vp, &uio, 0, p->p_ucred); 1046 VOP_UNLOCK(sc->sc_vp, 0, p); 1047 1048 if (err == 0 && memcmp(vdp->id, ISO_STANDARD_ID, sizeof(vdp->id))) 1049 err = ENOENT; 1050 1051 free(vdp, M_DEVBUF, 0); 1052 return (err == 0); 1053 } 1054 1055 void 1056 vdsp_alloc(void *arg1, void *arg2) 1057 { 1058 struct vdsp_softc *sc = arg1; 1059 struct vio_dring_reg dr; 1060 1061 KASSERT(sc->sc_num_descriptors <= VDSK_MAX_DESCRIPTORS); 1062 KASSERT(sc->sc_descriptor_size <= VDSK_MAX_DESCRIPTOR_SIZE); 1063 sc->sc_vd = malloc(sc->sc_num_descriptors * sc->sc_descriptor_size, 1064 M_DEVBUF, M_WAITOK); 1065 sc->sc_vd_task = malloc(sc->sc_num_descriptors * sizeof(struct task), 1066 M_DEVBUF, M_WAITOK); 1067 1068 bzero(&dr, sizeof(dr)); 1069 dr.tag.type = VIO_TYPE_CTRL; 1070 dr.tag.stype = VIO_SUBTYPE_ACK; 1071 dr.tag.stype_env = VIO_DRING_REG; 1072 dr.tag.sid = sc->sc_local_sid; 1073 dr.dring_ident = ++sc->sc_dring_ident; 1074 vdsp_sendmsg(sc, &dr, sizeof(dr), 1); 1075 } 1076 1077 void 1078 vdsp_read(void *arg1, void *arg2) 1079 { 1080 struct vdsp_softc *sc = arg1; 1081 1082 while (sc->sc_desc_tail != sc->sc_desc_head) { 1083 vdsp_read_desc(sc, sc->sc_desc_msg[sc->sc_desc_tail++]); 1084 sc->sc_desc_tail &= (VDSK_RX_ENTRIES - 1); 1085 } 1086 } 1087 1088 void 1089 vdsp_read_desc(struct vdsp_softc *sc, struct vdsk_desc_msg *dm) 1090 { 1091 struct ldc_conn *lc = &sc->sc_lc; 1092 struct proc *p = curproc; 1093 struct iovec iov; 1094 struct uio uio; 1095 caddr_t buf; 1096 vaddr_t va; 1097 paddr_t pa; 1098 uint64_t size, off; 1099 psize_t nbytes; 1100 int err, i; 1101 1102 if (sc->sc_vp == NULL) 1103 return; 1104 1105 buf = malloc(dm->size, M_DEVBUF, M_WAITOK); 1106 1107 iov.iov_base = buf; 1108 iov.iov_len = dm->size; 1109 uio.uio_iov = &iov; 1110 uio.uio_iovcnt = 1; 1111 uio.uio_offset = dm->offset * DEV_BSIZE; 1112 uio.uio_resid = dm->size; 1113 uio.uio_segflg = UIO_SYSSPACE; 1114 uio.uio_rw = UIO_READ; 1115 uio.uio_procp = p; 1116 1117 vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p); 1118 dm->status = VOP_READ(sc->sc_vp, &uio, 0, p->p_ucred); 1119 VOP_UNLOCK(sc->sc_vp, 0, p); 1120 1121 if (dm->status == 0) { 1122 i = 0; 1123 va = (vaddr_t)buf; 1124 size = dm->size; 1125 off = 0; 1126 while (size > 0 && i < dm->ncookies) { 1127 pmap_extract(pmap_kernel(), va, &pa); 1128 nbytes = MIN(size, dm->cookie[i].size - off); 1129 nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK)); 1130 err = hv_ldc_copy(lc->lc_id, LDC_COPY_OUT, 1131 dm->cookie[i].addr + off, pa, nbytes, &nbytes); 1132 if (err != H_EOK) { 1133 printf("%s: hv_ldc_copy: %d\n", __func__, err); 1134 dm->status = EIO; 1135 goto fail; 1136 } 1137 va += nbytes; 1138 size -= nbytes; 1139 off += nbytes; 1140 if (off >= dm->cookie[i].size) { 1141 off = 0; 1142 i++; 1143 } 1144 } 1145 } 1146 1147 fail: 1148 free(buf, M_DEVBUF, 0); 1149 1150 /* ACK the descriptor. */ 1151 dm->tag.stype = VIO_SUBTYPE_ACK; 1152 dm->tag.sid = sc->sc_local_sid; 1153 vdsp_sendmsg(sc, dm, sizeof(*dm) + 1154 (dm->ncookies - 1) * sizeof(struct ldc_cookie), 1); 1155 } 1156 1157 void 1158 vdsp_read_dring(void *arg1, void *arg2) 1159 { 1160 struct vdsp_softc *sc = arg1; 1161 struct ldc_conn *lc = &sc->sc_lc; 1162 struct vd_desc *vd = arg2; 1163 struct proc *p = curproc; 1164 struct iovec iov; 1165 struct uio uio; 1166 caddr_t buf; 1167 vaddr_t va; 1168 paddr_t pa; 1169 uint64_t size, off; 1170 psize_t nbytes; 1171 int err, i; 1172 1173 if (sc->sc_vp == NULL) 1174 return; 1175 1176 buf = malloc(vd->size, M_DEVBUF, M_WAITOK); 1177 1178 iov.iov_base = buf; 1179 iov.iov_len = vd->size; 1180 uio.uio_iov = &iov; 1181 uio.uio_iovcnt = 1; 1182 uio.uio_offset = vd->offset * DEV_BSIZE; 1183 uio.uio_resid = vd->size; 1184 uio.uio_segflg = UIO_SYSSPACE; 1185 uio.uio_rw = UIO_READ; 1186 uio.uio_procp = p; 1187 1188 vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p); 1189 vd->status = VOP_READ(sc->sc_vp, &uio, 0, p->p_ucred); 1190 VOP_UNLOCK(sc->sc_vp, 0, p); 1191 1192 if (vd->status == 0) { 1193 i = 0; 1194 va = (vaddr_t)buf; 1195 size = vd->size; 1196 off = 0; 1197 while (size > 0 && i < vd->ncookies) { 1198 pmap_extract(pmap_kernel(), va, &pa); 1199 nbytes = MIN(size, vd->cookie[i].size - off); 1200 nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK)); 1201 err = hv_ldc_copy(lc->lc_id, LDC_COPY_OUT, 1202 vd->cookie[i].addr + off, pa, nbytes, &nbytes); 1203 if (err != H_EOK) { 1204 printf("%s: hv_ldc_copy: %d\n", __func__, err); 1205 vd->status = EIO; 1206 goto fail; 1207 } 1208 va += nbytes; 1209 size -= nbytes; 1210 off += nbytes; 1211 if (off >= vd->cookie[i].size) { 1212 off = 0; 1213 i++; 1214 } 1215 } 1216 } 1217 1218 fail: 1219 free(buf, M_DEVBUF, 0); 1220 1221 /* ACK the descriptor. */ 1222 vd->hdr.dstate = VIO_DESC_DONE; 1223 vdsp_ack_desc(sc, vd); 1224 } 1225 1226 void 1227 vdsp_write_dring(void *arg1, void *arg2) 1228 { 1229 struct vdsp_softc *sc = arg1; 1230 struct ldc_conn *lc = &sc->sc_lc; 1231 struct vd_desc *vd = arg2; 1232 struct proc *p = curproc; 1233 struct iovec iov; 1234 struct uio uio; 1235 caddr_t buf; 1236 vaddr_t va; 1237 paddr_t pa; 1238 uint64_t size, off; 1239 psize_t nbytes; 1240 int err, i; 1241 1242 if (sc->sc_vp == NULL) 1243 return; 1244 1245 buf = malloc(vd->size, M_DEVBUF, M_WAITOK); 1246 1247 i = 0; 1248 va = (vaddr_t)buf; 1249 size = vd->size; 1250 off = 0; 1251 while (size > 0 && i < vd->ncookies) { 1252 pmap_extract(pmap_kernel(), va, &pa); 1253 nbytes = MIN(size, vd->cookie[i].size - off); 1254 nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK)); 1255 err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN, 1256 vd->cookie[i].addr + off, pa, nbytes, &nbytes); 1257 if (err != H_EOK) { 1258 printf("%s: hv_ldc_copy: %d\n", __func__, err); 1259 vd->status = EIO; 1260 goto fail; 1261 } 1262 va += nbytes; 1263 size -= nbytes; 1264 off += nbytes; 1265 if (off >= vd->cookie[i].size) { 1266 off = 0; 1267 i++; 1268 } 1269 } 1270 1271 iov.iov_base = buf; 1272 iov.iov_len = vd->size; 1273 uio.uio_iov = &iov; 1274 uio.uio_iovcnt = 1; 1275 uio.uio_offset = vd->offset * DEV_BSIZE; 1276 uio.uio_resid = vd->size; 1277 uio.uio_segflg = UIO_SYSSPACE; 1278 uio.uio_rw = UIO_WRITE; 1279 uio.uio_procp = p; 1280 1281 vn_lock(sc->sc_vp, LK_EXCLUSIVE | LK_RETRY, p); 1282 vd->status = VOP_WRITE(sc->sc_vp, &uio, 0, p->p_ucred); 1283 VOP_UNLOCK(sc->sc_vp, 0, p); 1284 1285 fail: 1286 free(buf, M_DEVBUF, 0); 1287 1288 /* ACK the descriptor. */ 1289 vd->hdr.dstate = VIO_DESC_DONE; 1290 vdsp_ack_desc(sc, vd); 1291 } 1292 1293 void 1294 vdsp_flush_dring(void *arg1, void *arg2) 1295 { 1296 struct vdsp_softc *sc = arg1; 1297 struct vd_desc *vd = arg2; 1298 1299 if (sc->sc_vp == NULL) 1300 return; 1301 1302 /* ACK the descriptor. */ 1303 vd->status = 0; 1304 vd->hdr.dstate = VIO_DESC_DONE; 1305 vdsp_ack_desc(sc, vd); 1306 } 1307 1308 void 1309 vdsp_get_vtoc(void *arg1, void *arg2) 1310 { 1311 struct vdsp_softc *sc = arg1; 1312 struct ldc_conn *lc = &sc->sc_lc; 1313 struct vd_desc *vd = arg2; 1314 struct sun_vtoc_preamble *sl; 1315 struct vd_vtoc *vt; 1316 vaddr_t va; 1317 paddr_t pa; 1318 uint64_t size, off; 1319 psize_t nbytes; 1320 int err, i; 1321 1322 vt = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO); 1323 1324 if (sc->sc_label == NULL) 1325 vdsp_readlabel(sc); 1326 1327 if (sc->sc_label && sc->sc_label->sl_magic == SUN_DKMAGIC) { 1328 sl = (struct sun_vtoc_preamble *)sc->sc_label; 1329 1330 memcpy(vt->ascii_label, sl->sl_text, sizeof(sl->sl_text)); 1331 memcpy(vt->volume_name, sl->sl_volume, sizeof(sl->sl_volume)); 1332 vt->sector_size = DEV_BSIZE; 1333 vt->num_partitions = sl->sl_nparts; 1334 for (i = 0; i < vt->num_partitions; i++) { 1335 vt->partition[i].id_tag = sl->sl_part[i].spi_tag; 1336 vt->partition[i].perm = sl->sl_part[i].spi_flag; 1337 vt->partition[i].start = 1338 sc->sc_label->sl_part[i].sdkp_cyloffset * 1339 sc->sc_label->sl_ntracks * 1340 sc->sc_label->sl_nsectors; 1341 vt->partition[i].nblocks = 1342 sc->sc_label->sl_part[i].sdkp_nsectors; 1343 } 1344 } else { 1345 uint64_t disk_size; 1346 int unit; 1347 1348 /* Human-readable disk size. */ 1349 disk_size = sc->sc_vdisk_size * sc->sc_vdisk_block_size; 1350 disk_size >>= 10; 1351 unit = 'K'; 1352 if (disk_size > (2 << 10)) { 1353 disk_size >>= 10; 1354 unit = 'M'; 1355 } 1356 if (disk_size > (2 << 10)) { 1357 disk_size >>= 10; 1358 unit = 'G'; 1359 } 1360 1361 snprintf(vt->ascii_label, sizeof(vt->ascii_label), 1362 "OpenBSD-DiskImage-%lld%cB cyl %d alt %d hd %d sec %d", 1363 disk_size, unit, sc->sc_ncyl, sc->sc_acyl, 1364 sc->sc_nhead, sc->sc_nsect); 1365 vt->sector_size = sc->sc_vdisk_block_size; 1366 vt->num_partitions = 8; 1367 vt->partition[2].id_tag = SPTAG_WHOLE_DISK; 1368 vt->partition[2].nblocks = 1369 sc->sc_ncyl * sc->sc_nhead * sc->sc_nsect; 1370 } 1371 1372 i = 0; 1373 va = (vaddr_t)vt; 1374 size = roundup(sizeof(*vt), 64); 1375 off = 0; 1376 while (size > 0 && i < vd->ncookies) { 1377 pmap_extract(pmap_kernel(), va, &pa); 1378 nbytes = MIN(size, vd->cookie[i].size - off); 1379 nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK)); 1380 err = hv_ldc_copy(lc->lc_id, LDC_COPY_OUT, 1381 vd->cookie[i].addr + off, pa, nbytes, &nbytes); 1382 if (err != H_EOK) { 1383 printf("%s: hv_ldc_copy: %d\n", __func__, err); 1384 vd->status = EIO; 1385 goto fail; 1386 } 1387 va += nbytes; 1388 size -= nbytes; 1389 off += nbytes; 1390 if (off >= vd->cookie[i].size) { 1391 off = 0; 1392 i++; 1393 } 1394 } 1395 1396 vd->status = 0; 1397 1398 fail: 1399 free(vt, M_DEVBUF, 0); 1400 1401 /* ACK the descriptor. */ 1402 vd->hdr.dstate = VIO_DESC_DONE; 1403 vdsp_ack_desc(sc, vd); 1404 } 1405 1406 void 1407 vdsp_set_vtoc(void *arg1, void *arg2) 1408 { 1409 struct vdsp_softc *sc = arg1; 1410 struct ldc_conn *lc = &sc->sc_lc; 1411 struct vd_desc *vd = arg2; 1412 struct sun_vtoc_preamble *sl; 1413 struct vd_vtoc *vt; 1414 u_short cksum = 0, *sp1, *sp2; 1415 vaddr_t va; 1416 paddr_t pa; 1417 uint64_t size, off; 1418 psize_t nbytes; 1419 int err, i; 1420 1421 vt = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO); 1422 1423 i = 0; 1424 va = (vaddr_t)vt; 1425 size = sizeof(*vt); 1426 off = 0; 1427 while (size > 0 && i < vd->ncookies) { 1428 pmap_extract(pmap_kernel(), va, &pa); 1429 nbytes = MIN(size, vd->cookie[i].size - off); 1430 nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK)); 1431 err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN, 1432 vd->cookie[i].addr + off, pa, nbytes, &nbytes); 1433 if (err != H_EOK) { 1434 printf("%s: hv_ldc_copy: %d\n", __func__, err); 1435 vd->status = EIO; 1436 goto fail; 1437 } 1438 va += nbytes; 1439 size -= nbytes; 1440 off += nbytes; 1441 if (off >= vd->cookie[i].size) { 1442 off = 0; 1443 i++; 1444 } 1445 } 1446 1447 if (vt->num_partitions > nitems(sc->sc_label->sl_part)) { 1448 vd->status = EINVAL; 1449 goto fail; 1450 } 1451 1452 if (sc->sc_label == NULL || sc->sc_label->sl_magic != SUN_DKMAGIC) { 1453 sc->sc_label = malloc(sizeof(*sc->sc_label), 1454 M_DEVBUF, M_WAITOK | M_ZERO); 1455 1456 sc->sc_label->sl_ntracks = sc->sc_nhead; 1457 sc->sc_label->sl_nsectors = sc->sc_nsect; 1458 sc->sc_label->sl_ncylinders = sc->sc_ncyl; 1459 sc->sc_label->sl_acylinders = sc->sc_acyl; 1460 sc->sc_label->sl_pcylinders = sc->sc_ncyl + sc->sc_acyl; 1461 sc->sc_label->sl_rpm = 3600; 1462 1463 sc->sc_label->sl_magic = SUN_DKMAGIC; 1464 } 1465 1466 sl = (struct sun_vtoc_preamble *)sc->sc_label; 1467 memcpy(sl->sl_text, vt->ascii_label, sizeof(sl->sl_text)); 1468 sl->sl_version = 0x01; 1469 memcpy(sl->sl_volume, sl->sl_volume, sizeof(sl->sl_volume)); 1470 sl->sl_nparts = vt->num_partitions; 1471 for (i = 0; i < vt->num_partitions; i++) { 1472 sl->sl_part[i].spi_tag = vt->partition[i].id_tag; 1473 sl->sl_part[i].spi_flag = vt->partition[i].perm; 1474 sc->sc_label->sl_part[i].sdkp_cyloffset = 1475 vt->partition[i].start / (sc->sc_nhead * sc->sc_nsect); 1476 sc->sc_label->sl_part[i].sdkp_nsectors = 1477 vt->partition[i].nblocks; 1478 } 1479 sl->sl_sanity = 0x600ddeee; 1480 1481 /* Compute the checksum. */ 1482 sp1 = (u_short *)sc->sc_label; 1483 sp2 = (u_short *)(sc->sc_label + 1); 1484 while (sp1 < sp2) 1485 cksum ^= *sp1++; 1486 sc->sc_label->sl_cksum = cksum; 1487 1488 vd->status = vdsp_writelabel(sc); 1489 1490 fail: 1491 free(vt, M_DEVBUF, 0); 1492 1493 /* ACK the descriptor. */ 1494 vd->hdr.dstate = VIO_DESC_DONE; 1495 vdsp_ack_desc(sc, vd); 1496 } 1497 1498 void 1499 vdsp_get_diskgeom(void *arg1, void *arg2) 1500 { 1501 struct vdsp_softc *sc = arg1; 1502 struct ldc_conn *lc = &sc->sc_lc; 1503 struct vd_desc *vd = arg2; 1504 struct vd_diskgeom *vg; 1505 vaddr_t va; 1506 paddr_t pa; 1507 uint64_t size, off; 1508 psize_t nbytes; 1509 int err, i; 1510 1511 vg = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO); 1512 1513 if (sc->sc_label == NULL) 1514 vdsp_readlabel(sc); 1515 1516 if (sc->sc_label && sc->sc_label->sl_magic == SUN_DKMAGIC) { 1517 vg->ncyl = sc->sc_label->sl_ncylinders; 1518 vg->acyl = sc->sc_label->sl_acylinders; 1519 vg->nhead = sc->sc_label->sl_ntracks; 1520 vg->nsect = sc->sc_label->sl_nsectors; 1521 vg->intrlv = sc->sc_label->sl_interleave; 1522 vg->apc = sc->sc_label->sl_sparespercyl; 1523 vg->rpm = sc->sc_label->sl_rpm; 1524 vg->pcyl = sc->sc_label->sl_pcylinders; 1525 } else { 1526 uint64_t disk_size, block_size; 1527 1528 disk_size = sc->sc_vdisk_size * sc->sc_vdisk_block_size; 1529 block_size = sc->sc_vdisk_block_size; 1530 1531 if (disk_size >= 8L * 1024 * 1024 * 1024) { 1532 vg->nhead = 96; 1533 vg->nsect = 768; 1534 } else if (disk_size >= 2 *1024 * 1024) { 1535 vg->nhead = 1; 1536 vg->nsect = 600; 1537 } else { 1538 vg->nhead = 1; 1539 vg->nsect = 200; 1540 } 1541 1542 vg->pcyl = disk_size / (block_size * vg->nhead * vg->nsect); 1543 if (vg->pcyl == 0) 1544 vg->pcyl = 1; 1545 if (vg->pcyl > 2) 1546 vg->acyl = 2; 1547 vg->ncyl = vg->pcyl - vg->acyl; 1548 1549 vg->rpm = 3600; 1550 } 1551 1552 sc->sc_ncyl = vg->ncyl; 1553 sc->sc_acyl = vg->acyl; 1554 sc->sc_nhead = vg->nhead; 1555 sc->sc_nsect = vg->nsect; 1556 1557 i = 0; 1558 va = (vaddr_t)vg; 1559 size = roundup(sizeof(*vg), 64); 1560 off = 0; 1561 while (size > 0 && i < vd->ncookies) { 1562 pmap_extract(pmap_kernel(), va, &pa); 1563 nbytes = MIN(size, vd->cookie[i].size - off); 1564 nbytes = MIN(nbytes, PAGE_SIZE - (off & PAGE_MASK)); 1565 err = hv_ldc_copy(lc->lc_id, LDC_COPY_OUT, 1566 vd->cookie[i].addr + off, pa, nbytes, &nbytes); 1567 if (err != H_EOK) { 1568 printf("%s: hv_ldc_copy: %d\n", __func__, err); 1569 vd->status = EIO; 1570 goto fail; 1571 } 1572 va += nbytes; 1573 size -= nbytes; 1574 off += nbytes; 1575 if (off >= vd->cookie[i].size) { 1576 off = 0; 1577 i++; 1578 } 1579 } 1580 1581 vd->status = 0; 1582 1583 fail: 1584 free(vg, M_DEVBUF, 0); 1585 1586 /* ACK the descriptor. */ 1587 vd->hdr.dstate = VIO_DESC_DONE; 1588 vdsp_ack_desc(sc, vd); 1589 } 1590 1591 void 1592 vdsp_unimp(void *arg1, void *arg2) 1593 { 1594 struct vdsp_softc *sc = arg1; 1595 struct vd_desc *vd = arg2; 1596 1597 /* ACK the descriptor. */ 1598 vd->status = ENOTSUP; 1599 vd->hdr.dstate = VIO_DESC_DONE; 1600 vdsp_ack_desc(sc, vd); 1601 } 1602 1603 void 1604 vdsp_ack_desc(struct vdsp_softc *sc, struct vd_desc *vd) 1605 { 1606 struct vio_dring_msg dm; 1607 vaddr_t va; 1608 paddr_t pa; 1609 uint64_t size, off; 1610 psize_t nbytes; 1611 int err; 1612 1613 va = (vaddr_t)vd; 1614 off = (caddr_t)vd - sc->sc_vd; 1615 size = sc->sc_descriptor_size; 1616 while (size > 0) { 1617 pmap_extract(pmap_kernel(), va, &pa); 1618 nbytes = MIN(size, PAGE_SIZE - (off & PAGE_MASK)); 1619 err = hv_ldc_copy(sc->sc_lc.lc_id, LDC_COPY_OUT, 1620 sc->sc_dring_cookie.addr + off, pa, nbytes, &nbytes); 1621 if (err != H_EOK) { 1622 printf("%s: hv_ldc_copy %d\n", __func__, err); 1623 return; 1624 } 1625 va += nbytes; 1626 size -= nbytes; 1627 off += nbytes; 1628 } 1629 1630 /* ACK the descriptor. */ 1631 bzero(&dm, sizeof(dm)); 1632 dm.tag.type = VIO_TYPE_DATA; 1633 dm.tag.stype = VIO_SUBTYPE_ACK; 1634 dm.tag.stype_env = VIO_DRING_DATA; 1635 dm.tag.sid = sc->sc_local_sid; 1636 dm.seq_no = ++sc->sc_seq_no; 1637 dm.dring_ident = sc->sc_dring_ident; 1638 off = (caddr_t)vd - sc->sc_vd; 1639 dm.start_idx = off / sc->sc_descriptor_size; 1640 dm.end_idx = off / sc->sc_descriptor_size; 1641 vdsp_sendmsg(sc, &dm, sizeof(dm), 1); 1642 } 1643 1644 int 1645 vdspopen(dev_t dev, int flag, int mode, struct proc *p) 1646 { 1647 struct vdsp_softc *sc; 1648 struct ldc_conn *lc; 1649 int unit = minor(dev); 1650 int err; 1651 1652 if (unit >= vdsp_cd.cd_ndevs) 1653 return (ENXIO); 1654 sc = vdsp_cd.cd_devs[unit]; 1655 if (sc == NULL) 1656 return (ENXIO); 1657 1658 lc = &sc->sc_lc; 1659 1660 err = hv_ldc_tx_qconf(lc->lc_id, 1661 lc->lc_txq->lq_map->dm_segs[0].ds_addr, lc->lc_txq->lq_nentries); 1662 if (err != H_EOK) 1663 printf("%s: hv_ldc_tx_qconf %d\n", __func__, err); 1664 1665 err = hv_ldc_rx_qconf(lc->lc_id, 1666 lc->lc_rxq->lq_map->dm_segs[0].ds_addr, lc->lc_rxq->lq_nentries); 1667 if (err != H_EOK) 1668 printf("%s: hv_ldc_rx_qconf %d\n", __func__, err); 1669 1670 cbus_intr_setenabled(sc->sc_tx_sysino, INTR_ENABLED); 1671 cbus_intr_setenabled(sc->sc_rx_sysino, INTR_ENABLED); 1672 1673 return (0); 1674 } 1675 1676 int 1677 vdspclose(dev_t dev, int flag, int mode, struct proc *p) 1678 { 1679 struct vdsp_softc *sc; 1680 int unit = minor(dev); 1681 1682 if (unit >= vdsp_cd.cd_ndevs) 1683 return (ENXIO); 1684 sc = vdsp_cd.cd_devs[unit]; 1685 if (sc == NULL) 1686 return (ENXIO); 1687 1688 cbus_intr_setenabled(sc->sc_tx_sysino, INTR_DISABLED); 1689 cbus_intr_setenabled(sc->sc_rx_sysino, INTR_DISABLED); 1690 1691 hv_ldc_tx_qconf(sc->sc_lc.lc_id, 0, 0); 1692 hv_ldc_rx_qconf(sc->sc_lc.lc_id, 0, 0); 1693 1694 if (sc->sc_vp) { 1695 vn_close(sc->sc_vp, FREAD | FWRITE, p->p_ucred, p); 1696 sc->sc_vp = NULL; 1697 } 1698 1699 return (0); 1700 } 1701 1702 int 1703 vdspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 1704 { 1705 struct vdsp_softc *sc; 1706 int unit = minor(dev); 1707 1708 if (unit >= vdsp_cd.cd_ndevs) 1709 return (ENXIO); 1710 sc = vdsp_cd.cd_devs[unit]; 1711 if (sc == NULL) 1712 return (ENXIO); 1713 1714 return (ENOTTY); 1715 } 1716