1 /* $OpenBSD: cac.c,v 1.53 2014/09/14 14:17:24 jsg Exp $ */ 2 /* $NetBSD: cac.c,v 1.15 2000/11/08 19:20:35 ad Exp $ */ 3 4 /* 5 * Copyright (c) 2001,2003 Michael Shalayeff 6 * All rights reserved. 7 * 8 * The SCSI emulation layer is derived from gdt(4) driver, 9 * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 /*- 33 * Copyright (c) 2000 The NetBSD Foundation, Inc. 34 * All rights reserved. 35 * 36 * This code is derived from software contributed to The NetBSD Foundation 37 * by Andrew Doran. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 49 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 50 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 51 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 52 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 53 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 56 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 58 * POSSIBILITY OF SUCH DAMAGE. 59 */ 60 61 /* 62 * Driver for Compaq array controllers. 63 */ 64 65 #include "bio.h" 66 67 /* #define CAC_DEBUG */ 68 69 #include <sys/param.h> 70 #include <sys/systm.h> 71 #include <sys/kernel.h> 72 #include <sys/ioctl.h> 73 #include <sys/device.h> 74 #include <sys/queue.h> 75 #include <sys/buf.h> 76 #include <sys/endian.h> 77 #include <sys/malloc.h> 78 #include <sys/pool.h> 79 80 #include <machine/bus.h> 81 82 #include <scsi/scsi_all.h> 83 #include <scsi/scsi_disk.h> 84 #include <scsi/scsiconf.h> 85 86 #include <dev/ic/cacreg.h> 87 #include <dev/ic/cacvar.h> 88 89 #if NBIO > 0 90 #include <dev/biovar.h> 91 #endif 92 #include <sys/sensors.h> 93 94 struct cfdriver cac_cd = { 95 NULL, "cac", DV_DULL 96 }; 97 98 void cac_scsi_cmd(struct scsi_xfer *); 99 void cacminphys(struct buf *bp, struct scsi_link *sl); 100 101 struct scsi_adapter cac_switch = { 102 cac_scsi_cmd, cacminphys, 0, 0, 103 }; 104 105 void *cac_ccb_alloc(void *); 106 void cac_ccb_done(struct cac_softc *, struct cac_ccb *); 107 void cac_ccb_free(void *, void *); 108 int cac_ccb_poll(struct cac_softc *, struct cac_ccb *, int); 109 int cac_ccb_start(struct cac_softc *, struct cac_ccb *); 110 int cac_cmd(struct cac_softc *sc, int command, void *data, int datasize, 111 int drive, int blkno, int flags, struct scsi_xfer *xs); 112 int cac_get_dinfo(struct cac_softc *sc, int target); 113 void cac_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size); 114 115 struct cac_ccb *cac_l0_completed(struct cac_softc *); 116 int cac_l0_fifo_full(struct cac_softc *); 117 void cac_l0_intr_enable(struct cac_softc *, int); 118 int cac_l0_intr_pending(struct cac_softc *); 119 void cac_l0_submit(struct cac_softc *, struct cac_ccb *); 120 121 #if NBIO > 0 122 int cac_ioctl(struct device *, u_long, caddr_t); 123 int cac_ioctl_vol(struct cac_softc *, struct bioc_vol *); 124 125 #ifndef SMALL_KERNEL 126 int cac_create_sensors(struct cac_softc *); 127 void cac_sensor_refresh(void *); 128 #endif 129 #endif /* NBIO > 0 */ 130 131 const 132 struct cac_linkage cac_l0 = { 133 cac_l0_completed, 134 cac_l0_fifo_full, 135 cac_l0_intr_enable, 136 cac_l0_intr_pending, 137 cac_l0_submit 138 }; 139 140 /* 141 * Initialise our interface to the controller. 142 */ 143 int 144 cac_init(struct cac_softc *sc, int startfw) 145 { 146 struct scsibus_attach_args saa; 147 struct cac_controller_info cinfo; 148 int error, rseg, size, i; 149 bus_dma_segment_t seg[1]; 150 struct cac_ccb *ccb; 151 152 SIMPLEQ_INIT(&sc->sc_ccb_free); 153 SIMPLEQ_INIT(&sc->sc_ccb_queue); 154 mtx_init(&sc->sc_ccb_mtx, IPL_BIO); 155 scsi_iopool_init(&sc->sc_iopool, sc, cac_ccb_alloc, cac_ccb_free); 156 157 size = sizeof(struct cac_ccb) * CAC_MAX_CCBS; 158 159 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, seg, 1, 160 &rseg, BUS_DMA_NOWAIT | BUS_DMA_ZERO)) != 0) { 161 printf("%s: unable to allocate CCBs, error = %d\n", 162 sc->sc_dv.dv_xname, error); 163 return (-1); 164 } 165 166 if ((error = bus_dmamem_map(sc->sc_dmat, seg, rseg, size, 167 &sc->sc_ccbs, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 168 printf("%s: unable to map CCBs, error = %d\n", 169 sc->sc_dv.dv_xname, error); 170 return (-1); 171 } 172 173 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 174 BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) { 175 printf("%s: unable to create CCB DMA map, error = %d\n", 176 sc->sc_dv.dv_xname, error); 177 return (-1); 178 } 179 180 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_ccbs, 181 size, NULL, BUS_DMA_NOWAIT)) != 0) { 182 printf("%s: unable to load CCB DMA map, error = %d\n", 183 sc->sc_dv.dv_xname, error); 184 return (-1); 185 } 186 187 sc->sc_ccbs_paddr = sc->sc_dmamap->dm_segs[0].ds_addr; 188 ccb = (struct cac_ccb *)sc->sc_ccbs; 189 190 for (i = 0; i < CAC_MAX_CCBS; i++, ccb++) { 191 /* Create the DMA map for this CCB's data */ 192 error = bus_dmamap_create(sc->sc_dmat, CAC_MAX_XFER, 193 CAC_SG_SIZE, CAC_MAX_XFER, 0, 194 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 195 &ccb->ccb_dmamap_xfer); 196 197 if (error) { 198 printf("%s: can't create ccb dmamap (%d)\n", 199 sc->sc_dv.dv_xname, error); 200 break; 201 } 202 203 ccb->ccb_paddr = sc->sc_ccbs_paddr + i * sizeof(struct cac_ccb); 204 mtx_enter(&sc->sc_ccb_mtx); 205 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_chain); 206 mtx_leave(&sc->sc_ccb_mtx); 207 } 208 209 /* Start firmware background tasks, if needed. */ 210 if (startfw) { 211 if (cac_cmd(sc, CAC_CMD_START_FIRMWARE, &cinfo, sizeof(cinfo), 212 0, 0, CAC_CCB_DATA_IN, NULL)) { 213 printf("%s: CAC_CMD_START_FIRMWARE failed\n", 214 sc->sc_dv.dv_xname); 215 return (-1); 216 } 217 } 218 219 if (cac_cmd(sc, CAC_CMD_GET_CTRL_INFO, &cinfo, sizeof(cinfo), 0, 0, 220 CAC_CCB_DATA_IN, NULL)) { 221 printf("%s: CAC_CMD_GET_CTRL_INFO failed\n", 222 sc->sc_dv.dv_xname); 223 return (-1); 224 } 225 226 if (!cinfo.num_drvs) { 227 printf("%s: no volumes defined\n", sc->sc_dv.dv_xname); 228 return (-1); 229 } 230 231 sc->sc_nunits = cinfo.num_drvs; 232 sc->sc_dinfos = mallocarray(cinfo.num_drvs, 233 sizeof(struct cac_drive_info), M_DEVBUF, M_NOWAIT | M_ZERO); 234 if (sc->sc_dinfos == NULL) { 235 printf("%s: cannot allocate memory for drive_info\n", 236 sc->sc_dv.dv_xname); 237 return (-1); 238 } 239 240 sc->sc_link.adapter_softc = sc; 241 sc->sc_link.adapter = &cac_switch; 242 sc->sc_link.adapter_target = cinfo.num_drvs; 243 sc->sc_link.adapter_buswidth = cinfo.num_drvs; 244 sc->sc_link.openings = CAC_MAX_CCBS / sc->sc_nunits; 245 if (sc->sc_link.openings < 4 ) 246 sc->sc_link.openings = 4; 247 sc->sc_link.pool = &sc->sc_iopool; 248 249 bzero(&saa, sizeof(saa)); 250 saa.saa_sc_link = &sc->sc_link; 251 252 config_found(&sc->sc_dv, &saa, scsiprint); 253 254 (*sc->sc_cl->cl_intr_enable)(sc, 1); 255 256 #if NBIO > 0 257 if (bio_register(&sc->sc_dv, cac_ioctl) != 0) 258 printf("%s: controller registration failed\n", 259 sc->sc_dv.dv_xname); 260 else 261 sc->sc_ioctl = cac_ioctl; 262 263 #ifndef SMALL_KERNEL 264 if (cac_create_sensors(sc) != 0) 265 printf("%s: unable to create sensors\n", sc->sc_dv.dv_xname); 266 #endif 267 #endif 268 269 270 return (0); 271 } 272 273 int 274 cac_flush(sc) 275 struct cac_softc *sc; 276 { 277 u_int8_t buf[512]; 278 279 memset(buf, 0, sizeof(buf)); 280 buf[0] = 1; 281 return cac_cmd(sc, CAC_CMD_FLUSH_CACHE, buf, sizeof(buf), 0, 0, 282 CAC_CCB_DATA_OUT, NULL); 283 } 284 285 /* 286 * Handle an interrupt from the controller: process finished CCBs and 287 * dequeue any waiting CCBs. 288 */ 289 int 290 cac_intr(v) 291 void *v; 292 { 293 struct cac_softc *sc = v; 294 struct cac_ccb *ccb; 295 int istat, ret = 0; 296 297 if (!(istat = (*sc->sc_cl->cl_intr_pending)(sc))) 298 return 0; 299 300 if (istat & CAC_INTR_FIFO_NEMPTY) 301 while ((ccb = (*sc->sc_cl->cl_completed)(sc)) != NULL) { 302 ret = 1; 303 cac_ccb_done(sc, ccb); 304 } 305 cac_ccb_start(sc, NULL); 306 307 return (ret); 308 } 309 310 /* 311 * Execute a [polled] command. 312 */ 313 int 314 cac_cmd(struct cac_softc *sc, int command, void *data, int datasize, 315 int drive, int blkno, int flags, struct scsi_xfer *xs) 316 { 317 struct cac_ccb *ccb; 318 struct cac_sgb *sgb; 319 int i, rv, size, nsegs; 320 321 #ifdef CAC_DEBUG 322 printf("cac_cmd op=%x drv=%d blk=%d data=%p[%x] fl=%x xs=%p ", 323 command, drive, blkno, data, datasize, flags, xs); 324 #endif 325 326 if (xs) { 327 ccb = xs->io; 328 /* 329 * The xs may have been restarted by the scsi layer, so 330 * ensure the ccb starts in the proper state. 331 */ 332 ccb->ccb_flags = 0; 333 } else { 334 /* Internal command. Need to get our own ccb. */ 335 ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL | SCSI_NOSLEEP); 336 if (ccb == NULL) 337 return (EBUSY); 338 } 339 340 if ((flags & (CAC_CCB_DATA_IN | CAC_CCB_DATA_OUT)) != 0) { 341 bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap_xfer, 342 (void *)data, datasize, NULL, BUS_DMA_NOWAIT); 343 344 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0, 345 ccb->ccb_dmamap_xfer->dm_mapsize, 346 (flags & CAC_CCB_DATA_IN) != 0 ? BUS_DMASYNC_PREREAD : 347 BUS_DMASYNC_PREWRITE); 348 349 sgb = ccb->ccb_seg; 350 nsegs = ccb->ccb_dmamap_xfer->dm_nsegs; 351 if (nsegs > CAC_SG_SIZE) 352 panic("cac_cmd: nsegs botch"); 353 354 size = 0; 355 for (i = 0; i < nsegs; i++, sgb++) { 356 size += ccb->ccb_dmamap_xfer->dm_segs[i].ds_len; 357 sgb->length = 358 htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_len); 359 sgb->addr = 360 htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_addr); 361 } 362 } else { 363 size = datasize; 364 nsegs = 0; 365 } 366 367 ccb->ccb_hdr.drive = drive; 368 ccb->ccb_hdr.priority = 0; 369 ccb->ccb_hdr.size = htole16((sizeof(struct cac_req) + 370 sizeof(struct cac_sgb) * CAC_SG_SIZE) >> 2); 371 372 ccb->ccb_req.next = 0; 373 ccb->ccb_req.command = command; 374 ccb->ccb_req.error = 0; 375 ccb->ccb_req.blkno = htole32(blkno); 376 ccb->ccb_req.bcount = htole16(howmany(size, DEV_BSIZE)); 377 ccb->ccb_req.sgcount = nsegs; 378 ccb->ccb_req.reserved = 0; 379 380 ccb->ccb_flags = flags; 381 ccb->ccb_datasize = size; 382 ccb->ccb_xs = xs; 383 384 if (!xs || xs->flags & SCSI_POLL) { 385 /* Synchronous commands musn't wait. */ 386 mtx_enter(&sc->sc_ccb_mtx); 387 if ((*sc->sc_cl->cl_fifo_full)(sc)) { 388 mtx_leave(&sc->sc_ccb_mtx); 389 rv = EBUSY; 390 } else { 391 mtx_leave(&sc->sc_ccb_mtx); 392 ccb->ccb_flags |= CAC_CCB_ACTIVE; 393 (*sc->sc_cl->cl_submit)(sc, ccb); 394 rv = cac_ccb_poll(sc, ccb, 2000); 395 } 396 } else 397 rv = cac_ccb_start(sc, ccb); 398 399 if (xs == NULL) 400 scsi_io_put(&sc->sc_iopool, ccb); 401 402 return (rv); 403 } 404 405 /* 406 * Wait for the specified CCB to complete. Must be called at splbio. 407 */ 408 int 409 cac_ccb_poll(struct cac_softc *sc, struct cac_ccb *wantccb, int timo) 410 { 411 struct cac_ccb *ccb; 412 int t; 413 414 t = timo * 100; 415 do { 416 for (; t--; DELAY(10)) 417 if ((ccb = (*sc->sc_cl->cl_completed)(sc)) != NULL) 418 break; 419 if (t < 0) { 420 printf("%s: timeout\n", sc->sc_dv.dv_xname); 421 return (EBUSY); 422 } 423 cac_ccb_done(sc, ccb); 424 } while (ccb != wantccb); 425 426 return (0); 427 } 428 429 /* 430 * Enqueue the specified command (if any) and attempt to start all enqueued 431 * commands. 432 */ 433 int 434 cac_ccb_start(struct cac_softc *sc, struct cac_ccb *ccb) 435 { 436 if (ccb != NULL) { 437 mtx_enter(&sc->sc_ccb_mtx); 438 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ccb, ccb_chain); 439 mtx_leave(&sc->sc_ccb_mtx); 440 } 441 442 while (1) { 443 mtx_enter(&sc->sc_ccb_mtx); 444 if (SIMPLEQ_EMPTY(&sc->sc_ccb_queue) || 445 (*sc->sc_cl->cl_fifo_full)(sc)) { 446 mtx_leave(&sc->sc_ccb_mtx); 447 break; 448 } 449 ccb = SIMPLEQ_FIRST(&sc->sc_ccb_queue); 450 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ccb_chain); 451 mtx_leave(&sc->sc_ccb_mtx); 452 453 ccb->ccb_flags |= CAC_CCB_ACTIVE; 454 (*sc->sc_cl->cl_submit)(sc, ccb); 455 } 456 457 return (0); 458 } 459 460 /* 461 * Process a finished CCB. 462 */ 463 void 464 cac_ccb_done(struct cac_softc *sc, struct cac_ccb *ccb) 465 { 466 struct scsi_xfer *xs = ccb->ccb_xs; 467 int error = 0; 468 469 if ((ccb->ccb_flags & CAC_CCB_ACTIVE) == 0) { 470 printf("%s: CCB not active, xs=%p\n", sc->sc_dv.dv_xname, xs); 471 if (xs) { 472 xs->error = XS_DRIVER_STUFFUP; 473 scsi_done(xs); 474 } 475 return; 476 } 477 478 if ((ccb->ccb_flags & (CAC_CCB_DATA_IN | CAC_CCB_DATA_OUT)) != 0) { 479 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0, 480 ccb->ccb_dmamap_xfer->dm_mapsize, 481 ccb->ccb_flags & CAC_CCB_DATA_IN ? 482 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 483 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap_xfer); 484 } 485 486 if ((ccb->ccb_req.error & CAC_RET_SOFT_ERROR) != 0) 487 printf("%s: soft error; corrected\n", sc->sc_dv.dv_xname); 488 if ((ccb->ccb_req.error & CAC_RET_HARD_ERROR) != 0) { 489 error = 1; 490 printf("%s: hard error\n", sc->sc_dv.dv_xname); 491 } 492 if ((ccb->ccb_req.error & CAC_RET_CMD_REJECTED) != 0) { 493 error = 1; 494 printf("%s: invalid request\n", sc->sc_dv.dv_xname); 495 } 496 497 if (xs) { 498 if (error) 499 xs->error = XS_DRIVER_STUFFUP; 500 else 501 xs->resid = 0; 502 503 scsi_done(xs); 504 } 505 } 506 507 /* 508 * Allocate a CCB. 509 */ 510 void * 511 cac_ccb_alloc(void *xsc) 512 { 513 struct cac_softc *sc = xsc; 514 struct cac_ccb *ccb = NULL; 515 516 mtx_enter(&sc->sc_ccb_mtx); 517 if (SIMPLEQ_EMPTY(&sc->sc_ccb_free)) { 518 #ifdef CAC_DEBUG 519 printf("%s: unable to alloc CCB\n", sc->sc_dv.dv_xname); 520 #endif 521 } else { 522 ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free); 523 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ccb_chain); 524 } 525 mtx_leave(&sc->sc_ccb_mtx); 526 527 return (ccb); 528 } 529 530 /* 531 * Put a CCB onto the freelist. 532 */ 533 void 534 cac_ccb_free(void *xsc, void *xccb) 535 { 536 struct cac_softc *sc = xsc; 537 struct cac_ccb *ccb = xccb; 538 539 ccb->ccb_flags = 0; 540 541 mtx_enter(&sc->sc_ccb_mtx); 542 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_chain); 543 mtx_leave(&sc->sc_ccb_mtx); 544 } 545 546 int 547 cac_get_dinfo(sc, target) 548 struct cac_softc *sc; 549 int target; 550 { 551 if (sc->sc_dinfos[target].ncylinders) 552 return (0); 553 554 if (cac_cmd(sc, CAC_CMD_GET_LOG_DRV_INFO, &sc->sc_dinfos[target], 555 sizeof(*sc->sc_dinfos), target, 0, CAC_CCB_DATA_IN, NULL)) { 556 printf("%s: CMD_GET_LOG_DRV_INFO failed\n", 557 sc->sc_dv.dv_xname); 558 return (-1); 559 } 560 561 return (0); 562 } 563 564 void 565 cacminphys(struct buf *bp, struct scsi_link *sl) 566 { 567 if (bp->b_bcount > CAC_MAX_XFER) 568 bp->b_bcount = CAC_MAX_XFER; 569 minphys(bp); 570 } 571 572 void 573 cac_copy_internal_data(xs, v, size) 574 struct scsi_xfer *xs; 575 void *v; 576 size_t size; 577 { 578 size_t copy_cnt; 579 580 if (!xs->datalen) 581 printf("uio move is not yet supported\n"); 582 else { 583 copy_cnt = MIN(size, xs->datalen); 584 bcopy(v, xs->data, copy_cnt); 585 } 586 } 587 588 void 589 cac_scsi_cmd(xs) 590 struct scsi_xfer *xs; 591 { 592 struct scsi_link *link = xs->sc_link; 593 struct cac_softc *sc = link->adapter_softc; 594 struct cac_drive_info *dinfo; 595 struct scsi_inquiry_data inq; 596 struct scsi_sense_data sd; 597 struct scsi_read_cap_data rcd; 598 u_int8_t target = link->target; 599 u_int32_t blockno, blockcnt, size; 600 struct scsi_rw *rw; 601 struct scsi_rw_big *rwb; 602 int op, flags, s, error; 603 const char *p; 604 605 if (target >= sc->sc_nunits || link->lun != 0) { 606 xs->error = XS_DRIVER_STUFFUP; 607 scsi_done(xs); 608 return; 609 } 610 611 s = splbio(); 612 xs->error = XS_NOERROR; 613 dinfo = &sc->sc_dinfos[target]; 614 615 switch (xs->cmd->opcode) { 616 case TEST_UNIT_READY: 617 case START_STOP: 618 #if 0 619 case VERIFY: 620 #endif 621 break; 622 623 case REQUEST_SENSE: 624 bzero(&sd, sizeof sd); 625 sd.error_code = SSD_ERRCODE_CURRENT; 626 sd.segment = 0; 627 sd.flags = SKEY_NO_SENSE; 628 *(u_int32_t*)sd.info = htole32(0); 629 sd.extra_len = 0; 630 cac_copy_internal_data(xs, &sd, sizeof sd); 631 break; 632 633 case INQUIRY: 634 if (cac_get_dinfo(sc, target)) { 635 xs->error = XS_DRIVER_STUFFUP; 636 break; 637 } 638 bzero(&inq, sizeof inq); 639 inq.device = T_DIRECT; 640 inq.dev_qual2 = 0; 641 inq.version = 2; 642 inq.response_format = 2; 643 inq.additional_length = 32; 644 inq.flags |= SID_CmdQue; 645 strlcpy(inq.vendor, "Compaq ", sizeof inq.vendor); 646 switch (CAC_GET1(dinfo->mirror)) { 647 case 0: p = "RAID0"; break; 648 case 1: p = "RAID4"; break; 649 case 2: p = "RAID1"; break; 650 case 3: p = "RAID5"; break; 651 default:p = "<UNK>"; break; 652 } 653 snprintf(inq.product, sizeof inq.product, "%s vol #%02d", 654 p, target); 655 strlcpy(inq.revision, " ", sizeof inq.revision); 656 cac_copy_internal_data(xs, &inq, sizeof inq); 657 break; 658 659 case READ_CAPACITY: 660 if (cac_get_dinfo(sc, target)) { 661 xs->error = XS_DRIVER_STUFFUP; 662 break; 663 } 664 bzero(&rcd, sizeof rcd); 665 _lto4b( CAC_GET2(dinfo->ncylinders) * CAC_GET1(dinfo->nheads) * 666 CAC_GET1(dinfo->nsectors) - 1, rcd.addr); 667 _lto4b(CAC_SECTOR_SIZE, rcd.length); 668 cac_copy_internal_data(xs, &rcd, sizeof rcd); 669 break; 670 671 case PREVENT_ALLOW: 672 break; 673 674 case SYNCHRONIZE_CACHE: 675 if (cac_flush(sc)) 676 xs->error = XS_DRIVER_STUFFUP; 677 break; 678 679 case READ_COMMAND: 680 case READ_BIG: 681 case WRITE_COMMAND: 682 case WRITE_BIG: 683 684 flags = 0; 685 /* A read or write operation. */ 686 if (xs->cmdlen == 6) { 687 rw = (struct scsi_rw *)xs->cmd; 688 blockno = _3btol(rw->addr) & 689 (SRW_TOPADDR << 16 | 0xffff); 690 blockcnt = rw->length ? rw->length : 0x100; 691 } else { 692 rwb = (struct scsi_rw_big *)xs->cmd; 693 blockno = _4btol(rwb->addr); 694 blockcnt = _2btol(rwb->length); 695 } 696 size = CAC_GET2(dinfo->ncylinders) * 697 CAC_GET1(dinfo->nheads) * CAC_GET1(dinfo->nsectors); 698 if (blockno >= size || blockno + blockcnt > size) { 699 printf("%s: out of bounds %u-%u >= %u\n", 700 sc->sc_dv.dv_xname, blockno, blockcnt, size); 701 xs->error = XS_DRIVER_STUFFUP; 702 break; 703 } 704 705 switch (xs->cmd->opcode) { 706 case READ_COMMAND: 707 case READ_BIG: 708 op = CAC_CMD_READ; 709 flags = CAC_CCB_DATA_IN; 710 break; 711 case WRITE_COMMAND: 712 case WRITE_BIG: 713 op = CAC_CMD_WRITE; 714 flags = CAC_CCB_DATA_OUT; 715 break; 716 } 717 718 if ((error = cac_cmd(sc, op, xs->data, blockcnt * DEV_BSIZE, 719 target, blockno, flags, xs))) { 720 splx(s); 721 if (error == EBUSY) 722 xs->error = XS_BUSY; 723 else 724 xs->error = XS_DRIVER_STUFFUP; 725 scsi_done(xs); 726 return; 727 } 728 729 splx(s); 730 return; 731 732 default: 733 SC_DEBUG(link, SDEV_DB1, ("unsupported scsi command %#x " 734 "tgt %d ", xs->cmd->opcode, target)); 735 xs->error = XS_DRIVER_STUFFUP; 736 } 737 738 splx(s); 739 scsi_done(xs); 740 } 741 742 /* 743 * Board specific linkage shared between multiple bus types. 744 */ 745 746 int 747 cac_l0_fifo_full(struct cac_softc *sc) 748 { 749 750 return (cac_inl(sc, CAC_REG_CMD_FIFO) == 0); 751 } 752 753 void 754 cac_l0_submit(struct cac_softc *sc, struct cac_ccb *ccb) 755 { 756 #ifdef CAC_DEBUG 757 printf("submit-%x ", ccb->ccb_paddr); 758 #endif 759 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 760 sc->sc_dmamap->dm_mapsize, 761 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 762 cac_outl(sc, CAC_REG_CMD_FIFO, ccb->ccb_paddr); 763 } 764 765 struct cac_ccb * 766 cac_l0_completed(sc) 767 struct cac_softc *sc; 768 { 769 struct cac_ccb *ccb; 770 paddr_t off, orig_off; 771 772 if (!(off = cac_inl(sc, CAC_REG_DONE_FIFO))) 773 return NULL; 774 #ifdef CAC_DEBUG 775 printf("compl-%x ", off); 776 #endif 777 orig_off = off; 778 779 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 780 sc->sc_dmamap->dm_mapsize, 781 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 782 783 off = (off & ~3) - sc->sc_ccbs_paddr; 784 ccb = (struct cac_ccb *)(sc->sc_ccbs + off); 785 786 if (orig_off & 3 && ccb->ccb_req.error == 0) 787 ccb->ccb_req.error = CAC_RET_CMD_INVALID; 788 789 return (ccb); 790 } 791 792 int 793 cac_l0_intr_pending(struct cac_softc *sc) 794 { 795 796 return (cac_inl(sc, CAC_REG_INTR_PENDING)); 797 } 798 799 void 800 cac_l0_intr_enable(struct cac_softc *sc, int state) 801 { 802 803 cac_outl(sc, CAC_REG_INTR_MASK, 804 state ? CAC_INTR_ENABLE : CAC_INTR_DISABLE); 805 } 806 807 #if NBIO > 0 808 const int cac_level[] = { 0, 4, 1, 5, 51, 7 }; 809 const int cac_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE, 810 BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED, 811 BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING, 812 BIOC_SVOFFLINE, BIOC_SVBUILDING }; 813 814 int 815 cac_ioctl(struct device *dev, u_long cmd, caddr_t addr) 816 { 817 struct cac_softc *sc = (struct cac_softc *)dev; 818 struct bioc_inq *bi; 819 struct bioc_disk *bd; 820 cac_lock_t lock; 821 int error = 0; 822 823 lock = CAC_LOCK(sc); 824 switch (cmd) { 825 case BIOCINQ: 826 bi = (struct bioc_inq *)addr; 827 strlcpy(bi->bi_dev, sc->sc_dv.dv_xname, sizeof(bi->bi_dev)); 828 bi->bi_novol = sc->sc_nunits; 829 bi->bi_nodisk = 0; 830 break; 831 832 case BIOCVOL: 833 error = cac_ioctl_vol(sc, (struct bioc_vol *)addr); 834 break; 835 836 case BIOCDISK: 837 bd = (struct bioc_disk *)addr; 838 if (bd->bd_volid > sc->sc_nunits) { 839 error = EINVAL; 840 break; 841 } 842 /* No disk information yet */ 843 break; 844 845 case BIOCBLINK: 846 case BIOCALARM: 847 case BIOCSETSTATE: 848 default: 849 error = ENOTTY; 850 } 851 CAC_UNLOCK(sc, lock); 852 853 return (error); 854 } 855 856 int 857 cac_ioctl_vol(struct cac_softc *sc, struct bioc_vol *bv) 858 { 859 struct cac_drive_info dinfo; 860 struct cac_drive_status dstatus; 861 u_int32_t blks; 862 863 if (bv->bv_volid > sc->sc_nunits) 864 return (EINVAL); 865 if (cac_cmd(sc, CAC_CMD_GET_LOG_DRV_INFO, &dinfo, sizeof(dinfo), 866 bv->bv_volid, 0, CAC_CCB_DATA_IN, NULL)) 867 return (EIO); 868 if (cac_cmd(sc, CAC_CMD_SENSE_DRV_STATUS, &dstatus, sizeof(dstatus), 869 bv->bv_volid, 0, CAC_CCB_DATA_IN, NULL)) 870 return (EIO); 871 bv->bv_status = BIOC_SVINVALID; 872 blks = CAC_GET2(dinfo.ncylinders) * CAC_GET1(dinfo.nheads) * 873 CAC_GET1(dinfo.nsectors); 874 bv->bv_size = (off_t)blks * CAC_GET2(dinfo.secsize); 875 bv->bv_level = cac_level[CAC_GET1(dinfo.mirror)]; /*XXX limit check */ 876 bv->bv_nodisk = 0; /* XXX */ 877 bv->bv_status = 0; /* XXX */ 878 bv->bv_percent = -1; 879 bv->bv_seconds = 0; 880 if (dstatus.stat < nitems(cac_stat)) 881 bv->bv_status = cac_stat[dstatus.stat]; 882 if (bv->bv_status == BIOC_SVREBUILD || 883 bv->bv_status == BIOC_SVBUILDING) 884 bv->bv_percent = ((blks - CAC_GET4(dstatus.prog)) * 1000ULL) / 885 blks; 886 887 return (0); 888 } 889 890 #ifndef SMALL_KERNEL 891 int 892 cac_create_sensors(struct cac_softc *sc) 893 { 894 struct device *dev; 895 struct scsibus_softc *ssc = NULL; 896 struct scsi_link *link; 897 int i; 898 899 TAILQ_FOREACH(dev, &alldevs, dv_list) { 900 if (dev->dv_parent != &sc->sc_dv) 901 continue; 902 903 /* check if this is the scsibus for the logical disks */ 904 ssc = (struct scsibus_softc *)dev; 905 if (ssc->adapter_link == &sc->sc_link) 906 break; 907 ssc = NULL; 908 } 909 910 if (ssc == NULL) 911 return (1); 912 913 sc->sc_sensors = mallocarray(sc->sc_nunits, 914 sizeof(struct ksensor), M_DEVBUF, M_NOWAIT | M_ZERO); 915 if (sc->sc_sensors == NULL) 916 return (1); 917 918 strlcpy(sc->sc_sensordev.xname, sc->sc_dv.dv_xname, 919 sizeof(sc->sc_sensordev.xname)); 920 921 for (i = 0; i < sc->sc_nunits; i++) { 922 link = scsi_get_link(ssc, i, 0); 923 if (link == NULL) 924 goto bad; 925 926 dev = link->device_softc; 927 928 sc->sc_sensors[i].type = SENSOR_DRIVE; 929 sc->sc_sensors[i].status = SENSOR_S_UNKNOWN; 930 931 strlcpy(sc->sc_sensors[i].desc, dev->dv_xname, 932 sizeof(sc->sc_sensors[i].desc)); 933 934 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]); 935 } 936 937 if (sensor_task_register(sc, cac_sensor_refresh, 10) == NULL) 938 goto bad; 939 940 sensordev_install(&sc->sc_sensordev); 941 942 return (0); 943 944 bad: 945 free(sc->sc_sensors, M_DEVBUF, 0); 946 947 return (1); 948 } 949 950 void 951 cac_sensor_refresh(void *arg) 952 { 953 struct cac_softc *sc = arg; 954 struct bioc_vol bv; 955 int i, s; 956 957 for (i = 0; i < sc->sc_nunits; i++) { 958 bzero(&bv, sizeof(bv)); 959 bv.bv_volid = i; 960 s = splbio(); 961 if (cac_ioctl_vol(sc, &bv)) { 962 splx(s); 963 return; 964 } 965 splx(s); 966 967 switch (bv.bv_status) { 968 case BIOC_SVOFFLINE: 969 sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL; 970 sc->sc_sensors[i].status = SENSOR_S_CRIT; 971 break; 972 973 case BIOC_SVDEGRADED: 974 sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL; 975 sc->sc_sensors[i].status = SENSOR_S_WARN; 976 break; 977 978 case BIOC_SVSCRUB: 979 case BIOC_SVONLINE: 980 sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE; 981 sc->sc_sensors[i].status = SENSOR_S_OK; 982 break; 983 984 case BIOC_SVREBUILD: 985 case BIOC_SVBUILDING: 986 sc->sc_sensors[i].value = SENSOR_DRIVE_REBUILD; 987 sc->sc_sensors[i].status = SENSOR_S_OK; 988 break; 989 990 case BIOC_SVINVALID: 991 /* FALLTRHOUGH */ 992 default: 993 sc->sc_sensors[i].value = 0; /* unknown */ 994 sc->sc_sensors[i].status = SENSOR_S_UNKNOWN; 995 } 996 } 997 } 998 #endif /* SMALL_KERNEL */ 999 #endif /* NBIO > 0 */ 1000