1 /* $OpenBSD: cac.c,v 1.30 2009/03/07 16:48:31 krw 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/proc.h> 76 #include <sys/buf.h> 77 #include <sys/endian.h> 78 #include <sys/malloc.h> 79 #include <sys/pool.h> 80 81 #include <machine/bus.h> 82 83 #include <scsi/scsi_all.h> 84 #include <scsi/scsi_disk.h> 85 #include <scsi/scsiconf.h> 86 87 #include <dev/ic/cacreg.h> 88 #include <dev/ic/cacvar.h> 89 90 #if NBIO > 0 91 #include <dev/biovar.h> 92 #endif 93 #include <sys/sensors.h> 94 95 struct cfdriver cac_cd = { 96 NULL, "cac", DV_DULL 97 }; 98 99 int cac_scsi_cmd(struct scsi_xfer *); 100 void cacminphys(struct buf *bp, struct scsi_link *sl); 101 102 struct scsi_adapter cac_switch = { 103 cac_scsi_cmd, cacminphys, 0, 0, 104 }; 105 106 struct scsi_device cac_dev = { 107 NULL, NULL, NULL, NULL 108 }; 109 110 struct cac_ccb *cac_ccb_alloc(struct cac_softc *, int); 111 void cac_ccb_done(struct cac_softc *, struct cac_ccb *); 112 void cac_ccb_free(struct cac_softc *, struct cac_ccb *); 113 int cac_ccb_poll(struct cac_softc *, struct cac_ccb *, int); 114 int cac_ccb_start(struct cac_softc *, struct cac_ccb *); 115 int cac_cmd(struct cac_softc *sc, int command, void *data, int datasize, 116 int drive, int blkno, int flags, struct scsi_xfer *xs); 117 int cac_get_dinfo(struct cac_softc *sc, int target); 118 int cac_flush(struct cac_softc *sc); 119 void cac_shutdown(void *); 120 void cac_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size); 121 122 struct cac_ccb *cac_l0_completed(struct cac_softc *); 123 int cac_l0_fifo_full(struct cac_softc *); 124 void cac_l0_intr_enable(struct cac_softc *, int); 125 int cac_l0_intr_pending(struct cac_softc *); 126 void cac_l0_submit(struct cac_softc *, struct cac_ccb *); 127 128 #if NBIO > 0 129 int cac_ioctl(struct device *, u_long, caddr_t); 130 int cac_ioctl_vol(struct cac_softc *, struct bioc_vol *); 131 132 #ifndef SMALL_KERNEL 133 int cac_create_sensors(struct cac_softc *); 134 void cac_sensor_refresh(void *); 135 #endif 136 #endif /* NBIO > 0 */ 137 138 void *cac_sdh; /* shutdown hook */ 139 140 const 141 struct cac_linkage cac_l0 = { 142 cac_l0_completed, 143 cac_l0_fifo_full, 144 cac_l0_intr_enable, 145 cac_l0_intr_pending, 146 cac_l0_submit 147 }; 148 149 /* 150 * Initialise our interface to the controller. 151 */ 152 int 153 cac_init(struct cac_softc *sc, int startfw) 154 { 155 struct scsibus_attach_args saa; 156 struct cac_controller_info cinfo; 157 int error, rseg, size, i; 158 bus_dma_segment_t seg[1]; 159 struct cac_ccb *ccb; 160 161 SIMPLEQ_INIT(&sc->sc_ccb_free); 162 SIMPLEQ_INIT(&sc->sc_ccb_queue); 163 164 size = sizeof(struct cac_ccb) * CAC_MAX_CCBS; 165 166 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, seg, 1, 167 &rseg, BUS_DMA_NOWAIT)) != 0) { 168 printf("%s: unable to allocate CCBs, error = %d\n", 169 sc->sc_dv.dv_xname, error); 170 return (-1); 171 } 172 173 if ((error = bus_dmamem_map(sc->sc_dmat, seg, rseg, size, 174 &sc->sc_ccbs, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 175 printf("%s: unable to map CCBs, error = %d\n", 176 sc->sc_dv.dv_xname, error); 177 return (-1); 178 } 179 180 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 181 BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) { 182 printf("%s: unable to create CCB DMA map, error = %d\n", 183 sc->sc_dv.dv_xname, error); 184 return (-1); 185 } 186 187 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_ccbs, 188 size, NULL, BUS_DMA_NOWAIT)) != 0) { 189 printf("%s: unable to load CCB DMA map, error = %d\n", 190 sc->sc_dv.dv_xname, error); 191 return (-1); 192 } 193 194 sc->sc_ccbs_paddr = sc->sc_dmamap->dm_segs[0].ds_addr; 195 memset(sc->sc_ccbs, 0, size); 196 ccb = (struct cac_ccb *)sc->sc_ccbs; 197 198 for (i = 0; i < CAC_MAX_CCBS; i++, ccb++) { 199 /* Create the DMA map for this CCB's data */ 200 error = bus_dmamap_create(sc->sc_dmat, CAC_MAX_XFER, 201 CAC_SG_SIZE, CAC_MAX_XFER, 0, 202 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 203 &ccb->ccb_dmamap_xfer); 204 205 if (error) { 206 printf("%s: can't create ccb dmamap (%d)\n", 207 sc->sc_dv.dv_xname, error); 208 break; 209 } 210 211 ccb->ccb_paddr = sc->sc_ccbs_paddr + i * sizeof(struct cac_ccb); 212 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_chain); 213 } 214 215 /* Start firmware background tasks, if needed. */ 216 if (startfw) { 217 if (cac_cmd(sc, CAC_CMD_START_FIRMWARE, &cinfo, sizeof(cinfo), 218 0, 0, CAC_CCB_DATA_IN, NULL)) { 219 printf("%s: CAC_CMD_START_FIRMWARE failed\n", 220 sc->sc_dv.dv_xname); 221 return (-1); 222 } 223 } 224 225 if (cac_cmd(sc, CAC_CMD_GET_CTRL_INFO, &cinfo, sizeof(cinfo), 0, 0, 226 CAC_CCB_DATA_IN, NULL)) { 227 printf("%s: CAC_CMD_GET_CTRL_INFO failed\n", 228 sc->sc_dv.dv_xname); 229 return (-1); 230 } 231 232 if (!cinfo.num_drvs) { 233 printf("%s: no volumes defined\n", sc->sc_dv.dv_xname); 234 return (-1); 235 } 236 237 sc->sc_nunits = cinfo.num_drvs; 238 sc->sc_dinfos = malloc(cinfo.num_drvs * sizeof(struct cac_drive_info), 239 M_DEVBUF, M_NOWAIT | M_ZERO); 240 if (sc->sc_dinfos == NULL) { 241 printf("%s: cannot allocate memory for drive_info\n", 242 sc->sc_dv.dv_xname); 243 return (-1); 244 } 245 246 sc->sc_link.adapter_softc = sc; 247 sc->sc_link.adapter = &cac_switch; 248 sc->sc_link.adapter_target = cinfo.num_drvs; 249 sc->sc_link.adapter_buswidth = cinfo.num_drvs; 250 sc->sc_link.device = &cac_dev; 251 sc->sc_link.openings = CAC_MAX_CCBS / sc->sc_nunits; 252 if (sc->sc_link.openings < 4 ) 253 sc->sc_link.openings = 4; 254 255 bzero(&saa, sizeof(saa)); 256 saa.saa_sc_link = &sc->sc_link; 257 258 config_found(&sc->sc_dv, &saa, scsiprint); 259 260 /* Set our `shutdownhook' before we start any device activity. */ 261 if (cac_sdh == NULL) 262 cac_sdh = shutdownhook_establish(cac_shutdown, NULL); 263 264 (*sc->sc_cl->cl_intr_enable)(sc, 1); 265 266 #if NBIO > 0 267 if (bio_register(&sc->sc_dv, cac_ioctl) != 0) 268 printf("%s: controller registration failed\n", 269 sc->sc_dv.dv_xname); 270 else 271 sc->sc_ioctl = cac_ioctl; 272 273 #ifndef SMALL_KERNEL 274 if (cac_create_sensors(sc) != 0) 275 printf("%s: unable to create sensors\n", sc->sc_dv.dv_xname); 276 #endif 277 #endif 278 279 280 return (0); 281 } 282 283 int 284 cac_flush(sc) 285 struct cac_softc *sc; 286 { 287 u_int8_t buf[512]; 288 289 memset(buf, 0, sizeof(buf)); 290 buf[0] = 1; 291 return cac_cmd(sc, CAC_CMD_FLUSH_CACHE, buf, sizeof(buf), 0, 0, 292 CAC_CCB_DATA_OUT, NULL); 293 } 294 295 /* 296 * Shut down all `cac' controllers. 297 */ 298 void 299 cac_shutdown(void *cookie) 300 { 301 extern struct cfdriver cac_cd; 302 struct cac_softc *sc; 303 int i; 304 305 for (i = 0; i < cac_cd.cd_ndevs; i++) { 306 if ((sc = (struct cac_softc *)device_lookup(&cac_cd, i)) == NULL) 307 continue; 308 cac_flush(sc); 309 } 310 } 311 312 /* 313 * Handle an interrupt from the controller: process finished CCBs and 314 * dequeue any waiting CCBs. 315 */ 316 int 317 cac_intr(v) 318 void *v; 319 { 320 struct cac_softc *sc = v; 321 struct cac_ccb *ccb; 322 int istat, ret = 0; 323 324 if (!(istat = (sc->sc_cl->cl_intr_pending)(sc))) 325 return 0; 326 327 if (istat & CAC_INTR_FIFO_NEMPTY) 328 while ((ccb = (*sc->sc_cl->cl_completed)(sc)) != NULL) { 329 ret = 1; 330 cac_ccb_done(sc, ccb); 331 } 332 cac_ccb_start(sc, NULL); 333 334 return (ret); 335 } 336 337 /* 338 * Execute a [polled] command. 339 */ 340 int 341 cac_cmd(struct cac_softc *sc, int command, void *data, int datasize, 342 int drive, int blkno, int flags, struct scsi_xfer *xs) 343 { 344 struct cac_ccb *ccb; 345 struct cac_sgb *sgb; 346 int i, rv, size, nsegs; 347 348 #ifdef CAC_DEBUG 349 printf("cac_cmd op=%x drv=%d blk=%d data=%p[%x] fl=%x xs=%p ", 350 command, drive, blkno, data, datasize, flags, xs); 351 #endif 352 353 if ((ccb = cac_ccb_alloc(sc, 0)) == NULL) { 354 #ifdef CAC_DEBUG 355 printf("%s: unable to alloc CCB\n", sc->sc_dv.dv_xname); 356 #endif 357 return (ENOMEM); 358 } 359 360 if ((flags & (CAC_CCB_DATA_IN | CAC_CCB_DATA_OUT)) != 0) { 361 bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap_xfer, 362 (void *)data, datasize, NULL, BUS_DMA_NOWAIT); 363 364 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0, 365 ccb->ccb_dmamap_xfer->dm_mapsize, 366 (flags & CAC_CCB_DATA_IN) != 0 ? BUS_DMASYNC_PREREAD : 367 BUS_DMASYNC_PREWRITE); 368 369 sgb = ccb->ccb_seg; 370 nsegs = ccb->ccb_dmamap_xfer->dm_nsegs; 371 if (nsegs > CAC_SG_SIZE) 372 panic("cac_cmd: nsegs botch"); 373 374 size = 0; 375 for (i = 0; i < nsegs; i++, sgb++) { 376 size += ccb->ccb_dmamap_xfer->dm_segs[i].ds_len; 377 sgb->length = 378 htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_len); 379 sgb->addr = 380 htole32(ccb->ccb_dmamap_xfer->dm_segs[i].ds_addr); 381 } 382 } else { 383 size = datasize; 384 nsegs = 0; 385 } 386 387 ccb->ccb_hdr.drive = drive; 388 ccb->ccb_hdr.priority = 0; 389 ccb->ccb_hdr.size = htole16((sizeof(struct cac_req) + 390 sizeof(struct cac_sgb) * CAC_SG_SIZE) >> 2); 391 392 ccb->ccb_req.next = 0; 393 ccb->ccb_req.command = command; 394 ccb->ccb_req.error = 0; 395 ccb->ccb_req.blkno = htole32(blkno); 396 ccb->ccb_req.bcount = htole16(howmany(size, DEV_BSIZE)); 397 ccb->ccb_req.sgcount = nsegs; 398 ccb->ccb_req.reserved = 0; 399 400 ccb->ccb_flags = flags; 401 ccb->ccb_datasize = size; 402 ccb->ccb_xs = xs; 403 404 if (!xs || xs->flags & SCSI_POLL) { 405 406 /* Synchronous commands musn't wait. */ 407 if ((*sc->sc_cl->cl_fifo_full)(sc)) { 408 cac_ccb_free(sc, ccb); 409 rv = ENOMEM; /* Causes NO_CCB, i/o is retried. */ 410 } else { 411 ccb->ccb_flags |= CAC_CCB_ACTIVE; 412 (*sc->sc_cl->cl_submit)(sc, ccb); 413 rv = cac_ccb_poll(sc, ccb, 2000); 414 } 415 } else 416 rv = cac_ccb_start(sc, ccb); 417 418 return (rv); 419 } 420 421 /* 422 * Wait for the specified CCB to complete. Must be called at splbio. 423 */ 424 int 425 cac_ccb_poll(struct cac_softc *sc, struct cac_ccb *wantccb, int timo) 426 { 427 struct cac_ccb *ccb; 428 int s, t = timo * 100; 429 430 do { 431 for (; t--; DELAY(10)) 432 if ((ccb = (*sc->sc_cl->cl_completed)(sc)) != NULL) 433 break; 434 if (t < 0) { 435 printf("%s: timeout\n", sc->sc_dv.dv_xname); 436 return (EBUSY); 437 } 438 s = splbio(); 439 cac_ccb_done(sc, ccb); 440 splx(s); 441 } while (ccb != wantccb); 442 443 return (0); 444 } 445 446 /* 447 * Enqueue the specified command (if any) and attempt to start all enqueued 448 * commands. Must be called at splbio. 449 */ 450 int 451 cac_ccb_start(struct cac_softc *sc, struct cac_ccb *ccb) 452 { 453 if (ccb != NULL) 454 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ccb, ccb_chain); 455 456 while ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL && 457 !(*sc->sc_cl->cl_fifo_full)(sc)) { 458 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ccb_chain); 459 ccb->ccb_flags |= CAC_CCB_ACTIVE; 460 (*sc->sc_cl->cl_submit)(sc, ccb); 461 } 462 463 return (0); 464 } 465 466 /* 467 * Process a finished CCB. 468 */ 469 void 470 cac_ccb_done(struct cac_softc *sc, struct cac_ccb *ccb) 471 { 472 struct scsi_xfer *xs = ccb->ccb_xs; 473 int error = 0; 474 475 if ((ccb->ccb_flags & CAC_CCB_ACTIVE) == 0) { 476 printf("%s: CCB not active, xs=%p\n", sc->sc_dv.dv_xname, xs); 477 if (xs) { 478 xs->error = XS_DRIVER_STUFFUP; 479 scsi_done(xs); 480 } 481 return; 482 } 483 484 if ((ccb->ccb_flags & (CAC_CCB_DATA_IN | CAC_CCB_DATA_OUT)) != 0) { 485 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap_xfer, 0, 486 ccb->ccb_dmamap_xfer->dm_mapsize, 487 ccb->ccb_flags & CAC_CCB_DATA_IN ? 488 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 489 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap_xfer); 490 } 491 492 if ((ccb->ccb_req.error & CAC_RET_SOFT_ERROR) != 0) 493 printf("%s: soft error; corrected\n", sc->sc_dv.dv_xname); 494 if ((ccb->ccb_req.error & CAC_RET_HARD_ERROR) != 0) { 495 error = 1; 496 printf("%s: hard error\n", sc->sc_dv.dv_xname); 497 } 498 if ((ccb->ccb_req.error & CAC_RET_CMD_REJECTED) != 0) { 499 error = 1; 500 printf("%s: invalid request\n", sc->sc_dv.dv_xname); 501 } 502 503 cac_ccb_free(sc, ccb); 504 if (xs) { 505 if (error) 506 xs->error = XS_DRIVER_STUFFUP; 507 else 508 xs->resid = 0; 509 510 xs->flags |= ITSDONE; 511 scsi_done(xs); 512 } 513 } 514 515 /* 516 * Allocate a CCB. 517 */ 518 struct cac_ccb * 519 cac_ccb_alloc(struct cac_softc *sc, int nosleep) 520 { 521 struct cac_ccb *ccb; 522 523 if ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free)) != NULL) 524 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ccb_chain); 525 else 526 ccb = NULL; 527 return (ccb); 528 } 529 530 /* 531 * Put a CCB onto the freelist. 532 */ 533 void 534 cac_ccb_free(struct cac_softc *sc, struct cac_ccb *ccb) 535 { 536 537 ccb->ccb_flags = 0; 538 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_chain); 539 } 540 541 int 542 cac_get_dinfo(sc, target) 543 struct cac_softc *sc; 544 int target; 545 { 546 if (sc->sc_dinfos[target].ncylinders) 547 return (0); 548 549 if (cac_cmd(sc, CAC_CMD_GET_LOG_DRV_INFO, &sc->sc_dinfos[target], 550 sizeof(*sc->sc_dinfos), target, 0, CAC_CCB_DATA_IN, NULL)) { 551 printf("%s: CMD_GET_LOG_DRV_INFO failed\n", 552 sc->sc_dv.dv_xname); 553 return (-1); 554 } 555 556 return (0); 557 } 558 559 void 560 cacminphys(struct buf *bp, struct scsi_link *sl) 561 { 562 if (bp->b_bcount > CAC_MAX_XFER) 563 bp->b_bcount = CAC_MAX_XFER; 564 minphys(bp); 565 } 566 567 void 568 cac_copy_internal_data(xs, v, size) 569 struct scsi_xfer *xs; 570 void *v; 571 size_t size; 572 { 573 size_t copy_cnt; 574 575 if (!xs->datalen) 576 printf("uio move is not yet supported\n"); 577 else { 578 copy_cnt = MIN(size, xs->datalen); 579 bcopy(v, xs->data, copy_cnt); 580 } 581 } 582 583 int 584 cac_scsi_cmd(xs) 585 struct scsi_xfer *xs; 586 { 587 struct scsi_link *link = xs->sc_link; 588 struct cac_softc *sc = link->adapter_softc; 589 struct cac_drive_info *dinfo; 590 struct scsi_inquiry_data inq; 591 struct scsi_sense_data sd; 592 struct scsi_read_cap_data rcd; 593 u_int8_t target = link->target; 594 u_int32_t blockno, blockcnt, size; 595 struct scsi_rw *rw; 596 struct scsi_rw_big *rwb; 597 int op, flags, s, error, poll; 598 const char *p; 599 600 if (target >= sc->sc_nunits || link->lun != 0) { 601 xs->error = XS_DRIVER_STUFFUP; 602 return (COMPLETE); 603 } 604 605 s = splbio(); 606 xs->error = XS_NOERROR; 607 xs->free_list.le_next = NULL; 608 dinfo = &sc->sc_dinfos[target]; 609 610 switch (xs->cmd->opcode) { 611 case TEST_UNIT_READY: 612 case START_STOP: 613 #if 0 614 case VERIFY: 615 #endif 616 break; 617 618 case REQUEST_SENSE: 619 bzero(&sd, sizeof sd); 620 sd.error_code = 0x70; 621 sd.segment = 0; 622 sd.flags = SKEY_NO_SENSE; 623 *(u_int32_t*)sd.info = htole32(0); 624 sd.extra_len = 0; 625 cac_copy_internal_data(xs, &sd, sizeof sd); 626 break; 627 628 case INQUIRY: 629 if (cac_get_dinfo(sc, target)) { 630 xs->error = XS_DRIVER_STUFFUP; 631 break; 632 } 633 bzero(&inq, sizeof inq); 634 inq.device = T_DIRECT; 635 inq.dev_qual2 = 0; 636 inq.version = 2; 637 inq.response_format = 2; 638 inq.additional_length = 32; 639 strlcpy(inq.vendor, "Compaq ", sizeof inq.vendor); 640 switch (CAC_GET1(dinfo->mirror)) { 641 case 0: p = "RAID0"; break; 642 case 1: p = "RAID4"; break; 643 case 2: p = "RAID1"; break; 644 case 3: p = "RAID5"; break; 645 default:p = "<UNK>"; break; 646 } 647 snprintf(inq.product, sizeof inq.product, "%s vol #%02d", 648 p, target); 649 strlcpy(inq.revision, " ", sizeof inq.revision); 650 cac_copy_internal_data(xs, &inq, sizeof inq); 651 break; 652 653 case READ_CAPACITY: 654 if (cac_get_dinfo(sc, target)) { 655 xs->error = XS_DRIVER_STUFFUP; 656 break; 657 } 658 bzero(&rcd, sizeof rcd); 659 _lto4b( CAC_GET2(dinfo->ncylinders) * CAC_GET1(dinfo->nheads) * 660 CAC_GET1(dinfo->nsectors) - 1, rcd.addr); 661 _lto4b(CAC_SECTOR_SIZE, rcd.length); 662 cac_copy_internal_data(xs, &rcd, sizeof rcd); 663 break; 664 665 case PREVENT_ALLOW: 666 break; 667 668 case SYNCHRONIZE_CACHE: 669 if (cac_flush(sc)) 670 xs->error = XS_DRIVER_STUFFUP; 671 break; 672 673 case READ_COMMAND: 674 case READ_BIG: 675 case WRITE_COMMAND: 676 case WRITE_BIG: 677 678 flags = 0; 679 /* A read or write operation. */ 680 if (xs->cmdlen == 6) { 681 rw = (struct scsi_rw *)xs->cmd; 682 blockno = _3btol(rw->addr) & 683 (SRW_TOPADDR << 16 | 0xffff); 684 blockcnt = rw->length ? rw->length : 0x100; 685 } else { 686 rwb = (struct scsi_rw_big *)xs->cmd; 687 blockno = _4btol(rwb->addr); 688 blockcnt = _2btol(rwb->length); 689 } 690 size = CAC_GET2(dinfo->ncylinders) * 691 CAC_GET1(dinfo->nheads) * CAC_GET1(dinfo->nsectors); 692 if (blockno >= size || blockno + blockcnt > size) { 693 printf("%s: out of bounds %u-%u >= %u\n", 694 sc->sc_dv.dv_xname, blockno, blockcnt, size); 695 xs->error = XS_DRIVER_STUFFUP; 696 scsi_done(xs); 697 break; 698 } 699 700 switch (xs->cmd->opcode) { 701 case READ_COMMAND: 702 case READ_BIG: 703 op = CAC_CMD_READ; 704 flags = CAC_CCB_DATA_IN; 705 break; 706 case WRITE_COMMAND: 707 case WRITE_BIG: 708 op = CAC_CMD_WRITE; 709 flags = CAC_CCB_DATA_OUT; 710 break; 711 } 712 713 poll = xs->flags & SCSI_POLL; 714 if ((error = cac_cmd(sc, op, xs->data, blockcnt * DEV_BSIZE, 715 target, blockno, flags, xs))) { 716 717 if (error == ENOMEM) { 718 splx(s); 719 return (NO_CCB); 720 } else if (poll) { 721 splx(s); 722 return (TRY_AGAIN_LATER); 723 } else { 724 xs->error = XS_DRIVER_STUFFUP; 725 scsi_done(xs); 726 break; 727 } 728 } 729 730 splx(s); 731 732 if (poll) 733 return (COMPLETE); 734 else 735 return (SUCCESSFULLY_QUEUED); 736 737 default: 738 SC_DEBUG(link, SDEV_DB1, ("unsupported scsi command %#x " 739 "tgt %d ", xs->cmd->opcode, target)); 740 xs->error = XS_DRIVER_STUFFUP; 741 } 742 splx(s); 743 744 return (COMPLETE); 745 } 746 747 /* 748 * Board specific linkage shared between multiple bus types. 749 */ 750 751 int 752 cac_l0_fifo_full(struct cac_softc *sc) 753 { 754 755 return (cac_inl(sc, CAC_REG_CMD_FIFO) == 0); 756 } 757 758 void 759 cac_l0_submit(struct cac_softc *sc, struct cac_ccb *ccb) 760 { 761 #ifdef CAC_DEBUG 762 printf("submit-%x ", ccb->ccb_paddr); 763 #endif 764 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 765 sc->sc_dmamap->dm_mapsize, 766 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 767 cac_outl(sc, CAC_REG_CMD_FIFO, ccb->ccb_paddr); 768 } 769 770 struct cac_ccb * 771 cac_l0_completed(sc) 772 struct cac_softc *sc; 773 { 774 struct cac_ccb *ccb; 775 paddr_t off; 776 777 if (!(off = cac_inl(sc, CAC_REG_DONE_FIFO))) 778 return NULL; 779 #ifdef CAC_DEBUG 780 printf("compl-%x ", off); 781 #endif 782 if (off & 3 && ccb->ccb_req.error == 0) 783 ccb->ccb_req.error = CAC_RET_CMD_INVALID; 784 785 off = (off & ~3) - sc->sc_ccbs_paddr; 786 ccb = (struct cac_ccb *)(sc->sc_ccbs + off); 787 788 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, 789 sc->sc_dmamap->dm_mapsize, 790 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 791 792 return (ccb); 793 } 794 795 int 796 cac_l0_intr_pending(struct cac_softc *sc) 797 { 798 799 return (cac_inl(sc, CAC_REG_INTR_PENDING)); 800 } 801 802 void 803 cac_l0_intr_enable(struct cac_softc *sc, int state) 804 { 805 806 cac_outl(sc, CAC_REG_INTR_MASK, 807 state ? CAC_INTR_ENABLE : CAC_INTR_DISABLE); 808 } 809 810 #if NBIO > 0 811 const int cac_level[] = { 0, 4, 1, 5, 51, 7 }; 812 const int cac_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE, 813 BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED, 814 BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING, 815 BIOC_SVOFFLINE, BIOC_SVBUILDING }; 816 817 int 818 cac_ioctl(struct device *dev, u_long cmd, caddr_t addr) 819 { 820 struct cac_softc *sc = (struct cac_softc *)dev; 821 struct bioc_inq *bi; 822 struct bioc_disk *bd; 823 cac_lock_t lock; 824 int error = 0; 825 826 lock = CAC_LOCK(sc); 827 switch (cmd) { 828 case BIOCINQ: 829 bi = (struct bioc_inq *)addr; 830 strlcpy(bi->bi_dev, sc->sc_dv.dv_xname, sizeof(bi->bi_dev)); 831 bi->bi_novol = sc->sc_nunits; 832 bi->bi_nodisk = 0; 833 break; 834 835 case BIOCVOL: 836 error = cac_ioctl_vol(sc, (struct bioc_vol *)addr); 837 break; 838 839 case BIOCDISK: 840 bd = (struct bioc_disk *)addr; 841 if (bd->bd_volid > sc->sc_nunits) { 842 error = EINVAL; 843 break; 844 } 845 /* No disk information yet */ 846 break; 847 848 case BIOCBLINK: 849 case BIOCALARM: 850 case BIOCSETSTATE: 851 default: 852 error = ENOTTY; 853 } 854 CAC_UNLOCK(sc, lock); 855 856 return (error); 857 } 858 859 int 860 cac_ioctl_vol(struct cac_softc *sc, struct bioc_vol *bv) 861 { 862 struct cac_drive_info dinfo; 863 struct cac_drive_status dstatus; 864 u_int32_t blks; 865 866 if (bv->bv_volid > sc->sc_nunits) 867 return (EINVAL); 868 if (cac_cmd(sc, CAC_CMD_GET_LOG_DRV_INFO, &dinfo, sizeof(dinfo), 869 bv->bv_volid, 0, CAC_CCB_DATA_IN, NULL)) 870 return (EIO); 871 if (cac_cmd(sc, CAC_CMD_SENSE_DRV_STATUS, &dstatus, sizeof(dstatus), 872 bv->bv_volid, 0, CAC_CCB_DATA_IN, NULL)) 873 return (EIO); 874 bv->bv_status = BIOC_SVINVALID; 875 blks = CAC_GET2(dinfo.ncylinders) * CAC_GET1(dinfo.nheads) * 876 CAC_GET1(dinfo.nsectors); 877 bv->bv_size = (off_t)blks * CAC_GET2(dinfo.secsize); 878 bv->bv_level = cac_level[CAC_GET1(dinfo.mirror)]; /*XXX limit check */ 879 bv->bv_nodisk = 0; /* XXX */ 880 bv->bv_status = 0; /* XXX */ 881 bv->bv_percent = -1; 882 bv->bv_seconds = 0; 883 if (dstatus.stat < sizeof(cac_stat)/sizeof(cac_stat[0])) 884 bv->bv_status = cac_stat[dstatus.stat]; 885 if (bv->bv_status == BIOC_SVREBUILD || 886 bv->bv_status == BIOC_SVBUILDING) 887 bv->bv_percent = ((blks - CAC_GET4(dstatus.prog)) * 1000ULL) / 888 blks; 889 890 return (0); 891 } 892 893 #ifndef SMALL_KERNEL 894 int 895 cac_create_sensors(struct cac_softc *sc) 896 { 897 struct device *dev; 898 struct scsibus_softc *ssc; 899 int i; 900 901 TAILQ_FOREACH(dev, &alldevs, dv_list) { 902 if (dev->dv_parent != &sc->sc_dv) 903 continue; 904 905 /* check if this is the scsibus for the logical disks */ 906 ssc = (struct scsibus_softc *)dev; 907 if (ssc->adapter_link == &sc->sc_link) 908 break; 909 } 910 911 if (ssc == NULL) 912 return (1); 913 914 sc->sc_sensors = malloc(sizeof(struct ksensor) * sc->sc_nunits, 915 M_DEVBUF, M_NOWAIT | M_ZERO); 916 if (sc->sc_sensors == NULL) 917 return (1); 918 919 strlcpy(sc->sc_sensordev.xname, sc->sc_dv.dv_xname, 920 sizeof(sc->sc_sensordev.xname)); 921 922 for (i = 0; i < sc->sc_nunits; i++) { 923 if (ssc->sc_link[i][0] == NULL) 924 goto bad; 925 926 dev = ssc->sc_link[i][0]->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); 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