1 /* $NetBSD: ld_ataraid.c,v 1.50 2020/01/17 19:31:31 ad Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* 39 * Support for ATA RAID logical disks. 40 * 41 * Note that all the RAID happens in software here; the ATA RAID 42 * controllers we're dealing with (Promise, etc.) only support 43 * configuration data on the component disks, with the BIOS supporting 44 * booting from the RAID volumes. 45 * 46 * bio(4) support was written by Juan Romero Pardines <xtraeme@gmail.com>. 47 */ 48 49 #include <sys/cdefs.h> 50 __KERNEL_RCSID(0, "$NetBSD: ld_ataraid.c,v 1.50 2020/01/17 19:31:31 ad Exp $"); 51 52 #if defined(_KERNEL_OPT) 53 #include "bio.h" 54 #endif 55 56 #include <sys/param.h> 57 #include <sys/systm.h> 58 #include <sys/conf.h> 59 #include <sys/kernel.h> 60 #include <sys/device.h> 61 #include <sys/buf.h> 62 #include <sys/bufq.h> 63 #include <sys/dkio.h> 64 #include <sys/disk.h> 65 #include <sys/disklabel.h> 66 #include <sys/fcntl.h> 67 #include <sys/vnode.h> 68 #include <sys/kauth.h> 69 #include <sys/module.h> 70 #if NBIO > 0 71 #include <dev/ata/atavar.h> 72 #include <dev/ata/atareg.h> 73 #include <dev/ata/wdvar.h> 74 #include <dev/biovar.h> 75 #include <dev/scsipi/scsipiconf.h> /* for scsipi_strvis() */ 76 #endif 77 78 #include <miscfs/specfs/specdev.h> 79 80 #include <dev/ldvar.h> 81 82 #include <dev/ata/ata_raidvar.h> 83 84 #include "ioconf.h" 85 86 struct ld_ataraid_softc { 87 struct ld_softc sc_ld; 88 89 struct ataraid_array_info *sc_aai; 90 struct vnode *sc_vnodes[ATA_RAID_MAX_DISKS]; 91 92 void (*sc_iodone)(struct buf *); 93 94 pool_cache_t sc_cbufpool; 95 96 SIMPLEQ_HEAD(, cbuf) sc_cbufq; 97 98 void *sc_sih_cookie; 99 }; 100 101 static int ld_ataraid_match(device_t, cfdata_t, void *); 102 static void ld_ataraid_attach(device_t, device_t, void *); 103 104 static int ld_ataraid_dump(struct ld_softc *, void *, int, int); 105 static int ld_ataraid_ioctl(struct ld_softc *, u_long, void *, int32_t, 106 bool); 107 108 static int cbufpool_ctor(void *, void *, int); 109 static void cbufpool_dtor(void *, void *); 110 111 static void ld_ataraid_start_vstrategy(void *); 112 static int ld_ataraid_start_span(struct ld_softc *, struct buf *); 113 114 static int ld_ataraid_start_raid0(struct ld_softc *, struct buf *); 115 static void ld_ataraid_iodone_raid0(struct buf *); 116 117 #if NBIO > 0 118 static int ld_ataraid_bioctl(device_t, u_long, void *); 119 static int ld_ataraid_bioinq(struct ld_ataraid_softc *, struct bioc_inq *); 120 static int ld_ataraid_biovol(struct ld_ataraid_softc *, struct bioc_vol *); 121 static int ld_ataraid_biodisk(struct ld_ataraid_softc *, 122 struct bioc_disk *); 123 #endif 124 125 CFATTACH_DECL_NEW(ld_ataraid, sizeof(struct ld_ataraid_softc), 126 ld_ataraid_match, ld_ataraid_attach, NULL, NULL); 127 128 struct cbuf { 129 struct buf cb_buf; /* new I/O buf */ 130 struct buf *cb_obp; /* ptr. to original I/O buf */ 131 struct ld_ataraid_softc *cb_sc; /* pointer to ld softc */ 132 u_int cb_comp; /* target component */ 133 SIMPLEQ_ENTRY(cbuf) cb_q; /* fifo of component buffers */ 134 struct cbuf *cb_other; /* other cbuf in case of mirror */ 135 int cb_flags; 136 #define CBUF_IODONE 0x00000001 /* I/O is already successfully done */ 137 }; 138 139 #define CBUF_GET() pool_cache_get(sc->sc_cbufpool, PR_NOWAIT); 140 #define CBUF_PUT(cbp) pool_cache_put(sc->sc_cbufpool, (cbp)) 141 142 static int 143 ld_ataraid_match(device_t parent, cfdata_t match, void *aux) 144 { 145 146 return (1); 147 } 148 149 static void 150 ld_ataraid_attach(device_t parent, device_t self, void *aux) 151 { 152 struct ld_ataraid_softc *sc = device_private(self); 153 struct ld_softc *ld = &sc->sc_ld; 154 struct ataraid_array_info *aai = aux; 155 struct ataraid_disk_info *adi = NULL; 156 const char *level; 157 struct vnode *vp; 158 char unklev[32]; 159 u_int i; 160 161 ld->sc_dv = self; 162 163 sc->sc_cbufpool = pool_cache_init(sizeof(struct cbuf), 0, 164 0, 0, "ldcbuf", NULL, IPL_BIO, cbufpool_ctor, cbufpool_dtor, sc); 165 sc->sc_sih_cookie = softint_establish(SOFTINT_BIO, 166 ld_ataraid_start_vstrategy, sc); 167 168 sc->sc_aai = aai; /* this data persists */ 169 170 ld->sc_maxxfer = MAXPHYS * aai->aai_width; /* XXX */ 171 ld->sc_secperunit = aai->aai_capacity; 172 ld->sc_secsize = 512; /* XXX */ 173 ld->sc_maxqueuecnt = 128; /* XXX */ 174 ld->sc_dump = ld_ataraid_dump; 175 ld->sc_ioctl = ld_ataraid_ioctl; 176 177 switch (aai->aai_level) { 178 case AAI_L_SPAN: 179 level = "SPAN"; 180 ld->sc_start = ld_ataraid_start_span; 181 sc->sc_iodone = ld_ataraid_iodone_raid0; 182 break; 183 184 case AAI_L_RAID0: 185 level = "RAID-0"; 186 ld->sc_start = ld_ataraid_start_raid0; 187 sc->sc_iodone = ld_ataraid_iodone_raid0; 188 break; 189 190 case AAI_L_RAID1: 191 level = "RAID-1"; 192 ld->sc_start = ld_ataraid_start_raid0; 193 sc->sc_iodone = ld_ataraid_iodone_raid0; 194 break; 195 196 case AAI_L_RAID0 | AAI_L_RAID1: 197 level = "RAID-10"; 198 ld->sc_start = ld_ataraid_start_raid0; 199 sc->sc_iodone = ld_ataraid_iodone_raid0; 200 break; 201 202 default: 203 snprintf(unklev, sizeof(unklev), "<unknown level 0x%x>", 204 aai->aai_level); 205 level = unklev; 206 } 207 208 aprint_naive(": ATA %s array\n", level); 209 aprint_normal(": %s ATA %s array\n", 210 ata_raid_type_name(aai->aai_type), level); 211 212 if (ld->sc_start == NULL) { 213 aprint_error_dev(ld->sc_dv, "unsupported array type\n"); 214 return; 215 } 216 217 /* 218 * We get a geometry from the device; use it. 219 */ 220 ld->sc_nheads = aai->aai_heads; 221 ld->sc_nsectors = aai->aai_sectors; 222 ld->sc_ncylinders = aai->aai_cylinders; 223 224 /* 225 * Configure all the component disks. 226 */ 227 for (i = 0; i < aai->aai_ndisks; i++) { 228 adi = &aai->aai_disks[i]; 229 vp = ata_raid_disk_vnode_find(adi); 230 if (vp == NULL) { 231 /* 232 * XXX This is bogus. We should just mark the 233 * XXX component as FAILED, and write-back new 234 * XXX config blocks. 235 */ 236 break; 237 } 238 sc->sc_vnodes[i] = vp; 239 } 240 if (i == aai->aai_ndisks) { 241 ld->sc_flags = LDF_ENABLED; 242 goto finish; 243 } 244 245 for (i = 0; i < aai->aai_ndisks; i++) { 246 vp = sc->sc_vnodes[i]; 247 sc->sc_vnodes[i] = NULL; 248 if (vp != NULL) 249 (void) vn_close(vp, FREAD|FWRITE, NOCRED); 250 } 251 252 finish: 253 #if NBIO > 0 254 if (bio_register(self, ld_ataraid_bioctl) != 0) 255 panic("%s: bioctl registration failed\n", 256 device_xname(ld->sc_dv)); 257 #endif 258 SIMPLEQ_INIT(&sc->sc_cbufq); 259 ldattach(ld, BUFQ_DISK_DEFAULT_STRAT); 260 } 261 262 static int 263 cbufpool_ctor(void *arg, void *obj, int flags) 264 { 265 struct ld_ataraid_softc *sc = arg; 266 struct ld_softc *ld = &sc->sc_ld; 267 struct cbuf *cbp = obj; 268 269 /* We release/reacquire the spinlock before calling buf_init() */ 270 mutex_exit(&ld->sc_mutex); 271 buf_init(&cbp->cb_buf); 272 mutex_enter(&ld->sc_mutex); 273 274 return 0; 275 } 276 277 static void 278 cbufpool_dtor(void *arg, void *obj) 279 { 280 struct cbuf *cbp = obj; 281 282 buf_destroy(&cbp->cb_buf); 283 } 284 285 static struct cbuf * 286 ld_ataraid_make_cbuf(struct ld_ataraid_softc *sc, struct buf *bp, 287 u_int comp, daddr_t bn, void *addr, long bcount) 288 { 289 struct cbuf *cbp; 290 291 cbp = CBUF_GET(); 292 if (cbp == NULL) 293 return NULL; 294 cbp->cb_buf.b_flags = bp->b_flags; 295 cbp->cb_buf.b_oflags = bp->b_oflags; 296 cbp->cb_buf.b_cflags = bp->b_cflags; 297 cbp->cb_buf.b_iodone = sc->sc_iodone; 298 cbp->cb_buf.b_proc = bp->b_proc; 299 cbp->cb_buf.b_vp = sc->sc_vnodes[comp]; 300 cbp->cb_buf.b_objlock = sc->sc_vnodes[comp]->v_interlock; 301 cbp->cb_buf.b_blkno = bn + sc->sc_aai->aai_offset; 302 cbp->cb_buf.b_data = addr; 303 cbp->cb_buf.b_bcount = bcount; 304 305 /* Context for iodone */ 306 cbp->cb_obp = bp; 307 cbp->cb_sc = sc; 308 cbp->cb_comp = comp; 309 cbp->cb_other = NULL; 310 cbp->cb_flags = 0; 311 312 return cbp; 313 } 314 315 static void 316 ld_ataraid_start_vstrategy(void *arg) 317 { 318 struct ld_ataraid_softc *sc = arg; 319 struct cbuf *cbp; 320 321 while ((cbp = SIMPLEQ_FIRST(&sc->sc_cbufq)) != NULL) { 322 SIMPLEQ_REMOVE_HEAD(&sc->sc_cbufq, cb_q); 323 if ((cbp->cb_buf.b_flags & B_READ) == 0) { 324 mutex_enter(cbp->cb_buf.b_vp->v_interlock); 325 cbp->cb_buf.b_vp->v_numoutput++; 326 mutex_exit(cbp->cb_buf.b_vp->v_interlock); 327 } 328 VOP_STRATEGY(cbp->cb_buf.b_vp, &cbp->cb_buf); 329 } 330 } 331 332 static int 333 ld_ataraid_start_span(struct ld_softc *ld, struct buf *bp) 334 { 335 struct ld_ataraid_softc *sc = (void *) ld; 336 struct ataraid_array_info *aai = sc->sc_aai; 337 struct ataraid_disk_info *adi; 338 struct cbuf *cbp; 339 char *addr; 340 daddr_t bn; 341 long bcount, rcount; 342 u_int comp; 343 344 /* Allocate component buffers. */ 345 addr = bp->b_data; 346 347 /* Find the first component. */ 348 comp = 0; 349 adi = &aai->aai_disks[comp]; 350 bn = bp->b_rawblkno; 351 while (bn >= adi->adi_compsize) { 352 bn -= adi->adi_compsize; 353 adi = &aai->aai_disks[++comp]; 354 } 355 356 bp->b_resid = bp->b_bcount; 357 358 for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) { 359 rcount = bp->b_bcount; 360 if ((adi->adi_compsize - bn) < btodb(rcount)) 361 rcount = dbtob(adi->adi_compsize - bn); 362 363 cbp = ld_ataraid_make_cbuf(sc, bp, comp, bn, addr, rcount); 364 if (cbp == NULL) { 365 /* Free the already allocated component buffers. */ 366 while ((cbp = SIMPLEQ_FIRST(&sc->sc_cbufq)) != NULL) { 367 SIMPLEQ_REMOVE_HEAD(&sc->sc_cbufq, cb_q); 368 CBUF_PUT(cbp); 369 } 370 return EAGAIN; 371 } 372 373 /* 374 * For a span, we always know we advance to the next disk, 375 * and always start at offset 0 on that disk. 376 */ 377 adi = &aai->aai_disks[++comp]; 378 bn = 0; 379 380 SIMPLEQ_INSERT_TAIL(&sc->sc_cbufq, cbp, cb_q); 381 addr += rcount; 382 } 383 384 /* Now fire off the requests. */ 385 softint_schedule(sc->sc_sih_cookie); 386 387 return 0; 388 } 389 390 static int 391 ld_ataraid_start_raid0(struct ld_softc *ld, struct buf *bp) 392 { 393 struct ld_ataraid_softc *sc = (void *)ld; 394 struct ataraid_array_info *aai = sc->sc_aai; 395 struct ataraid_disk_info *adi; 396 struct cbuf *cbp, *other_cbp; 397 char *addr; 398 daddr_t bn, cbn, tbn, off; 399 long bcount, rcount; 400 u_int comp; 401 const int read = bp->b_flags & B_READ; 402 const int mirror = aai->aai_level & AAI_L_RAID1; 403 int error = 0; 404 405 /* Allocate component buffers. */ 406 addr = bp->b_data; 407 bn = bp->b_rawblkno; 408 409 bp->b_resid = bp->b_bcount; 410 411 for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) { 412 tbn = bn / aai->aai_interleave; 413 off = bn % aai->aai_interleave; 414 415 if (__predict_false(tbn == aai->aai_capacity / 416 aai->aai_interleave)) { 417 /* Last stripe. */ 418 daddr_t sz = (aai->aai_capacity - 419 (tbn * aai->aai_interleave)) / 420 aai->aai_width; 421 comp = off / sz; 422 cbn = ((tbn / aai->aai_width) * aai->aai_interleave) + 423 (off % sz); 424 rcount = uimin(bcount, dbtob(sz)); 425 } else { 426 comp = tbn % aai->aai_width; 427 cbn = ((tbn / aai->aai_width) * aai->aai_interleave) + 428 off; 429 rcount = uimin(bcount, dbtob(aai->aai_interleave - off)); 430 } 431 432 /* 433 * See if a component is valid. 434 */ 435 try_mirror: 436 adi = &aai->aai_disks[comp]; 437 if ((adi->adi_status & ADI_S_ONLINE) == 0) { 438 if (mirror && comp < aai->aai_width) { 439 comp += aai->aai_width; 440 goto try_mirror; 441 } 442 443 /* 444 * No component available. 445 */ 446 error = EIO; 447 goto free_and_exit; 448 } 449 450 cbp = ld_ataraid_make_cbuf(sc, bp, comp, cbn, addr, rcount); 451 if (cbp == NULL) { 452 resource_shortage: 453 error = EAGAIN; 454 free_and_exit: 455 /* Free the already allocated component buffers. */ 456 while ((cbp = SIMPLEQ_FIRST(&sc->sc_cbufq)) != NULL) { 457 SIMPLEQ_REMOVE_HEAD(&sc->sc_cbufq, cb_q); 458 CBUF_PUT(cbp); 459 } 460 return error; 461 } 462 SIMPLEQ_INSERT_TAIL(&sc->sc_cbufq, cbp, cb_q); 463 if (mirror && !read && comp < aai->aai_width) { 464 comp += aai->aai_width; 465 adi = &aai->aai_disks[comp]; 466 if (adi->adi_status & ADI_S_ONLINE) { 467 other_cbp = ld_ataraid_make_cbuf(sc, bp, 468 comp, cbn, addr, rcount); 469 if (other_cbp == NULL) 470 goto resource_shortage; 471 SIMPLEQ_INSERT_TAIL(&sc->sc_cbufq, 472 other_cbp, cb_q); 473 other_cbp->cb_other = cbp; 474 cbp->cb_other = other_cbp; 475 } 476 } 477 bn += btodb(rcount); 478 addr += rcount; 479 } 480 481 /* Now fire off the requests. */ 482 softint_schedule(sc->sc_sih_cookie); 483 484 return error; 485 } 486 487 /* 488 * Called at interrupt time. Mark the component as done and if all 489 * components are done, take an "interrupt". 490 */ 491 static void 492 ld_ataraid_iodone_raid0(struct buf *vbp) 493 { 494 struct cbuf *cbp = (struct cbuf *) vbp, *other_cbp; 495 struct buf *bp = cbp->cb_obp; 496 struct ld_ataraid_softc *sc = cbp->cb_sc; 497 struct ataraid_array_info *aai = sc->sc_aai; 498 struct ataraid_disk_info *adi; 499 long count; 500 int s, iodone; 501 502 s = splbio(); 503 KERNEL_LOCK(1, NULL); /* XXXSMP */ 504 505 iodone = cbp->cb_flags & CBUF_IODONE; 506 other_cbp = cbp->cb_other; 507 if (other_cbp != NULL) 508 /* You are alone */ 509 other_cbp->cb_other = NULL; 510 511 if (cbp->cb_buf.b_error != 0) { 512 /* 513 * Mark this component broken. 514 */ 515 adi = &aai->aai_disks[cbp->cb_comp]; 516 adi->adi_status &= ~ADI_S_ONLINE; 517 518 printf("%s: error %d on component %d (%s)\n", 519 device_xname(sc->sc_ld.sc_dv), bp->b_error, cbp->cb_comp, 520 device_xname(adi->adi_dev)); 521 522 /* 523 * If we didn't see an error yet and we are reading 524 * RAID1 disk, try another component. 525 */ 526 if (bp->b_error == 0 && 527 (cbp->cb_buf.b_flags & B_READ) != 0 && 528 (aai->aai_level & AAI_L_RAID1) != 0 && 529 cbp->cb_comp < aai->aai_width) { 530 cbp->cb_comp += aai->aai_width; 531 adi = &aai->aai_disks[cbp->cb_comp]; 532 if (adi->adi_status & ADI_S_ONLINE) { 533 cbp->cb_buf.b_error = 0; 534 VOP_STRATEGY(cbp->cb_buf.b_vp, &cbp->cb_buf); 535 goto out; 536 } 537 } 538 539 if (iodone || other_cbp != NULL) 540 /* 541 * If I/O on other component successfully done 542 * or the I/O is still in progress, no need 543 * to tell an error to upper layer. 544 */ 545 ; 546 else { 547 bp->b_error = cbp->cb_buf.b_error ? 548 cbp->cb_buf.b_error : EIO; 549 } 550 551 /* XXX Update component config blocks. */ 552 553 } else { 554 /* 555 * If other I/O is still in progress, tell it that 556 * our I/O is successfully done. 557 */ 558 if (other_cbp != NULL) 559 other_cbp->cb_flags |= CBUF_IODONE; 560 } 561 count = cbp->cb_buf.b_bcount; 562 CBUF_PUT(cbp); 563 564 if (other_cbp != NULL) 565 goto out; 566 567 /* If all done, "interrupt". */ 568 bp->b_resid -= count; 569 if (bp->b_resid < 0) 570 panic("ld_ataraid_iodone_raid0: count"); 571 if (bp->b_resid == 0) 572 lddone(&sc->sc_ld, bp); 573 574 out: 575 KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */ 576 splx(s); 577 } 578 579 static int 580 ld_ataraid_dump(struct ld_softc *sc, void *data, 581 int blkno, int blkcnt) 582 { 583 584 return (EIO); 585 } 586 587 #if NBIO > 0 588 static int 589 ld_ataraid_bioctl(device_t self, u_long cmd, void *addr) 590 { 591 struct ld_ataraid_softc *sc = device_private(self); 592 int error = 0; 593 594 switch (cmd) { 595 case BIOCINQ: 596 error = ld_ataraid_bioinq(sc, (struct bioc_inq *)addr); 597 break; 598 case BIOCVOL: 599 error = ld_ataraid_biovol(sc, (struct bioc_vol *)addr); 600 break; 601 case BIOCDISK: 602 error = ld_ataraid_biodisk(sc, (struct bioc_disk *)addr); 603 break; 604 default: 605 error = ENOTTY; 606 break; 607 } 608 609 return error; 610 } 611 612 static int 613 ld_ataraid_bioinq(struct ld_ataraid_softc *sc, struct bioc_inq *bi) 614 { 615 struct ataraid_array_info *aai = sc->sc_aai; 616 617 /* there's always one volume per ld device */ 618 bi->bi_novol = 1; 619 bi->bi_nodisk = aai->aai_ndisks; 620 621 return 0; 622 } 623 624 static int 625 ld_ataraid_biovol(struct ld_ataraid_softc *sc, struct bioc_vol *bv) 626 { 627 struct ataraid_array_info *aai = sc->sc_aai; 628 struct ld_softc *ld = &sc->sc_ld; 629 #define to_kibytes(ld,s) (ld->sc_secsize*(s)/1024) 630 631 /* Fill in data for _this_ volume */ 632 bv->bv_percent = -1; 633 bv->bv_seconds = 0; 634 635 switch (aai->aai_status) { 636 case AAI_S_READY: 637 bv->bv_status = BIOC_SVONLINE; 638 break; 639 case AAI_S_DEGRADED: 640 bv->bv_status = BIOC_SVDEGRADED; 641 break; 642 } 643 644 bv->bv_size = ld->sc_secsize * ld->sc_secperunit; 645 646 switch (aai->aai_level) { 647 case AAI_L_SPAN: 648 case AAI_L_RAID0: 649 bv->bv_stripe_size = to_kibytes(ld, aai->aai_interleave); 650 bv->bv_level = 0; 651 break; 652 case AAI_L_RAID1: 653 bv->bv_stripe_size = 0; 654 bv->bv_level = 1; 655 break; 656 case AAI_L_RAID5: 657 bv->bv_stripe_size = to_kibytes(ld, aai->aai_interleave); 658 bv->bv_level = 5; 659 break; 660 } 661 662 bv->bv_nodisk = aai->aai_ndisks; 663 strlcpy(bv->bv_dev, device_xname(ld->sc_dv), sizeof(bv->bv_dev)); 664 if (aai->aai_name[0] != '\0') 665 strlcpy(bv->bv_vendor, aai->aai_name, sizeof(bv->bv_vendor)); 666 667 return 0; 668 } 669 670 static int 671 ld_ataraid_biodisk(struct ld_ataraid_softc *sc, struct bioc_disk *bd) 672 { 673 struct ataraid_array_info *aai = sc->sc_aai; 674 struct ataraid_disk_info *adi; 675 struct ld_softc *ld = &sc->sc_ld; 676 struct atabus_softc *atabus; 677 struct wd_softc *wd; 678 char model[81], serial[41], rev[17]; 679 680 /* sanity check */ 681 if (bd->bd_diskid > aai->aai_ndisks) 682 return EINVAL; 683 684 adi = &aai->aai_disks[bd->bd_diskid]; 685 atabus = device_private(device_parent(adi->adi_dev)); 686 wd = device_private(adi->adi_dev); 687 688 /* fill in data for _this_ disk */ 689 switch (adi->adi_status) { 690 case ADI_S_ONLINE | ADI_S_ASSIGNED: 691 bd->bd_status = BIOC_SDONLINE; 692 break; 693 case ADI_S_SPARE: 694 bd->bd_status = BIOC_SDHOTSPARE; 695 break; 696 default: 697 bd->bd_status = BIOC_SDOFFLINE; 698 break; 699 } 700 701 bd->bd_channel = 0; 702 bd->bd_target = atabus->sc_chan->ch_channel; 703 bd->bd_lun = 0; 704 bd->bd_size = (wd->sc_capacity * ld->sc_secsize) - aai->aai_reserved; 705 706 strlcpy(bd->bd_procdev, device_xname(adi->adi_dev), 707 sizeof(bd->bd_procdev)); 708 709 strnvisx(serial, sizeof(serial), wd->sc_params.atap_serial, 710 sizeof(wd->sc_params.atap_serial), VIS_TRIM|VIS_SAFE|VIS_OCTAL); 711 strnvisx(model, sizeof(model), wd->sc_params.atap_model, 712 sizeof(wd->sc_params.atap_model), VIS_TRIM|VIS_SAFE|VIS_OCTAL); 713 strnvisx(rev, sizeof(rev), wd->sc_params.atap_revision, 714 sizeof(wd->sc_params.atap_revision), VIS_TRIM|VIS_SAFE|VIS_OCTAL); 715 716 snprintf(bd->bd_vendor, sizeof(bd->bd_vendor), "%s %s", model, rev); 717 strlcpy(bd->bd_serial, serial, sizeof(bd->bd_serial)); 718 719 return 0; 720 } 721 #endif /* NBIO > 0 */ 722 723 static int 724 ld_ataraid_ioctl(struct ld_softc *ld, u_long cmd, void *addr, int32_t flag, 725 bool poll) 726 { 727 struct ld_ataraid_softc *sc = (void *)ld; 728 int error, i, j; 729 kauth_cred_t uc; 730 731 uc = kauth_cred_get(); 732 733 switch (cmd) { 734 case DIOCGCACHE: 735 { 736 int dkcache = 0; 737 738 /* 739 * We pass this call down to all components and report 740 * intersection of the flags returned by the components. 741 * If any errors out, we return error. ATA RAID components 742 * can only change via BIOS, device feature flags will remain 743 * static. RCE/WCE can change if set directly on underlying 744 * device. 745 */ 746 for (error = 0, i = 0; i < sc->sc_aai->aai_ndisks; i++) { 747 KASSERT(sc->sc_vnodes[i] != NULL); 748 749 error = VOP_IOCTL(sc->sc_vnodes[i], cmd, &j, 750 flag, uc); 751 if (error) 752 break; 753 754 if (i == 0) 755 dkcache = j; 756 else 757 dkcache = DKCACHE_COMBINE(dkcache, j); 758 } 759 760 *((int *)addr) = dkcache; 761 break; 762 } 763 764 case DIOCCACHESYNC: 765 { 766 /* 767 * We pass this call down to all components and report 768 * the first error we encounter. 769 */ 770 for (error = 0, i = 0; i < sc->sc_aai->aai_ndisks; i++) { 771 KASSERT(sc->sc_vnodes[i] != NULL); 772 773 j = VOP_IOCTL(sc->sc_vnodes[i], cmd, addr, 774 flag, uc); 775 if (j != 0 && error == 0) 776 error = j; 777 } 778 break; 779 } 780 781 default: 782 error = EPASSTHROUGH; 783 break; 784 } 785 786 return error; 787 } 788 789 MODULE(MODULE_CLASS_DRIVER, ld_ataraid, "ld,ataraid"); 790 791 #ifdef _MODULE 792 /* 793 * XXX Don't allow ioconf.c to redefine the "struct cfdriver ld_ataraid" 794 * XXX it will be defined in the common-code module 795 */ 796 #undef CFDRIVER_DECL 797 #define CFDRIVER_DECL(name, class, attr) 798 #include "ioconf.c" 799 #endif 800 801 static int 802 ld_ataraid_modcmd(modcmd_t cmd, void *opaque) 803 { 804 #ifdef _MODULE 805 /* 806 * We ignore the cfdriver_vec[] that ioconf provides, since 807 * the cfdrivers are attached already. 808 */ 809 static struct cfdriver * const no_cfdriver_vec[] = { NULL }; 810 #endif 811 int error = 0; 812 813 #ifdef _MODULE 814 switch (cmd) { 815 case MODULE_CMD_INIT: 816 error = config_init_component(no_cfdriver_vec, 817 cfattach_ioconf_ld_ataraid, cfdata_ioconf_ld_ataraid); 818 break; 819 case MODULE_CMD_FINI: 820 error = config_fini_component(no_cfdriver_vec, 821 cfattach_ioconf_ld_ataraid, cfdata_ioconf_ld_ataraid); 822 break; 823 default: 824 error = ENOTTY; 825 break; 826 } 827 #endif 828 829 return error; 830 } 831