1 /* $OpenBSD: ami.c,v 1.262 2022/04/16 19:19:58 naddy Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Michael Shalayeff 5 * Copyright (c) 2005 Marco Peereboom 6 * Copyright (c) 2006 David Gwynne 7 * All rights reserved. 8 * 9 * The SCSI emulation layer is derived from gdt(4) driver, 10 * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 * THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 /* 34 * American Megatrends Inc. MegaRAID controllers driver 35 * 36 * This driver was made because these ppl and organizations 37 * donated hardware and provided documentation: 38 * 39 * - 428 model card 40 * John Kerbawy, Stephan Matis, Mark Stovall; 41 * 42 * - 467 and 475 model cards, docs 43 * American Megatrends Inc.; 44 * 45 * - uninterruptible electric power for cvs 46 * Theo de Raadt. 47 */ 48 49 #include "bio.h" 50 51 /* #define AMI_DEBUG */ 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/buf.h> 56 #include <sys/ioctl.h> 57 #include <sys/device.h> 58 #include <sys/kernel.h> 59 #include <sys/malloc.h> 60 #include <sys/rwlock.h> 61 #include <sys/pool.h> 62 #include <sys/sensors.h> 63 64 #include <machine/bus.h> 65 66 #include <scsi/scsi_all.h> 67 #include <scsi/scsi_disk.h> 68 #include <scsi/scsiconf.h> 69 70 #include <dev/biovar.h> 71 #include <dev/ic/amireg.h> 72 #include <dev/ic/amivar.h> 73 74 #ifdef AMI_DEBUG 75 #define AMI_DPRINTF(m,a) do { if (ami_debug & (m)) printf a; } while (0) 76 #define AMI_D_CMD 0x0001 77 #define AMI_D_INTR 0x0002 78 #define AMI_D_MISC 0x0004 79 #define AMI_D_DMA 0x0008 80 #define AMI_D_IOCTL 0x0010 81 int ami_debug = 0 82 /* | AMI_D_CMD */ 83 /* | AMI_D_INTR */ 84 /* | AMI_D_MISC */ 85 /* | AMI_D_DMA */ 86 /* | AMI_D_IOCTL */ 87 ; 88 #else 89 #define AMI_DPRINTF(m,a) /* m, a */ 90 #endif 91 92 struct cfdriver ami_cd = { 93 NULL, "ami", DV_DULL 94 }; 95 96 void ami_scsi_cmd(struct scsi_xfer *); 97 int ami_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int); 98 99 const struct scsi_adapter ami_switch = { 100 ami_scsi_cmd, NULL, NULL, NULL, ami_scsi_ioctl 101 }; 102 103 void ami_scsi_raw_cmd(struct scsi_xfer *); 104 105 const struct scsi_adapter ami_raw_switch = { 106 ami_scsi_raw_cmd, NULL, NULL, NULL, NULL 107 }; 108 109 void * ami_get_ccb(void *); 110 void ami_put_ccb(void *, void *); 111 112 u_int32_t ami_read(struct ami_softc *, bus_size_t); 113 void ami_write(struct ami_softc *, bus_size_t, u_int32_t); 114 115 void ami_copyhds(struct ami_softc *, const u_int32_t *, 116 const u_int8_t *, const u_int8_t *); 117 struct ami_mem *ami_allocmem(struct ami_softc *, size_t); 118 void ami_freemem(struct ami_softc *, struct ami_mem *); 119 int ami_alloc_ccbs(struct ami_softc *, int); 120 121 int ami_poll(struct ami_softc *, struct ami_ccb *); 122 void ami_start(struct ami_softc *, struct ami_ccb *); 123 void ami_complete(struct ami_softc *, struct ami_ccb *, int); 124 void ami_runqueue_tick(void *); 125 void ami_runqueue(struct ami_softc *); 126 127 void ami_start_xs(struct ami_softc *sc, struct ami_ccb *, 128 struct scsi_xfer *); 129 void ami_done_xs(struct ami_softc *, struct ami_ccb *); 130 void ami_done_pt(struct ami_softc *, struct ami_ccb *); 131 void ami_done_flush(struct ami_softc *, struct ami_ccb *); 132 void ami_done_sysflush(struct ami_softc *, struct ami_ccb *); 133 134 void ami_done_dummy(struct ami_softc *, struct ami_ccb *); 135 void ami_done_ioctl(struct ami_softc *, struct ami_ccb *); 136 void ami_done_init(struct ami_softc *, struct ami_ccb *); 137 138 int ami_load_ptmem(struct ami_softc*, struct ami_ccb *, 139 void *, size_t, int, int); 140 141 #if NBIO > 0 142 int ami_mgmt(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t, 143 u_int8_t, size_t, void *); 144 int ami_drv_pt(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t *, 145 int, int, void *); 146 int ami_drv_readcap(struct ami_softc *, u_int8_t, u_int8_t, 147 daddr_t *); 148 int ami_drv_inq(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t, 149 void *); 150 int ami_ioctl(struct device *, u_long, caddr_t); 151 int ami_ioctl_inq(struct ami_softc *, struct bioc_inq *); 152 int ami_vol(struct ami_softc *, struct bioc_vol *, 153 struct ami_big_diskarray *); 154 int ami_disk(struct ami_softc *, struct bioc_disk *, 155 struct ami_big_diskarray *); 156 int ami_ioctl_vol(struct ami_softc *, struct bioc_vol *); 157 int ami_ioctl_disk(struct ami_softc *, struct bioc_disk *); 158 int ami_ioctl_alarm(struct ami_softc *, struct bioc_alarm *); 159 int ami_ioctl_setstate(struct ami_softc *, struct bioc_setstate *); 160 161 #ifndef SMALL_KERNEL 162 int ami_create_sensors(struct ami_softc *); 163 void ami_refresh_sensors(void *); 164 #endif 165 #endif /* NBIO > 0 */ 166 167 #define DEVNAME(_s) ((_s)->sc_dev.dv_xname) 168 169 void * 170 ami_get_ccb(void *xsc) 171 { 172 struct ami_softc *sc = xsc; 173 struct ami_ccb *ccb; 174 175 mtx_enter(&sc->sc_ccb_freeq_mtx); 176 ccb = TAILQ_FIRST(&sc->sc_ccb_freeq); 177 if (ccb != NULL) { 178 TAILQ_REMOVE(&sc->sc_ccb_freeq, ccb, ccb_link); 179 ccb->ccb_state = AMI_CCB_READY; 180 } 181 mtx_leave(&sc->sc_ccb_freeq_mtx); 182 183 return (ccb); 184 } 185 186 void 187 ami_put_ccb(void *xsc, void *xccb) 188 { 189 struct ami_softc *sc = xsc; 190 struct ami_ccb *ccb = xccb; 191 192 ccb->ccb_state = AMI_CCB_FREE; 193 ccb->ccb_xs = NULL; 194 ccb->ccb_flags = 0; 195 ccb->ccb_done = NULL; 196 197 mtx_enter(&sc->sc_ccb_freeq_mtx); 198 TAILQ_INSERT_TAIL(&sc->sc_ccb_freeq, ccb, ccb_link); 199 mtx_leave(&sc->sc_ccb_freeq_mtx); 200 } 201 202 u_int32_t 203 ami_read(struct ami_softc *sc, bus_size_t r) 204 { 205 u_int32_t rv; 206 207 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, 208 BUS_SPACE_BARRIER_READ); 209 rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r); 210 211 AMI_DPRINTF(AMI_D_CMD, ("ari 0x%lx 0x08%x ", r, rv)); 212 return (rv); 213 } 214 215 void 216 ami_write(struct ami_softc *sc, bus_size_t r, u_int32_t v) 217 { 218 AMI_DPRINTF(AMI_D_CMD, ("awo 0x%lx 0x%08x ", r, v)); 219 220 bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v); 221 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, 222 BUS_SPACE_BARRIER_WRITE); 223 } 224 225 struct ami_mem * 226 ami_allocmem(struct ami_softc *sc, size_t size) 227 { 228 struct ami_mem *am; 229 int nsegs; 230 231 am = malloc(sizeof(struct ami_mem), M_DEVBUF, M_NOWAIT|M_ZERO); 232 if (am == NULL) 233 return (NULL); 234 235 am->am_size = size; 236 237 if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 238 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &am->am_map) != 0) 239 goto amfree; 240 241 if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &am->am_seg, 1, 242 &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0) 243 goto destroy; 244 245 if (bus_dmamem_map(sc->sc_dmat, &am->am_seg, nsegs, size, &am->am_kva, 246 BUS_DMA_NOWAIT) != 0) 247 goto free; 248 249 if (bus_dmamap_load(sc->sc_dmat, am->am_map, am->am_kva, size, NULL, 250 BUS_DMA_NOWAIT) != 0) 251 goto unmap; 252 253 return (am); 254 255 unmap: 256 bus_dmamem_unmap(sc->sc_dmat, am->am_kva, size); 257 free: 258 bus_dmamem_free(sc->sc_dmat, &am->am_seg, 1); 259 destroy: 260 bus_dmamap_destroy(sc->sc_dmat, am->am_map); 261 amfree: 262 free(am, M_DEVBUF, sizeof *am); 263 264 return (NULL); 265 } 266 267 void 268 ami_freemem(struct ami_softc *sc, struct ami_mem *am) 269 { 270 bus_dmamap_unload(sc->sc_dmat, am->am_map); 271 bus_dmamem_unmap(sc->sc_dmat, am->am_kva, am->am_size); 272 bus_dmamem_free(sc->sc_dmat, &am->am_seg, 1); 273 bus_dmamap_destroy(sc->sc_dmat, am->am_map); 274 free(am, M_DEVBUF, sizeof *am); 275 } 276 277 void 278 ami_copyhds(struct ami_softc *sc, const u_int32_t *sizes, 279 const u_int8_t *props, const u_int8_t *stats) 280 { 281 int i; 282 283 for (i = 0; i < sc->sc_nunits; i++) { 284 sc->sc_hdr[i].hd_present = 1; 285 sc->sc_hdr[i].hd_is_logdrv = 1; 286 sc->sc_hdr[i].hd_size = letoh32(sizes[i]); 287 sc->sc_hdr[i].hd_prop = props[i]; 288 sc->sc_hdr[i].hd_stat = stats[i]; 289 } 290 } 291 292 int 293 ami_alloc_ccbs(struct ami_softc *sc, int nccbs) 294 { 295 struct ami_ccb *ccb; 296 struct ami_ccbmem *ccbmem, *mem; 297 int i, error; 298 299 sc->sc_ccbs = mallocarray(nccbs, sizeof(struct ami_ccb), 300 M_DEVBUF, M_NOWAIT); 301 if (sc->sc_ccbs == NULL) { 302 printf(": unable to allocate ccbs\n"); 303 return (1); 304 } 305 306 sc->sc_ccbmem_am = ami_allocmem(sc, sizeof(struct ami_ccbmem) * nccbs); 307 if (sc->sc_ccbmem_am == NULL) { 308 printf(": unable to allocate ccb dmamem\n"); 309 goto free_ccbs; 310 } 311 ccbmem = AMIMEM_KVA(sc->sc_ccbmem_am); 312 313 TAILQ_INIT(&sc->sc_ccb_freeq); 314 mtx_init(&sc->sc_ccb_freeq_mtx, IPL_BIO); 315 TAILQ_INIT(&sc->sc_ccb_preq); 316 TAILQ_INIT(&sc->sc_ccb_runq); 317 timeout_set(&sc->sc_run_tmo, ami_runqueue_tick, sc); 318 319 scsi_iopool_init(&sc->sc_iopool, sc, ami_get_ccb, ami_put_ccb); 320 321 for (i = 0; i < nccbs; i++) { 322 ccb = &sc->sc_ccbs[i]; 323 mem = &ccbmem[i]; 324 325 error = bus_dmamap_create(sc->sc_dmat, AMI_MAXFER, 326 AMI_MAXOFFSETS, AMI_MAXFER, 0, 327 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap); 328 if (error) { 329 printf(": cannot create ccb dmamap (%d)\n", error); 330 goto free_list; 331 } 332 333 ccb->ccb_sc = sc; 334 335 ccb->ccb_cmd.acc_id = i + 1; 336 ccb->ccb_offset = sizeof(struct ami_ccbmem) * i; 337 338 ccb->ccb_pt = &mem->cd_pt; 339 ccb->ccb_ptpa = htole32(AMIMEM_DVA(sc->sc_ccbmem_am) + 340 ccb->ccb_offset); 341 342 ccb->ccb_sglist = mem->cd_sg; 343 ccb->ccb_sglistpa = htole32(AMIMEM_DVA(sc->sc_ccbmem_am) + 344 ccb->ccb_offset + sizeof(struct ami_passthrough)); 345 346 /* override last command for management */ 347 if (i == nccbs - 1) { 348 ccb->ccb_cmd.acc_id = 0xfe; 349 sc->sc_mgmtccb = ccb; 350 } else { 351 ami_put_ccb(sc, ccb); 352 } 353 } 354 355 return (0); 356 357 free_list: 358 while ((ccb = ami_get_ccb(sc)) != NULL) 359 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap); 360 361 ami_freemem(sc, sc->sc_ccbmem_am); 362 free_ccbs: 363 free(sc->sc_ccbs, M_DEVBUF, 0); 364 365 return (1); 366 } 367 368 int 369 ami_attach(struct ami_softc *sc) 370 { 371 struct scsibus_attach_args saa; 372 struct ami_rawsoftc *rsc; 373 struct ami_ccb iccb; 374 struct ami_iocmd *cmd; 375 struct ami_mem *am; 376 struct ami_inquiry *inq; 377 struct ami_fc_einquiry *einq; 378 struct ami_fc_prodinfo *pi; 379 const char *p; 380 paddr_t pa; 381 382 mtx_init(&sc->sc_cmd_mtx, IPL_BIO); 383 384 am = ami_allocmem(sc, NBPG); 385 if (am == NULL) { 386 printf(": unable to allocate init data\n"); 387 return (1); 388 } 389 pa = htole32(AMIMEM_DVA(am)); 390 391 sc->sc_mbox_am = ami_allocmem(sc, sizeof(struct ami_iocmd)); 392 if (sc->sc_mbox_am == NULL) { 393 printf(": unable to allocate mbox\n"); 394 goto free_idata; 395 } 396 sc->sc_mbox = (volatile struct ami_iocmd *)AMIMEM_KVA(sc->sc_mbox_am); 397 sc->sc_mbox_pa = htole32(AMIMEM_DVA(sc->sc_mbox_am)); 398 AMI_DPRINTF(AMI_D_CMD, ("mbox=%p ", sc->sc_mbox)); 399 AMI_DPRINTF(AMI_D_CMD, ("mbox_pa=0x%llx ", (long long)sc->sc_mbox_pa)); 400 401 /* create a spartan ccb for use with ami_poll */ 402 bzero(&iccb, sizeof(iccb)); 403 iccb.ccb_sc = sc; 404 iccb.ccb_done = ami_done_init; 405 cmd = &iccb.ccb_cmd; 406 407 (sc->sc_init)(sc); 408 409 /* try FC inquiry first */ 410 cmd->acc_cmd = AMI_FCOP; 411 cmd->acc_io.aio_channel = AMI_FC_EINQ3; 412 cmd->acc_io.aio_param = AMI_FC_EINQ3_SOLICITED_FULL; 413 cmd->acc_io.aio_data = pa; 414 if (ami_poll(sc, &iccb) == 0) { 415 einq = AMIMEM_KVA(am); 416 pi = AMIMEM_KVA(am); 417 418 sc->sc_nunits = einq->ain_nlogdrv; 419 sc->sc_drvinscnt = einq->ain_drvinscnt + 1; /* force scan */ 420 ami_copyhds(sc, einq->ain_ldsize, einq->ain_ldprop, 421 einq->ain_ldstat); 422 423 cmd->acc_cmd = AMI_FCOP; 424 cmd->acc_io.aio_channel = AMI_FC_PRODINF; 425 cmd->acc_io.aio_param = 0; 426 cmd->acc_io.aio_data = pa; 427 if (ami_poll(sc, &iccb) == 0) { 428 sc->sc_maxunits = AMI_BIG_MAX_LDRIVES; 429 430 bcopy (pi->api_fwver, sc->sc_fwver, 16); 431 sc->sc_fwver[15] = '\0'; 432 bcopy (pi->api_biosver, sc->sc_biosver, 16); 433 sc->sc_biosver[15] = '\0'; 434 sc->sc_channels = pi->api_channels; 435 sc->sc_targets = pi->api_fcloops; 436 sc->sc_memory = letoh16(pi->api_ramsize); 437 sc->sc_maxcmds = pi->api_maxcmd; 438 p = "FC loop"; 439 } 440 } 441 442 if (sc->sc_maxunits == 0) { 443 inq = AMIMEM_KVA(am); 444 445 cmd->acc_cmd = AMI_EINQUIRY; 446 cmd->acc_io.aio_channel = 0; 447 cmd->acc_io.aio_param = 0; 448 cmd->acc_io.aio_data = pa; 449 if (ami_poll(sc, &iccb) != 0) { 450 cmd->acc_cmd = AMI_INQUIRY; 451 cmd->acc_io.aio_channel = 0; 452 cmd->acc_io.aio_param = 0; 453 cmd->acc_io.aio_data = pa; 454 if (ami_poll(sc, &iccb) != 0) { 455 printf(": cannot do inquiry\n"); 456 goto free_mbox; 457 } 458 } 459 460 sc->sc_maxunits = AMI_MAX_LDRIVES; 461 sc->sc_nunits = inq->ain_nlogdrv; 462 ami_copyhds(sc, inq->ain_ldsize, inq->ain_ldprop, 463 inq->ain_ldstat); 464 465 bcopy (inq->ain_fwver, sc->sc_fwver, 4); 466 sc->sc_fwver[4] = '\0'; 467 bcopy (inq->ain_biosver, sc->sc_biosver, 4); 468 sc->sc_biosver[4] = '\0'; 469 sc->sc_channels = inq->ain_channels; 470 sc->sc_targets = inq->ain_targets; 471 sc->sc_memory = inq->ain_ramsize; 472 sc->sc_maxcmds = inq->ain_maxcmd; 473 sc->sc_drvinscnt = inq->ain_drvinscnt + 1; /* force scan */ 474 p = "target"; 475 } 476 477 if (sc->sc_flags & AMI_BROKEN) { 478 sc->sc_maxcmds = 1; 479 sc->sc_maxunits = 1; 480 } else { 481 sc->sc_maxunits = AMI_BIG_MAX_LDRIVES; 482 if (sc->sc_maxcmds > AMI_MAXCMDS) 483 sc->sc_maxcmds = AMI_MAXCMDS; 484 /* 485 * Reserve ccb's for ioctl's and raw commands to 486 * processors/enclosures by lowering the number of 487 * openings available for logical units. 488 */ 489 sc->sc_maxcmds -= AMI_MAXIOCTLCMDS + AMI_MAXPROCS * 490 AMI_MAXRAWCMDS * sc->sc_channels; 491 } 492 493 if (ami_alloc_ccbs(sc, AMI_MAXCMDS + 1) != 0) { 494 /* error already printed */ 495 goto free_mbox; 496 } 497 498 ami_freemem(sc, am); 499 500 /* hack for hp netraid version encoding */ 501 if ('A' <= sc->sc_fwver[2] && sc->sc_fwver[2] <= 'Z' && 502 sc->sc_fwver[1] < ' ' && sc->sc_fwver[0] < ' ' && 503 'A' <= sc->sc_biosver[2] && sc->sc_biosver[2] <= 'Z' && 504 sc->sc_biosver[1] < ' ' && sc->sc_biosver[0] < ' ') { 505 506 snprintf(sc->sc_fwver, sizeof sc->sc_fwver, "%c.%02d.%02d", 507 sc->sc_fwver[2], sc->sc_fwver[1], sc->sc_fwver[0]); 508 snprintf(sc->sc_biosver, sizeof sc->sc_biosver, "%c.%02d.%02d", 509 sc->sc_biosver[2], sc->sc_biosver[1], sc->sc_biosver[0]); 510 } 511 512 /* TODO: fetch & print cache strategy */ 513 /* TODO: fetch & print scsi and raid info */ 514 515 #ifdef AMI_DEBUG 516 printf(", FW %s, BIOS v%s, %dMB RAM\n" 517 "%s: %d channels, %d %ss, %d logical drives, " 518 "max commands %d, quirks: %04x\n", 519 sc->sc_fwver, sc->sc_biosver, sc->sc_memory, DEVNAME(sc), 520 sc->sc_channels, sc->sc_targets, p, sc->sc_nunits, 521 sc->sc_maxcmds, sc->sc_flags); 522 #else 523 printf(", FW %s, BIOS v%s, %dMB RAM\n" 524 "%s: %d channels, %d %ss, %d logical drives\n", 525 sc->sc_fwver, sc->sc_biosver, sc->sc_memory, DEVNAME(sc), 526 sc->sc_channels, sc->sc_targets, p, sc->sc_nunits); 527 #endif /* AMI_DEBUG */ 528 529 if (sc->sc_flags & AMI_BROKEN && sc->sc_nunits > 1) 530 printf("%s: firmware buggy, limiting access to first logical " 531 "disk\n", DEVNAME(sc)); 532 533 /* lock around ioctl requests */ 534 rw_init(&sc->sc_lock, NULL); 535 536 saa.saa_adapter_softc = sc; 537 saa.saa_adapter = &ami_switch; 538 saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET; 539 saa.saa_adapter_buswidth = sc->sc_maxunits; 540 saa.saa_luns = 8; 541 saa.saa_openings = sc->sc_maxcmds; 542 saa.saa_pool = &sc->sc_iopool; 543 saa.saa_quirks = saa.saa_flags = 0; 544 saa.saa_wwpn = saa.saa_wwnn = 0; 545 546 sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev, &saa, 547 scsiprint); 548 549 /* can't do bioctls, sensors, or pass-through on broken devices */ 550 if (sc->sc_flags & AMI_BROKEN) 551 return (0); 552 553 #if NBIO > 0 554 if (bio_register(&sc->sc_dev, ami_ioctl) != 0) 555 printf("%s: controller registration failed\n", DEVNAME(sc)); 556 else 557 sc->sc_ioctl = ami_ioctl; 558 559 #ifndef SMALL_KERNEL 560 if (ami_create_sensors(sc) != 0) 561 printf("%s: unable to create sensors\n", DEVNAME(sc)); 562 #endif 563 #endif 564 565 rsc = mallocarray(sc->sc_channels, sizeof(struct ami_rawsoftc), 566 M_DEVBUF, M_NOWAIT|M_ZERO); 567 if (!rsc) { 568 printf("%s: no memory for raw interface\n", DEVNAME(sc)); 569 return (0); 570 } 571 572 for (sc->sc_rawsoftcs = rsc; 573 rsc < &sc->sc_rawsoftcs[sc->sc_channels]; rsc++) { 574 575 struct scsibus_softc *ptbus; 576 struct scsi_link *proclink; 577 struct device *procdev; 578 579 rsc->sc_softc = sc; 580 rsc->sc_channel = rsc - sc->sc_rawsoftcs; 581 rsc->sc_proctarget = -1; 582 583 /* TODO fetch adapter_target from the controller */ 584 585 saa.saa_adapter_softc = rsc; 586 saa.saa_adapter = &ami_raw_switch; 587 saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET; 588 saa.saa_adapter_buswidth = 16; 589 saa.saa_luns = 8; 590 saa.saa_openings = sc->sc_maxcmds; 591 saa.saa_pool = &sc->sc_iopool; 592 saa.saa_quirks = saa.saa_flags = 0; 593 saa.saa_wwpn = saa.saa_wwnn = 0; 594 595 ptbus = (struct scsibus_softc *)config_found(&sc->sc_dev, 596 &saa, scsiprint); 597 598 if (ptbus == NULL || rsc->sc_proctarget == -1) 599 continue; 600 601 proclink = scsi_get_link(ptbus, rsc->sc_proctarget, 0); 602 if (proclink == NULL) 603 continue; 604 605 procdev = proclink->device_softc; 606 strlcpy(rsc->sc_procdev, procdev->dv_xname, 607 sizeof(rsc->sc_procdev)); 608 } 609 610 return (0); 611 612 free_mbox: 613 ami_freemem(sc, sc->sc_mbox_am); 614 free_idata: 615 ami_freemem(sc, am); 616 617 return (1); 618 } 619 620 int 621 ami_quartz_init(struct ami_softc *sc) 622 { 623 ami_write(sc, AMI_QIDB, 0); 624 625 return (0); 626 } 627 628 int 629 ami_quartz_exec(struct ami_softc *sc, struct ami_iocmd *cmd) 630 { 631 if (sc->sc_mbox->acc_busy) { 632 AMI_DPRINTF(AMI_D_CMD, ("mbox_busy ")); 633 return (EBUSY); 634 } 635 636 memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16); 637 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 638 sizeof(struct ami_iocmd), BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); 639 640 sc->sc_mbox->acc_busy = 1; 641 sc->sc_mbox->acc_poll = 0; 642 sc->sc_mbox->acc_ack = 0; 643 644 ami_write(sc, AMI_QIDB, sc->sc_mbox_pa | htole32(AMI_QIDB_EXEC)); 645 646 return (0); 647 } 648 649 int 650 ami_quartz_done(struct ami_softc *sc, struct ami_iocmd *mbox) 651 { 652 u_int32_t i, n; 653 u_int8_t nstat, status; 654 u_int8_t completed[AMI_MAXSTATACK]; 655 656 if (ami_read(sc, AMI_QODB) != AMI_QODB_READY) 657 return (0); /* nothing to do */ 658 659 ami_write(sc, AMI_QODB, AMI_QODB_READY); 660 661 /* 662 * The following sequence is not supposed to have a timeout clause 663 * since the firmware has a "guarantee" that all commands will 664 * complete. The choice is either panic or hoping for a miracle 665 * and that the IOs will complete much later. 666 */ 667 i = 0; 668 while ((nstat = sc->sc_mbox->acc_nstat) == 0xff) { 669 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 670 sizeof(struct ami_iocmd), BUS_DMASYNC_POSTREAD); 671 delay(1); 672 if (i++ > 1000000) 673 return (0); /* nothing to do */ 674 } 675 sc->sc_mbox->acc_nstat = 0xff; 676 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 677 sizeof(struct ami_iocmd), BUS_DMASYNC_POSTWRITE); 678 679 /* wait until fw wrote out all completions */ 680 i = 0; 681 AMI_DPRINTF(AMI_D_CMD, ("aqd %d ", nstat)); 682 for (n = 0; n < nstat; n++) { 683 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 684 sizeof(struct ami_iocmd), BUS_DMASYNC_PREREAD); 685 while ((completed[n] = sc->sc_mbox->acc_cmplidl[n]) == 0xff) { 686 delay(1); 687 if (i++ > 1000000) 688 return (0); /* nothing to do */ 689 } 690 sc->sc_mbox->acc_cmplidl[n] = 0xff; 691 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 692 sizeof(struct ami_iocmd), BUS_DMASYNC_POSTWRITE); 693 } 694 695 /* this should never happen, someone screwed up the completion status */ 696 if ((status = sc->sc_mbox->acc_status) == 0xff) 697 panic("%s: status 0xff from the firmware", DEVNAME(sc)); 698 699 sc->sc_mbox->acc_status = 0xff; 700 701 /* copy mailbox to temporary one and fixup other changed values */ 702 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 16, 703 BUS_DMASYNC_POSTWRITE); 704 memcpy(mbox, (struct ami_iocmd *)sc->sc_mbox, 16); 705 mbox->acc_nstat = nstat; 706 mbox->acc_status = status; 707 for (n = 0; n < nstat; n++) 708 mbox->acc_cmplidl[n] = completed[n]; 709 710 /* ack interrupt */ 711 ami_write(sc, AMI_QIDB, AMI_QIDB_ACK); 712 713 return (1); /* ready to complete all IOs in acc_cmplidl */ 714 } 715 716 int 717 ami_quartz_poll(struct ami_softc *sc, struct ami_iocmd *cmd) 718 { 719 /* struct scsi_xfer *xs = ccb->ccb_xs; */ 720 u_int32_t i; 721 u_int8_t status; 722 723 splassert(IPL_BIO); 724 725 if (sc->sc_dis_poll) 726 return (-1); /* fail */ 727 728 i = 0; 729 while (sc->sc_mbox->acc_busy && (i < AMI_MAX_BUSYWAIT)) { 730 delay(1); 731 i++; 732 } 733 if (sc->sc_mbox->acc_busy) { 734 AMI_DPRINTF(AMI_D_CMD, ("mbox_busy ")); 735 return (-1); 736 } 737 738 memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16); 739 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 16, 740 BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); 741 742 sc->sc_mbox->acc_id = 0xfe; 743 sc->sc_mbox->acc_busy = 1; 744 sc->sc_mbox->acc_poll = 0; 745 sc->sc_mbox->acc_ack = 0; 746 sc->sc_mbox->acc_nstat = 0xff; 747 sc->sc_mbox->acc_status = 0xff; 748 749 /* send command to firmware */ 750 ami_write(sc, AMI_QIDB, sc->sc_mbox_pa | htole32(AMI_QIDB_EXEC)); 751 752 i = 0; 753 while ((sc->sc_mbox->acc_nstat == 0xff) && (i < AMI_MAX_POLLWAIT)) { 754 delay(1); 755 i++; 756 } 757 if (i >= AMI_MAX_POLLWAIT) { 758 printf("%s: command not accepted, polling disabled\n", 759 DEVNAME(sc)); 760 sc->sc_dis_poll = 1; 761 return (-1); 762 } 763 764 /* poll firmware */ 765 i = 0; 766 while ((sc->sc_mbox->acc_poll != 0x77) && (i < AMI_MAX_POLLWAIT)) { 767 delay(1); 768 i++; 769 } 770 if (i >= AMI_MAX_POLLWAIT) { 771 printf("%s: firmware didn't reply, polling disabled\n", 772 DEVNAME(sc)); 773 sc->sc_dis_poll = 1; 774 return (-1); 775 } 776 777 /* ack */ 778 ami_write(sc, AMI_QIDB, sc->sc_mbox_pa | htole32(AMI_QIDB_ACK)); 779 780 i = 0; 781 while((ami_read(sc, AMI_QIDB) & AMI_QIDB_ACK) && 782 (i < AMI_MAX_POLLWAIT)) { 783 delay(1); 784 i++; 785 } 786 if (i >= AMI_MAX_POLLWAIT) { 787 printf("%s: firmware didn't ack the ack, polling disabled\n", 788 DEVNAME(sc)); 789 sc->sc_dis_poll = 1; 790 return (-1); 791 } 792 793 sc->sc_mbox->acc_poll = 0; 794 sc->sc_mbox->acc_ack = 0x77; 795 status = sc->sc_mbox->acc_status; 796 sc->sc_mbox->acc_nstat = 0xff; 797 sc->sc_mbox->acc_status = 0xff; 798 799 for (i = 0; i < AMI_MAXSTATACK; i++) 800 sc->sc_mbox->acc_cmplidl[i] = 0xff; 801 802 return (status); 803 } 804 805 int 806 ami_schwartz_init(struct ami_softc *sc) 807 { 808 u_int32_t a = (u_int32_t)sc->sc_mbox_pa; 809 810 bus_space_write_4(sc->sc_iot, sc->sc_ioh, AMI_SMBADDR, a); 811 /* XXX 40bit address ??? */ 812 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SMBENA, 0); 813 814 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_ACK); 815 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SIEM, AMI_SEIM_ENA | 816 bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SIEM)); 817 818 return (0); 819 } 820 821 int 822 ami_schwartz_exec(struct ami_softc *sc, struct ami_iocmd *cmd) 823 { 824 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT) & 825 AMI_SMBST_BUSY) { 826 AMI_DPRINTF(AMI_D_CMD, ("mbox_busy ")); 827 return (EBUSY); 828 } 829 830 memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16); 831 sc->sc_mbox->acc_busy = 1; 832 sc->sc_mbox->acc_poll = 0; 833 sc->sc_mbox->acc_ack = 0; 834 835 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_EXEC); 836 return (0); 837 } 838 839 int 840 ami_schwartz_done(struct ami_softc *sc, struct ami_iocmd *mbox) 841 { 842 u_int8_t stat; 843 844 #if 0 845 /* do not scramble the busy mailbox */ 846 if (sc->sc_mbox->acc_busy) 847 return (0); 848 #endif 849 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT) & 850 AMI_SMBST_BUSY) 851 return (0); 852 853 stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT); 854 if (stat & AMI_ISTAT_PEND) { 855 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT, stat); 856 857 *mbox = *sc->sc_mbox; 858 AMI_DPRINTF(AMI_D_CMD, ("asd %d ", mbox->acc_nstat)); 859 860 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, 861 AMI_SCMD_ACK); 862 863 return (1); 864 } 865 866 return (0); 867 } 868 869 int 870 ami_schwartz_poll(struct ami_softc *sc, struct ami_iocmd *mbox) 871 { 872 u_int8_t status; 873 u_int32_t i; 874 int rv; 875 876 splassert(IPL_BIO); 877 878 if (sc->sc_dis_poll) 879 return (-1); /* fail */ 880 881 for (i = 0; i < AMI_MAX_POLLWAIT; i++) { 882 if (!(bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT) & 883 AMI_SMBST_BUSY)) 884 break; 885 delay(1); 886 } 887 if (i >= AMI_MAX_POLLWAIT) { 888 AMI_DPRINTF(AMI_D_CMD, ("mbox_busy ")); 889 return (-1); 890 } 891 892 memcpy((struct ami_iocmd *)sc->sc_mbox, mbox, 16); 893 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 16, 894 BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); 895 896 sc->sc_mbox->acc_busy = 1; 897 sc->sc_mbox->acc_poll = 0; 898 sc->sc_mbox->acc_ack = 0; 899 /* send command to firmware */ 900 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_EXEC); 901 902 /* wait until no longer busy */ 903 for (i = 0; i < AMI_MAX_POLLWAIT; i++) { 904 if (!(bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT) & 905 AMI_SMBST_BUSY)) 906 break; 907 delay(1); 908 } 909 if (i >= AMI_MAX_POLLWAIT) { 910 printf("%s: command not accepted, polling disabled\n", 911 DEVNAME(sc)); 912 sc->sc_dis_poll = 1; 913 return (-1); 914 } 915 916 /* wait for interrupt bit */ 917 for (i = 0; i < AMI_MAX_POLLWAIT; i++) { 918 status = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT); 919 if (status & AMI_ISTAT_PEND) 920 break; 921 delay(1); 922 } 923 if (i >= AMI_MAX_POLLWAIT) { 924 printf("%s: interrupt didn't arrive, polling disabled\n", 925 DEVNAME(sc)); 926 sc->sc_dis_poll = 1; 927 return (-1); 928 } 929 930 /* write ststus back to firmware */ 931 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT, status); 932 933 /* copy mailbox and status back */ 934 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 935 sizeof(struct ami_iocmd), BUS_DMASYNC_PREREAD); 936 *mbox = *sc->sc_mbox; 937 rv = sc->sc_mbox->acc_status; 938 939 /* ack interrupt */ 940 bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_ACK); 941 942 return (rv); 943 } 944 945 void 946 ami_start_xs(struct ami_softc *sc, struct ami_ccb *ccb, struct scsi_xfer *xs) 947 { 948 if (xs->flags & SCSI_POLL) 949 ami_complete(sc, ccb, xs->timeout); 950 else 951 ami_start(sc, ccb); 952 } 953 954 void 955 ami_start(struct ami_softc *sc, struct ami_ccb *ccb) 956 { 957 mtx_enter(&sc->sc_cmd_mtx); 958 ccb->ccb_state = AMI_CCB_PREQUEUED; 959 TAILQ_INSERT_TAIL(&sc->sc_ccb_preq, ccb, ccb_link); 960 mtx_leave(&sc->sc_cmd_mtx); 961 962 ami_runqueue(sc); 963 } 964 965 void 966 ami_runqueue_tick(void *arg) 967 { 968 ami_runqueue(arg); 969 } 970 971 void 972 ami_runqueue(struct ami_softc *sc) 973 { 974 struct ami_ccb *ccb; 975 int add = 0; 976 977 mtx_enter(&sc->sc_cmd_mtx); 978 if (!sc->sc_drainio) { 979 while ((ccb = TAILQ_FIRST(&sc->sc_ccb_preq)) != NULL) { 980 if (sc->sc_exec(sc, &ccb->ccb_cmd) != 0) { 981 add = 1; 982 break; 983 } 984 985 TAILQ_REMOVE(&sc->sc_ccb_preq, ccb, ccb_link); 986 ccb->ccb_state = AMI_CCB_QUEUED; 987 TAILQ_INSERT_TAIL(&sc->sc_ccb_runq, ccb, ccb_link); 988 } 989 } 990 mtx_leave(&sc->sc_cmd_mtx); 991 992 if (add) 993 timeout_add(&sc->sc_run_tmo, 1); 994 } 995 996 int 997 ami_poll(struct ami_softc *sc, struct ami_ccb *ccb) 998 { 999 int error; 1000 1001 mtx_enter(&sc->sc_cmd_mtx); 1002 error = sc->sc_poll(sc, &ccb->ccb_cmd); 1003 if (error == -1) 1004 ccb->ccb_flags |= AMI_CCB_F_ERR; 1005 mtx_leave(&sc->sc_cmd_mtx); 1006 1007 ccb->ccb_done(sc, ccb); 1008 1009 return (error); 1010 } 1011 1012 void 1013 ami_complete(struct ami_softc *sc, struct ami_ccb *ccb, int timeout) 1014 { 1015 void (*done)(struct ami_softc *, struct ami_ccb *); 1016 int ready; 1017 int i = 0; 1018 int s; 1019 1020 done = ccb->ccb_done; 1021 ccb->ccb_done = ami_done_dummy; 1022 1023 /* 1024 * since exec will return if the mbox is busy we have to busy wait 1025 * ourselves. once its in, jam it into the runq. 1026 */ 1027 mtx_enter(&sc->sc_cmd_mtx); 1028 while (i < AMI_MAX_BUSYWAIT) { 1029 if (sc->sc_exec(sc, &ccb->ccb_cmd) == 0) { 1030 ccb->ccb_state = AMI_CCB_QUEUED; 1031 TAILQ_INSERT_TAIL(&sc->sc_ccb_runq, ccb, ccb_link); 1032 break; 1033 } 1034 DELAY(1000); 1035 i++; 1036 } 1037 ready = (ccb->ccb_state == AMI_CCB_QUEUED); 1038 mtx_leave(&sc->sc_cmd_mtx); 1039 1040 if (!ready) { 1041 ccb->ccb_flags |= AMI_CCB_F_ERR; 1042 ccb->ccb_state = AMI_CCB_READY; 1043 goto done; 1044 } 1045 1046 /* 1047 * Override timeout for PERC3. The first command triggers a chip 1048 * reset on the QL12160 chip which causes the firmware to reload. 1049 * 30000 is slightly less than double of how long it takes for the 1050 * firmware to be up again. After the first two commands the 1051 * timeouts are as expected. 1052 */ 1053 timeout = MAX(30000, timeout); /* timeout */ 1054 1055 while (ccb->ccb_state == AMI_CCB_QUEUED) { 1056 s = splbio(); /* interrupt handlers are called at their IPL */ 1057 ready = ami_intr(sc); 1058 splx(s); 1059 1060 if (ready == 0) { 1061 if (timeout-- == 0) { 1062 /* XXX */ 1063 printf("%s: timeout\n", DEVNAME(sc)); 1064 return; 1065 } 1066 1067 delay(1000); 1068 continue; 1069 } 1070 } 1071 1072 done: 1073 done(sc, ccb); 1074 } 1075 1076 void 1077 ami_done_pt(struct ami_softc *sc, struct ami_ccb *ccb) 1078 { 1079 struct scsi_xfer *xs = ccb->ccb_xs; 1080 struct scsi_link *link = xs->sc_link; 1081 struct ami_rawsoftc *rsc = link->bus->sb_adapter_softc; 1082 u_int8_t target = link->target, type; 1083 1084 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am), 1085 ccb->ccb_offset, sizeof(struct ami_ccbmem), 1086 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1087 1088 if (xs->data != NULL) { 1089 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0, 1090 ccb->ccb_dmamap->dm_mapsize, 1091 (xs->flags & SCSI_DATA_IN) ? 1092 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 1093 1094 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap); 1095 } 1096 1097 xs->resid = 0; 1098 1099 if (ccb->ccb_flags & AMI_CCB_F_ERR) 1100 xs->error = XS_DRIVER_STUFFUP; 1101 else if (ccb->ccb_status != 0x00) 1102 xs->error = XS_DRIVER_STUFFUP; 1103 else if (xs->flags & SCSI_POLL && xs->cmd.opcode == INQUIRY) { 1104 type = ((struct scsi_inquiry_data *)xs->data)->device & 1105 SID_TYPE; 1106 if (!(type == T_PROCESSOR || type == T_ENCLOSURE)) 1107 xs->error = XS_DRIVER_STUFFUP; 1108 else 1109 rsc->sc_proctarget = target; 1110 } 1111 1112 scsi_done(xs); 1113 } 1114 1115 void 1116 ami_done_xs(struct ami_softc *sc, struct ami_ccb *ccb) 1117 { 1118 struct scsi_xfer *xs = ccb->ccb_xs; 1119 1120 if (xs->data != NULL) { 1121 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0, 1122 ccb->ccb_dmamap->dm_mapsize, 1123 (xs->flags & SCSI_DATA_IN) ? 1124 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 1125 1126 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am), 1127 ccb->ccb_offset, sizeof(struct ami_ccbmem), 1128 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1129 1130 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap); 1131 } 1132 1133 xs->resid = 0; 1134 1135 if (ccb->ccb_flags & AMI_CCB_F_ERR) 1136 xs->error = XS_DRIVER_STUFFUP; 1137 1138 scsi_done(xs); 1139 } 1140 1141 void 1142 ami_done_flush(struct ami_softc *sc, struct ami_ccb *ccb) 1143 { 1144 struct scsi_xfer *xs = ccb->ccb_xs; 1145 struct ami_iocmd *cmd = &ccb->ccb_cmd; 1146 1147 if (ccb->ccb_flags & AMI_CCB_F_ERR) { 1148 xs->error = XS_DRIVER_STUFFUP; 1149 xs->resid = 0; 1150 1151 scsi_done(xs); 1152 return; 1153 } 1154 1155 /* reuse the ccb for the sysflush command */ 1156 ccb->ccb_done = ami_done_sysflush; 1157 cmd->acc_cmd = AMI_SYSFLUSH; 1158 1159 ami_start_xs(sc, ccb, xs); 1160 } 1161 1162 void 1163 ami_done_sysflush(struct ami_softc *sc, struct ami_ccb *ccb) 1164 { 1165 struct scsi_xfer *xs = ccb->ccb_xs; 1166 1167 xs->resid = 0; 1168 if (ccb->ccb_flags & AMI_CCB_F_ERR) 1169 xs->error = XS_DRIVER_STUFFUP; 1170 1171 scsi_done(xs); 1172 } 1173 1174 void 1175 ami_done_dummy(struct ami_softc *sc, struct ami_ccb *ccb) 1176 { 1177 } 1178 1179 void 1180 ami_done_ioctl(struct ami_softc *sc, struct ami_ccb *ccb) 1181 { 1182 wakeup(ccb); 1183 } 1184 1185 void 1186 ami_done_init(struct ami_softc *sc, struct ami_ccb *ccb) 1187 { 1188 /* the ccb is going to be reused, so do nothing with it */ 1189 } 1190 1191 void 1192 ami_scsi_raw_cmd(struct scsi_xfer *xs) 1193 { 1194 struct scsi_link *link = xs->sc_link; 1195 struct ami_rawsoftc *rsc = link->bus->sb_adapter_softc; 1196 struct ami_softc *sc = rsc->sc_softc; 1197 u_int8_t channel = rsc->sc_channel, target = link->target; 1198 struct ami_ccb *ccb; 1199 1200 AMI_DPRINTF(AMI_D_CMD, ("ami_scsi_raw_cmd ")); 1201 1202 if (xs->cmdlen > AMI_MAX_CDB) { 1203 AMI_DPRINTF(AMI_D_CMD, ("CDB too big %p ", xs)); 1204 bzero(&xs->sense, sizeof(xs->sense)); 1205 xs->sense.error_code = SSD_ERRCODE_VALID | SSD_ERRCODE_CURRENT; 1206 xs->sense.flags = SKEY_ILLEGAL_REQUEST; 1207 xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */ 1208 xs->error = XS_SENSE; 1209 scsi_done(xs); 1210 return; 1211 } 1212 1213 xs->error = XS_NOERROR; 1214 1215 ccb = xs->io; 1216 1217 memset(ccb->ccb_pt, 0, sizeof(struct ami_passthrough)); 1218 1219 ccb->ccb_xs = xs; 1220 ccb->ccb_done = ami_done_pt; 1221 1222 ccb->ccb_cmd.acc_cmd = AMI_PASSTHRU; 1223 ccb->ccb_cmd.acc_passthru.apt_data = ccb->ccb_ptpa; 1224 1225 ccb->ccb_pt->apt_param = AMI_PTPARAM(AMI_TIMEOUT_6,1,0); 1226 ccb->ccb_pt->apt_channel = channel; 1227 ccb->ccb_pt->apt_target = target; 1228 bcopy(&xs->cmd, ccb->ccb_pt->apt_cdb, AMI_MAX_CDB); 1229 ccb->ccb_pt->apt_ncdb = xs->cmdlen; 1230 ccb->ccb_pt->apt_nsense = AMI_MAX_SENSE; 1231 ccb->ccb_pt->apt_datalen = xs->datalen; 1232 ccb->ccb_pt->apt_data = 0; 1233 1234 if (ami_load_ptmem(sc, ccb, xs->data, xs->datalen, 1235 xs->flags & SCSI_DATA_IN, xs->flags & SCSI_NOSLEEP) != 0) { 1236 xs->error = XS_DRIVER_STUFFUP; 1237 scsi_done(xs); 1238 return; 1239 } 1240 1241 ami_start_xs(sc, ccb, xs); 1242 } 1243 1244 int 1245 ami_load_ptmem(struct ami_softc *sc, struct ami_ccb *ccb, void *data, 1246 size_t len, int read, int nowait) 1247 { 1248 bus_dmamap_t dmap = ccb->ccb_dmamap; 1249 bus_dma_segment_t *sgd; 1250 int error, i; 1251 1252 if (data != NULL) { 1253 error = bus_dmamap_load(sc->sc_dmat, dmap, data, len, NULL, 1254 nowait ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 1255 if (error) { 1256 if (error == EFBIG) 1257 printf("more than %d dma segs\n", 1258 AMI_MAXOFFSETS); 1259 else 1260 printf("error %d loading dma map\n", error); 1261 1262 return (1); 1263 } 1264 1265 sgd = dmap->dm_segs; 1266 if (dmap->dm_nsegs > 1) { 1267 struct ami_sgent *sgl = ccb->ccb_sglist; 1268 1269 ccb->ccb_pt->apt_nsge = dmap->dm_nsegs; 1270 ccb->ccb_pt->apt_data = ccb->ccb_sglistpa; 1271 1272 for (i = 0; i < dmap->dm_nsegs; i++) { 1273 sgl[i].asg_addr = htole32(sgd[i].ds_addr); 1274 sgl[i].asg_len = htole32(sgd[i].ds_len); 1275 } 1276 } else { 1277 ccb->ccb_pt->apt_nsge = 0; 1278 ccb->ccb_pt->apt_data = htole32(sgd->ds_addr); 1279 } 1280 1281 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 1282 read ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 1283 } 1284 1285 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am), 1286 ccb->ccb_offset, sizeof(struct ami_ccbmem), 1287 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1288 1289 return (0); 1290 } 1291 1292 void 1293 ami_scsi_cmd(struct scsi_xfer *xs) 1294 { 1295 struct scsi_link *link = xs->sc_link; 1296 struct ami_softc *sc = link->bus->sb_adapter_softc; 1297 struct device *dev = link->device_softc; 1298 struct ami_ccb *ccb; 1299 struct ami_iocmd *cmd; 1300 struct scsi_inquiry_data inq; 1301 struct scsi_sense_data sd; 1302 struct scsi_read_cap_data rcd; 1303 u_int8_t target = link->target; 1304 u_int32_t blockno, blockcnt; 1305 struct scsi_rw *rw; 1306 struct scsi_rw_10 *rw10; 1307 bus_dma_segment_t *sgd; 1308 int error; 1309 int i; 1310 1311 AMI_DPRINTF(AMI_D_CMD, ("ami_scsi_cmd ")); 1312 1313 if (target >= sc->sc_nunits || !sc->sc_hdr[target].hd_present || 1314 link->lun != 0) { 1315 AMI_DPRINTF(AMI_D_CMD, ("no target %d ", target)); 1316 /* XXX should be XS_SENSE and sense filled out */ 1317 xs->error = XS_DRIVER_STUFFUP; 1318 scsi_done(xs); 1319 return; 1320 } 1321 1322 xs->error = XS_NOERROR; 1323 1324 switch (xs->cmd.opcode) { 1325 case READ_COMMAND: 1326 case READ_10: 1327 case WRITE_COMMAND: 1328 case WRITE_10: 1329 /* deal with io outside the switch */ 1330 break; 1331 1332 case SYNCHRONIZE_CACHE: 1333 ccb = xs->io; 1334 1335 ccb->ccb_xs = xs; 1336 ccb->ccb_done = ami_done_flush; 1337 if (xs->timeout < 30000) 1338 xs->timeout = 30000; /* at least 30sec */ 1339 1340 cmd = &ccb->ccb_cmd; 1341 cmd->acc_cmd = AMI_FLUSH; 1342 1343 ami_start_xs(sc, ccb, xs); 1344 return; 1345 1346 case TEST_UNIT_READY: 1347 /* save off sd? after autoconf */ 1348 if (!cold) /* XXX bogus */ 1349 strlcpy(sc->sc_hdr[target].dev, dev->dv_xname, 1350 sizeof(sc->sc_hdr[target].dev)); 1351 case START_STOP: 1352 #if 0 1353 case VERIFY: 1354 #endif 1355 case PREVENT_ALLOW: 1356 AMI_DPRINTF(AMI_D_CMD, ("opc %d tgt %d ", xs->cmd.opcode, 1357 target)); 1358 xs->error = XS_NOERROR; 1359 scsi_done(xs); 1360 return; 1361 1362 case REQUEST_SENSE: 1363 AMI_DPRINTF(AMI_D_CMD, ("REQUEST SENSE tgt %d ", target)); 1364 bzero(&sd, sizeof(sd)); 1365 sd.error_code = SSD_ERRCODE_CURRENT; 1366 sd.segment = 0; 1367 sd.flags = SKEY_NO_SENSE; 1368 *(u_int32_t*)sd.info = htole32(0); 1369 sd.extra_len = 0; 1370 scsi_copy_internal_data(xs, &sd, sizeof(sd)); 1371 1372 xs->error = XS_NOERROR; 1373 scsi_done(xs); 1374 return; 1375 1376 case INQUIRY: 1377 if (ISSET(((struct scsi_inquiry *)&xs->cmd)->flags, SI_EVPD)) { 1378 xs->error = XS_DRIVER_STUFFUP; 1379 scsi_done(xs); 1380 return; 1381 } 1382 1383 AMI_DPRINTF(AMI_D_CMD, ("INQUIRY tgt %d ", target)); 1384 bzero(&inq, sizeof(inq)); 1385 inq.device = T_DIRECT; 1386 inq.dev_qual2 = 0; 1387 inq.version = SCSI_REV_2; 1388 inq.response_format = SID_SCSI2_RESPONSE; 1389 inq.additional_length = SID_SCSI2_ALEN; 1390 inq.flags |= SID_CmdQue; 1391 strlcpy(inq.vendor, "AMI ", sizeof(inq.vendor)); 1392 snprintf(inq.product, sizeof(inq.product), 1393 "Host drive #%02d", target); 1394 strlcpy(inq.revision, " ", sizeof(inq.revision)); 1395 scsi_copy_internal_data(xs, &inq, sizeof(inq)); 1396 1397 xs->error = XS_NOERROR; 1398 scsi_done(xs); 1399 return; 1400 1401 case READ_CAPACITY: 1402 AMI_DPRINTF(AMI_D_CMD, ("READ CAPACITY tgt %d ", target)); 1403 bzero(&rcd, sizeof(rcd)); 1404 _lto4b(sc->sc_hdr[target].hd_size - 1, rcd.addr); 1405 _lto4b(AMI_SECTOR_SIZE, rcd.length); 1406 scsi_copy_internal_data(xs, &rcd, sizeof(rcd)); 1407 1408 xs->error = XS_NOERROR; 1409 scsi_done(xs); 1410 return; 1411 1412 default: 1413 AMI_DPRINTF(AMI_D_CMD, ("unsupported scsi command %#x tgt %d ", 1414 xs->cmd.opcode, target)); 1415 1416 xs->error = XS_DRIVER_STUFFUP; 1417 scsi_done(xs); 1418 return; 1419 } 1420 1421 /* A read or write operation. */ 1422 if (xs->cmdlen == 6) { 1423 rw = (struct scsi_rw *)&xs->cmd; 1424 blockno = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff); 1425 blockcnt = rw->length ? rw->length : 0x100; 1426 } else { 1427 rw10 = (struct scsi_rw_10 *)&xs->cmd; 1428 blockno = _4btol(rw10->addr); 1429 blockcnt = _2btol(rw10->length); 1430 } 1431 1432 if (blockno >= sc->sc_hdr[target].hd_size || 1433 blockno + blockcnt > sc->sc_hdr[target].hd_size) { 1434 printf("%s: out of bounds %u-%u >= %u\n", DEVNAME(sc), 1435 blockno, blockcnt, sc->sc_hdr[target].hd_size); 1436 xs->error = XS_DRIVER_STUFFUP; 1437 scsi_done(xs); 1438 return; 1439 } 1440 1441 ccb = xs->io; 1442 1443 ccb->ccb_xs = xs; 1444 ccb->ccb_done = ami_done_xs; 1445 1446 cmd = &ccb->ccb_cmd; 1447 cmd->acc_cmd = (xs->flags & SCSI_DATA_IN) ? AMI_READ : AMI_WRITE; 1448 cmd->acc_mbox.amb_nsect = htole16(blockcnt); 1449 cmd->acc_mbox.amb_lba = htole32(blockno); 1450 cmd->acc_mbox.amb_ldn = target; 1451 1452 error = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap, 1453 xs->data, xs->datalen, NULL, 1454 (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 1455 if (error) { 1456 if (error == EFBIG) 1457 printf("more than %d dma segs\n", AMI_MAXOFFSETS); 1458 else 1459 printf("error %d loading dma map\n", error); 1460 1461 xs->error = XS_DRIVER_STUFFUP; 1462 scsi_done(xs); 1463 return; 1464 } 1465 1466 sgd = ccb->ccb_dmamap->dm_segs; 1467 if (ccb->ccb_dmamap->dm_nsegs > 1) { 1468 struct ami_sgent *sgl = ccb->ccb_sglist; 1469 1470 cmd->acc_mbox.amb_nsge = ccb->ccb_dmamap->dm_nsegs; 1471 cmd->acc_mbox.amb_data = ccb->ccb_sglistpa; 1472 1473 for (i = 0; i < ccb->ccb_dmamap->dm_nsegs; i++) { 1474 sgl[i].asg_addr = htole32(sgd[i].ds_addr); 1475 sgl[i].asg_len = htole32(sgd[i].ds_len); 1476 } 1477 } else { 1478 cmd->acc_mbox.amb_nsge = 0; 1479 cmd->acc_mbox.amb_data = htole32(sgd->ds_addr); 1480 } 1481 1482 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am), 1483 ccb->ccb_offset, sizeof(struct ami_ccbmem), 1484 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1485 1486 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0, 1487 ccb->ccb_dmamap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ? 1488 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 1489 1490 ami_start_xs(sc, ccb, xs); 1491 } 1492 1493 int 1494 ami_intr(void *v) 1495 { 1496 struct ami_iocmd mbox; 1497 struct ami_softc *sc = v; 1498 struct ami_ccb *ccb; 1499 int i, rv = 0, ready; 1500 1501 mtx_enter(&sc->sc_cmd_mtx); 1502 while (!TAILQ_EMPTY(&sc->sc_ccb_runq) && sc->sc_done(sc, &mbox)) { 1503 AMI_DPRINTF(AMI_D_CMD, ("got#%d ", mbox.acc_nstat)); 1504 for (i = 0; i < mbox.acc_nstat; i++ ) { 1505 ready = mbox.acc_cmplidl[i] - 1; 1506 AMI_DPRINTF(AMI_D_CMD, ("ready=%d ", ready)); 1507 1508 ccb = &sc->sc_ccbs[ready]; 1509 ccb->ccb_status = mbox.acc_status; 1510 ccb->ccb_state = AMI_CCB_READY; 1511 TAILQ_REMOVE(&ccb->ccb_sc->sc_ccb_runq, ccb, ccb_link); 1512 1513 mtx_leave(&sc->sc_cmd_mtx); 1514 ccb->ccb_done(sc, ccb); 1515 mtx_enter(&sc->sc_cmd_mtx); 1516 1517 rv = 1; 1518 } 1519 } 1520 ready = (sc->sc_drainio && TAILQ_EMPTY(&sc->sc_ccb_runq)); 1521 mtx_leave(&sc->sc_cmd_mtx); 1522 1523 if (ready) 1524 wakeup(sc); 1525 else if (rv) 1526 ami_runqueue(sc); 1527 1528 AMI_DPRINTF(AMI_D_INTR, ("exit ")); 1529 return (rv); 1530 } 1531 1532 int 1533 ami_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag) 1534 { 1535 struct ami_softc *sc = link->bus->sb_adapter_softc; 1536 /* struct device *dev = (struct device *)link->device_softc; */ 1537 /* u_int8_t target = link->target; */ 1538 1539 if (sc->sc_ioctl) 1540 return (sc->sc_ioctl(&sc->sc_dev, cmd, addr)); 1541 else 1542 return (ENOTTY); 1543 } 1544 1545 #if NBIO > 0 1546 int 1547 ami_ioctl(struct device *dev, u_long cmd, caddr_t addr) 1548 { 1549 struct ami_softc *sc = (struct ami_softc *)dev; 1550 int error = 0; 1551 1552 AMI_DPRINTF(AMI_D_IOCTL, ("%s: ioctl ", DEVNAME(sc))); 1553 1554 if (sc->sc_flags & AMI_BROKEN) 1555 return (ENODEV); /* can't do this to broken device for now */ 1556 1557 switch (cmd) { 1558 case BIOCINQ: 1559 AMI_DPRINTF(AMI_D_IOCTL, ("inq ")); 1560 error = ami_ioctl_inq(sc, (struct bioc_inq *)addr); 1561 break; 1562 1563 case BIOCVOL: 1564 AMI_DPRINTF(AMI_D_IOCTL, ("vol ")); 1565 error = ami_ioctl_vol(sc, (struct bioc_vol *)addr); 1566 break; 1567 1568 case BIOCDISK: 1569 AMI_DPRINTF(AMI_D_IOCTL, ("disk ")); 1570 error = ami_ioctl_disk(sc, (struct bioc_disk *)addr); 1571 break; 1572 1573 case BIOCALARM: 1574 AMI_DPRINTF(AMI_D_IOCTL, ("alarm ")); 1575 error = ami_ioctl_alarm(sc, (struct bioc_alarm *)addr); 1576 break; 1577 1578 case BIOCSETSTATE: 1579 AMI_DPRINTF(AMI_D_IOCTL, ("setstate ")); 1580 error = ami_ioctl_setstate(sc, (struct bioc_setstate *)addr); 1581 break; 1582 1583 default: 1584 AMI_DPRINTF(AMI_D_IOCTL, (" invalid ioctl\n")); 1585 error = ENOTTY; 1586 } 1587 1588 return (error); 1589 } 1590 1591 int 1592 ami_drv_pt(struct ami_softc *sc, u_int8_t ch, u_int8_t tg, u_int8_t *cmd, 1593 int clen, int blen, void *buf) 1594 { 1595 struct ami_ccb *ccb; 1596 struct ami_passthrough *pt; 1597 int error = 0; 1598 1599 rw_enter_write(&sc->sc_lock); 1600 1601 ccb = scsi_io_get(&sc->sc_iopool, 0); 1602 if (ccb == NULL) { 1603 error = ENOMEM; 1604 goto err; 1605 } 1606 1607 ccb->ccb_done = ami_done_ioctl; 1608 1609 ccb->ccb_cmd.acc_cmd = AMI_PASSTHRU; 1610 ccb->ccb_cmd.acc_passthru.apt_data = ccb->ccb_ptpa; 1611 1612 pt = ccb->ccb_pt; 1613 memset(pt, 0, sizeof *pt); 1614 pt->apt_channel = ch; 1615 pt->apt_target = tg; 1616 pt->apt_ncdb = clen; 1617 pt->apt_nsense = sizeof(struct scsi_sense_data); 1618 pt->apt_datalen = blen; 1619 pt->apt_data = 0; 1620 1621 bcopy(cmd, pt->apt_cdb, clen); 1622 1623 if (ami_load_ptmem(sc, ccb, buf, blen, 1, 0) != 0) { 1624 error = ENOMEM; 1625 goto ptmemerr; 1626 } 1627 1628 ami_start(sc, ccb); 1629 1630 while (ccb->ccb_state != AMI_CCB_READY) 1631 tsleep_nsec(ccb, PRIBIO, "ami_drv_pt", INFSLP); 1632 1633 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0, 1634 ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); 1635 bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am), 1636 ccb->ccb_offset, sizeof(struct ami_ccbmem), 1637 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1638 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap); 1639 1640 if (ccb->ccb_flags & AMI_CCB_F_ERR) 1641 error = EIO; 1642 else if (pt->apt_scsistat != 0x00) 1643 error = EIO; 1644 1645 ptmemerr: 1646 scsi_io_put(&sc->sc_iopool, ccb); 1647 1648 err: 1649 rw_exit_write(&sc->sc_lock); 1650 return (error); 1651 } 1652 1653 int 1654 ami_drv_inq(struct ami_softc *sc, u_int8_t ch, u_int8_t tg, u_int8_t page, 1655 void *inqbuf) 1656 { 1657 struct scsi_inquiry_data *inq = inqbuf; 1658 u_int8_t cdb[6]; 1659 int error = 0; 1660 1661 bzero(&cdb, sizeof cdb); 1662 1663 cdb[0] = INQUIRY; 1664 cdb[1] = 0; 1665 cdb[2] = 0; 1666 cdb[3] = 0; 1667 cdb[4] = sizeof(struct scsi_inquiry_data); 1668 cdb[5] = 0; 1669 if (page != 0) { 1670 cdb[1] = SI_EVPD; 1671 cdb[2] = page; 1672 } 1673 1674 error = ami_drv_pt(sc, ch, tg, cdb, 6, sizeof *inq, inqbuf); 1675 if (error) 1676 return (error); 1677 1678 if ((inq->device & SID_TYPE) != T_DIRECT) 1679 error = EINVAL; 1680 1681 return (error); 1682 } 1683 1684 int 1685 ami_drv_readcap(struct ami_softc *sc, u_int8_t ch, u_int8_t tg, daddr_t *sz) 1686 { 1687 struct scsi_read_cap_data *rcd = NULL; 1688 struct scsi_read_cap_data_16 *rcd16 = NULL; 1689 u_int8_t cdb[16]; 1690 u_int32_t blksz; 1691 daddr_t noblk; 1692 int error = 0; 1693 1694 bzero(&cdb, sizeof cdb); 1695 cdb[0] = READ_CAPACITY; 1696 rcd = dma_alloc(sizeof(*rcd), PR_WAITOK); 1697 1698 error = ami_drv_pt(sc, ch, tg, cdb, 10, sizeof(*rcd), rcd); 1699 if (error) 1700 goto fail; 1701 1702 noblk = _4btol(rcd->addr); 1703 if (noblk == 0xffffffffllu) { 1704 /* huge disk */ 1705 bzero(&cdb, sizeof cdb); 1706 cdb[0] = READ_CAPACITY_16; 1707 rcd16 = dma_alloc(sizeof(*rcd16), PR_WAITOK); 1708 1709 error = ami_drv_pt(sc, ch, tg, cdb, 16, sizeof(*rcd16), rcd16); 1710 if (error) 1711 goto fail; 1712 1713 noblk = _8btol(rcd16->addr); 1714 blksz = _4btol(rcd16->length); 1715 } else 1716 blksz = _4btol(rcd->length); 1717 1718 if (blksz == 0) 1719 blksz = 512; 1720 *sz = noblk * blksz; 1721 1722 fail: 1723 if (rcd16) 1724 dma_free(rcd16, sizeof(*rcd16)); 1725 dma_free(rcd, sizeof(*rcd)); 1726 return (error); 1727 } 1728 1729 int 1730 ami_mgmt(struct ami_softc *sc, u_int8_t opcode, u_int8_t par1, u_int8_t par2, 1731 u_int8_t par3, size_t size, void *buffer) 1732 { 1733 struct ami_ccb *ccb; 1734 struct ami_iocmd *cmd; 1735 struct ami_mem *am = NULL; 1736 char *idata = NULL; 1737 int error = 0; 1738 1739 rw_enter_write(&sc->sc_lock); 1740 1741 if (opcode != AMI_CHSTATE) { 1742 ccb = scsi_io_get(&sc->sc_iopool, 0); 1743 if (ccb == NULL) { 1744 error = ENOMEM; 1745 goto err; 1746 } 1747 ccb->ccb_done = ami_done_ioctl; 1748 } else 1749 ccb = sc->sc_mgmtccb; 1750 1751 if (size) { 1752 if ((am = ami_allocmem(sc, size)) == NULL) { 1753 error = ENOMEM; 1754 goto memerr; 1755 } 1756 idata = AMIMEM_KVA(am); 1757 } 1758 1759 cmd = &ccb->ccb_cmd; 1760 cmd->acc_cmd = opcode; 1761 1762 /* 1763 * some commands require data to be written to idata before sending 1764 * command to fw 1765 */ 1766 switch (opcode) { 1767 case AMI_SPEAKER: 1768 *idata = par1; 1769 break; 1770 default: 1771 cmd->acc_io.aio_channel = par1; 1772 cmd->acc_io.aio_param = par2; 1773 cmd->acc_io.aio_pad[0] = par3; 1774 break; 1775 }; 1776 1777 cmd->acc_io.aio_data = am ? htole32(AMIMEM_DVA(am)) : 0; 1778 1779 if (opcode != AMI_CHSTATE) { 1780 ami_start(sc, ccb); 1781 mtx_enter(&sc->sc_cmd_mtx); 1782 while (ccb->ccb_state != AMI_CCB_READY) 1783 msleep_nsec(ccb, &sc->sc_cmd_mtx, PRIBIO, "ami_mgmt", 1784 INFSLP); 1785 mtx_leave(&sc->sc_cmd_mtx); 1786 } else { 1787 /* change state must be run with id 0xfe and MUST be polled */ 1788 mtx_enter(&sc->sc_cmd_mtx); 1789 sc->sc_drainio = 1; 1790 while (!TAILQ_EMPTY(&sc->sc_ccb_runq)) { 1791 if (msleep_nsec(sc, &sc->sc_cmd_mtx, PRIBIO, 1792 "amimgmt", SEC_TO_NSEC(60)) == EWOULDBLOCK) { 1793 printf("%s: drain io timeout\n", DEVNAME(sc)); 1794 ccb->ccb_flags |= AMI_CCB_F_ERR; 1795 goto restartio; 1796 } 1797 } 1798 1799 error = sc->sc_poll(sc, &ccb->ccb_cmd); 1800 if (error == -1) 1801 ccb->ccb_flags |= AMI_CCB_F_ERR; 1802 1803 restartio: 1804 /* restart io */ 1805 sc->sc_drainio = 0; 1806 mtx_leave(&sc->sc_cmd_mtx); 1807 ami_runqueue(sc); 1808 } 1809 1810 if (ccb->ccb_flags & AMI_CCB_F_ERR) 1811 error = EIO; 1812 else if (buffer && size) 1813 memcpy(buffer, idata, size); 1814 1815 if (am) 1816 ami_freemem(sc, am); 1817 memerr: 1818 if (opcode != AMI_CHSTATE) { 1819 scsi_io_put(&sc->sc_iopool, ccb); 1820 } else { 1821 ccb->ccb_flags = 0; 1822 ccb->ccb_state = AMI_CCB_FREE; 1823 } 1824 1825 err: 1826 rw_exit_write(&sc->sc_lock); 1827 return (error); 1828 } 1829 1830 int 1831 ami_ioctl_inq(struct ami_softc *sc, struct bioc_inq *bi) 1832 { 1833 struct ami_big_diskarray *p; /* struct too large for stack */ 1834 struct scsi_inquiry_data *inqbuf; 1835 struct ami_fc_einquiry einq; 1836 int ch, tg; 1837 int i, s, t, off; 1838 int error = 0, changes = 0; 1839 1840 if ((error = ami_mgmt(sc, AMI_FCOP, AMI_FC_EINQ3, 1841 AMI_FC_EINQ3_SOLICITED_FULL, 0, sizeof einq, &einq))) 1842 return (EINVAL); 1843 1844 inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK); 1845 1846 if (einq.ain_drvinscnt == sc->sc_drvinscnt) { 1847 /* poke existing known drives to make sure they aren't gone */ 1848 for(i = 0; i < sc->sc_channels * 16; i++) { 1849 if (sc->sc_plist[i] == 0) 1850 continue; 1851 1852 ch = (i & 0xf0) >> 4; 1853 tg = i & 0x0f; 1854 if (ami_drv_inq(sc, ch, tg, 0, inqbuf)) { 1855 /* drive is gone, force rescan */ 1856 changes = 1; 1857 break; 1858 } 1859 } 1860 if (changes == 0) { 1861 bcopy(&sc->sc_bi, bi, sizeof *bi); 1862 goto done; 1863 } 1864 } 1865 1866 sc->sc_drvinscnt = einq.ain_drvinscnt; 1867 1868 p = malloc(sizeof *p, M_DEVBUF, M_NOWAIT); 1869 if (!p) { 1870 error = ENOMEM; 1871 goto done; 1872 } 1873 1874 if ((error = ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, 0, sizeof *p, 1875 p))) { 1876 error = EINVAL; 1877 goto bail; 1878 } 1879 1880 bzero(sc->sc_plist, sizeof sc->sc_plist); 1881 1882 bi->bi_novol = p->ada_nld; 1883 bi->bi_nodisk = 0; 1884 strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev)); 1885 1886 /* count used disks, including failed ones */ 1887 for (i = 0; i < p->ada_nld; i++) 1888 for (s = 0; s < p->ald[i].adl_spandepth; s++) 1889 for (t = 0; t < p->ald[i].adl_nstripes; t++) { 1890 off = p->ald[i].asp[s].adv[t].add_channel * 1891 AMI_MAX_TARGET + 1892 p->ald[i].asp[s].adv[t].add_target; 1893 1894 /* account for multi raid vol on same disk */ 1895 if (!sc->sc_plist[off]) { 1896 sc->sc_plist[off] = 1; 1897 bi->bi_nodisk++; 1898 } 1899 } 1900 1901 /* count unused disks */ 1902 for(i = 0; i < sc->sc_channels * 16; i++) { 1903 if (sc->sc_plist[i]) 1904 continue; /* skip claimed drives */ 1905 1906 /* 1907 * hack to invalidate device type, needed for initiator id 1908 * on an unconnected channel. 1909 * XXX find out if we can determine this differently 1910 */ 1911 memset(inqbuf, 0xff, sizeof(*inqbuf)); 1912 1913 ch = (i & 0xf0) >> 4; 1914 tg = i & 0x0f; 1915 if (!ami_drv_inq(sc, ch, tg, 0, inqbuf)) { 1916 if ((inqbuf->device & SID_TYPE) != T_DIRECT) 1917 continue; 1918 bi->bi_novol++; 1919 bi->bi_nodisk++; 1920 sc->sc_plist[i] = 2; 1921 } else 1922 sc->sc_plist[i] = 0; 1923 } 1924 1925 bcopy(bi, &sc->sc_bi, sizeof sc->sc_bi); 1926 error = 0; 1927 bail: 1928 free(p, M_DEVBUF, sizeof *p); 1929 done: 1930 dma_free(inqbuf, sizeof(*inqbuf)); 1931 return (error); 1932 } 1933 1934 int 1935 ami_vol(struct ami_softc *sc, struct bioc_vol *bv, struct ami_big_diskarray *p) 1936 { 1937 int i, ld = p->ada_nld, error = EINVAL; 1938 1939 for(i = 0; i < sc->sc_channels * 16; i++) { 1940 /* skip claimed/unused drives */ 1941 if (sc->sc_plist[i] != 2) 1942 continue; 1943 1944 /* are we it? */ 1945 if (ld != bv->bv_volid) { 1946 ld++; 1947 continue; 1948 } 1949 1950 bv->bv_status = BIOC_SVONLINE; 1951 bv->bv_size = (uint64_t)p->apd[i].adp_size * 1952 (uint64_t)512; 1953 bv->bv_nodisk = 1; 1954 strlcpy(bv->bv_dev, 1955 sc->sc_hdr[bv->bv_volid].dev, 1956 sizeof(bv->bv_dev)); 1957 1958 if (p->apd[i].adp_ostatus == AMI_PD_HOTSPARE 1959 && p->apd[i].adp_type == 0) 1960 bv->bv_level = -1; 1961 else 1962 bv->bv_level = -2; 1963 1964 error = 0; 1965 goto bail; 1966 } 1967 1968 bail: 1969 return (error); 1970 } 1971 1972 int 1973 ami_disk(struct ami_softc *sc, struct bioc_disk *bd, 1974 struct ami_big_diskarray *p) 1975 { 1976 char vend[8+16+4+1], *vendp; 1977 char ser[32 + 1]; 1978 struct scsi_inquiry_data *inqbuf; 1979 struct scsi_vpd_serial *vpdbuf; 1980 int i, ld = p->ada_nld, error = EINVAL; 1981 u_int8_t ch, tg; 1982 daddr_t sz = 0; 1983 1984 inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK); 1985 vpdbuf = dma_alloc(sizeof(*vpdbuf), PR_WAITOK); 1986 1987 for(i = 0; i < sc->sc_channels * 16; i++) { 1988 /* skip claimed/unused drives */ 1989 if (sc->sc_plist[i] != 2) 1990 continue; 1991 1992 /* are we it? */ 1993 if (ld != bd->bd_volid) { 1994 ld++; 1995 continue; 1996 } 1997 1998 ch = (i & 0xf0) >> 4; 1999 tg = i & 0x0f; 2000 if (ami_drv_inq(sc, ch, tg, 0, inqbuf)) 2001 goto bail; 2002 2003 vendp = inqbuf->vendor; 2004 bcopy(vendp, vend, sizeof vend - 1); 2005 2006 vend[sizeof vend - 1] = '\0'; 2007 strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor)); 2008 2009 if (!ami_drv_inq(sc, ch, tg, 0x80, vpdbuf)) { 2010 bcopy(vpdbuf->serial, ser, sizeof ser - 1); 2011 ser[sizeof ser - 1] = '\0'; 2012 if (_2btol(vpdbuf->hdr.page_length) < sizeof ser) 2013 ser[_2btol(vpdbuf->hdr.page_length)] = '\0'; 2014 strlcpy(bd->bd_serial, ser, sizeof(bd->bd_serial)); 2015 } 2016 2017 error = ami_drv_readcap(sc, ch, tg, &sz); 2018 if (error) 2019 goto bail; 2020 2021 bd->bd_size = sz; 2022 bd->bd_channel = ch; 2023 bd->bd_target = tg; 2024 2025 strlcpy(bd->bd_procdev, sc->sc_rawsoftcs[ch].sc_procdev, 2026 sizeof(bd->bd_procdev)); 2027 2028 if (p->apd[i].adp_ostatus == AMI_PD_HOTSPARE) 2029 bd->bd_status = BIOC_SDHOTSPARE; 2030 else 2031 bd->bd_status = BIOC_SDUNUSED; 2032 2033 #ifdef AMI_DEBUG 2034 if (p->apd[i].adp_type != 0) 2035 printf("invalid disk type: %d %d %x inquiry type: %x\n", 2036 ch, tg, p->apd[i].adp_type, inqbuf->device); 2037 #endif /* AMI_DEBUG */ 2038 2039 error = 0; 2040 goto bail; 2041 } 2042 2043 bail: 2044 dma_free(inqbuf, sizeof(*inqbuf)); 2045 dma_free(vpdbuf, sizeof(*vpdbuf)); 2046 return (error); 2047 } 2048 2049 int 2050 ami_ioctl_vol(struct ami_softc *sc, struct bioc_vol *bv) 2051 { 2052 struct ami_big_diskarray *p; /* struct too large for stack */ 2053 int i, s, t, off; 2054 int error = 0; 2055 struct ami_progress perc; 2056 u_int8_t bgi[5]; /* 40 LD, 1 bit per LD if BGI is active */ 2057 2058 p = malloc(sizeof *p, M_DEVBUF, M_NOWAIT); 2059 if (!p) 2060 return (ENOMEM); 2061 2062 if ((error = ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, 0, sizeof *p, p))) 2063 goto bail; 2064 2065 if (bv->bv_volid >= p->ada_nld) { 2066 error = ami_vol(sc, bv, p); 2067 goto bail; 2068 } 2069 2070 i = bv->bv_volid; 2071 2072 switch (p->ald[i].adl_status) { 2073 case AMI_RDRV_OFFLINE: 2074 bv->bv_status = BIOC_SVOFFLINE; 2075 break; 2076 2077 case AMI_RDRV_DEGRADED: 2078 bv->bv_status = BIOC_SVDEGRADED; 2079 break; 2080 2081 case AMI_RDRV_OPTIMAL: 2082 bv->bv_status = BIOC_SVONLINE; 2083 bv->bv_percent = -1; 2084 2085 /* get BGI progress here and over-ride status if so */ 2086 memset(bgi, 0, sizeof bgi); 2087 if (ami_mgmt(sc, AMI_MISC, AMI_GET_BGI, 0, 0, sizeof bgi, &bgi)) 2088 break; 2089 2090 if ((bgi[i / 8] & (1 << i % 8)) == 0) 2091 break; 2092 2093 if (!ami_mgmt(sc, AMI_GCHECKPROGR, i, 0, 0, sizeof perc, &perc)) 2094 if (perc.apr_progress < 100) { 2095 bv->bv_status = BIOC_SVSCRUB; 2096 bv->bv_percent = perc.apr_progress >= 100 ? -1 : 2097 perc.apr_progress; 2098 } 2099 break; 2100 2101 default: 2102 bv->bv_status = BIOC_SVINVALID; 2103 } 2104 2105 /* over-ride status if a pd is in rebuild status for this ld */ 2106 for (s = 0; s < p->ald[i].adl_spandepth; s++) 2107 for (t = 0; t < p->ald[i].adl_nstripes; t++) { 2108 off = p->ald[i].asp[s].adv[t].add_channel * 2109 AMI_MAX_TARGET + 2110 p->ald[i].asp[s].adv[t].add_target; 2111 2112 if (p->apd[off].adp_ostatus != AMI_PD_RBLD) 2113 continue; 2114 2115 /* get rebuild progress from pd 0 */ 2116 bv->bv_status = BIOC_SVREBUILD; 2117 if (ami_mgmt(sc, AMI_GRBLDPROGR, 2118 p->ald[i].asp[s].adv[t].add_channel, 2119 p->ald[i].asp[s].adv[t].add_target, 0, 2120 sizeof perc, &perc)) 2121 bv->bv_percent = -1; 2122 else 2123 bv->bv_percent = perc.apr_progress >= 100 ? -1 : 2124 perc.apr_progress; 2125 break; 2126 } 2127 2128 bv->bv_size = 0; 2129 bv->bv_level = p->ald[i].adl_raidlvl; 2130 bv->bv_nodisk = 0; 2131 2132 for (s = 0; s < p->ald[i].adl_spandepth; s++) { 2133 for (t = 0; t < p->ald[i].adl_nstripes; t++) 2134 bv->bv_nodisk++; 2135 2136 switch (bv->bv_level) { 2137 case 0: 2138 bv->bv_size += p->ald[i].asp[s].ads_length * 2139 p->ald[i].adl_nstripes; 2140 break; 2141 2142 case 1: 2143 bv->bv_size += p->ald[i].asp[s].ads_length; 2144 break; 2145 2146 case 5: 2147 bv->bv_size += p->ald[i].asp[s].ads_length * 2148 (p->ald[i].adl_nstripes - 1); 2149 break; 2150 } 2151 } 2152 2153 if (p->ald[i].adl_spandepth > 1) 2154 bv->bv_level *= 10; 2155 2156 bv->bv_size *= (uint64_t)512; 2157 2158 strlcpy(bv->bv_dev, sc->sc_hdr[i].dev, sizeof(bv->bv_dev)); 2159 2160 bail: 2161 free(p, M_DEVBUF, sizeof *p); 2162 2163 return (error); 2164 } 2165 2166 int 2167 ami_ioctl_disk(struct ami_softc *sc, struct bioc_disk *bd) 2168 { 2169 struct scsi_inquiry_data *inqbuf; 2170 struct scsi_vpd_serial *vpdbuf; 2171 struct ami_big_diskarray *p; /* struct too large for stack */ 2172 int i, s, t, d; 2173 int off; 2174 int error = EINVAL; 2175 u_int16_t ch, tg; 2176 char vend[8+16+4+1], *vendp; 2177 char ser[32 + 1]; 2178 2179 inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK); 2180 vpdbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK); 2181 p = malloc(sizeof *p, M_DEVBUF, M_WAITOK); 2182 2183 if ((error = ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, 0, sizeof *p, p))) 2184 goto bail; 2185 2186 if (bd->bd_volid >= p->ada_nld) { 2187 error = ami_disk(sc, bd, p); 2188 goto bail; 2189 } 2190 2191 i = bd->bd_volid; 2192 for (s = 0, d = 0; s < p->ald[i].adl_spandepth; s++) 2193 for (t = 0; t < p->ald[i].adl_nstripes; t++) { 2194 if (d != bd->bd_diskid) { 2195 d++; 2196 continue; 2197 } 2198 2199 off = p->ald[i].asp[s].adv[t].add_channel * 2200 AMI_MAX_TARGET + 2201 p->ald[i].asp[s].adv[t].add_target; 2202 2203 bd->bd_size = (uint64_t)p->apd[off].adp_size * 2204 (uint64_t)512; 2205 2206 switch (p->apd[off].adp_ostatus) { 2207 case AMI_PD_UNCNF: 2208 bd->bd_status = BIOC_SDUNUSED; 2209 break; 2210 2211 case AMI_PD_ONLINE: 2212 bd->bd_status = BIOC_SDONLINE; 2213 break; 2214 2215 case AMI_PD_FAILED: 2216 bd->bd_status = BIOC_SDFAILED; 2217 bd->bd_size = 0; 2218 break; 2219 2220 case AMI_PD_RBLD: 2221 bd->bd_status = BIOC_SDREBUILD; 2222 break; 2223 2224 case AMI_PD_HOTSPARE: 2225 bd->bd_status = BIOC_SDHOTSPARE; 2226 break; 2227 2228 default: 2229 bd->bd_status = BIOC_SDINVALID; 2230 bd->bd_size = 0; 2231 } 2232 2233 2234 ch = p->ald[i].asp[s].adv[t].add_target >> 4; 2235 tg = p->ald[i].asp[s].adv[t].add_target & 0x0f; 2236 2237 bd->bd_channel = ch; 2238 bd->bd_target = tg; 2239 strlcpy(bd->bd_procdev, sc->sc_rawsoftcs[ch].sc_procdev, 2240 sizeof(bd->bd_procdev)); 2241 2242 /* if we are failed don't query drive */ 2243 if (bd->bd_size == 0) { 2244 bzero(&bd->bd_vendor, sizeof(bd->bd_vendor)); 2245 bzero(&bd->bd_serial, sizeof(bd->bd_serial)); 2246 goto done; 2247 } 2248 2249 if (!ami_drv_inq(sc, ch, tg, 0, inqbuf)) { 2250 vendp = inqbuf->vendor; 2251 bcopy(vendp, vend, sizeof vend - 1); 2252 vend[sizeof vend - 1] = '\0'; 2253 strlcpy(bd->bd_vendor, vend, 2254 sizeof(bd->bd_vendor)); 2255 } 2256 2257 if (!ami_drv_inq(sc, ch, tg, 0x80, vpdbuf)) { 2258 bcopy(vpdbuf->serial, ser, sizeof ser - 1); 2259 ser[sizeof ser - 1] = '\0'; 2260 if (_2btol(vpdbuf->hdr.page_length) < 2261 sizeof(ser)) 2262 ser[_2btol(vpdbuf->hdr.page_length)] = 2263 '\0'; 2264 strlcpy(bd->bd_serial, ser, 2265 sizeof(bd->bd_serial)); 2266 } 2267 goto done; 2268 } 2269 2270 done: 2271 error = 0; 2272 bail: 2273 free(p, M_DEVBUF, sizeof *p); 2274 dma_free(vpdbuf, sizeof(*vpdbuf)); 2275 dma_free(inqbuf, sizeof(*inqbuf)); 2276 2277 return (error); 2278 } 2279 2280 int ami_ioctl_alarm(struct ami_softc *sc, struct bioc_alarm *ba) 2281 { 2282 int error = 0; 2283 u_int8_t func, ret; 2284 2285 switch(ba->ba_opcode) { 2286 case BIOC_SADISABLE: 2287 func = AMI_SPKR_OFF; 2288 break; 2289 2290 case BIOC_SAENABLE: 2291 func = AMI_SPKR_ON; 2292 break; 2293 2294 case BIOC_SASILENCE: 2295 func = AMI_SPKR_SHUT; 2296 break; 2297 2298 case BIOC_GASTATUS: 2299 func = AMI_SPKR_GVAL; 2300 break; 2301 2302 case BIOC_SATEST: 2303 func = AMI_SPKR_TEST; 2304 break; 2305 2306 default: 2307 AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocalarm invalid opcode %x\n", 2308 DEVNAME(sc), ba->ba_opcode)); 2309 return (EINVAL); 2310 } 2311 2312 if (!(error = ami_mgmt(sc, AMI_SPEAKER, func, 0, 0, sizeof ret, 2313 &ret))) { 2314 if (ba->ba_opcode == BIOC_GASTATUS) 2315 ba->ba_status = ret; 2316 else 2317 ba->ba_status = 0; 2318 } 2319 2320 return (error); 2321 } 2322 2323 int 2324 ami_ioctl_setstate(struct ami_softc *sc, struct bioc_setstate *bs) 2325 { 2326 struct scsi_inquiry_data *inqbuf; 2327 int func, error = 0; 2328 2329 inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK); 2330 2331 switch (bs->bs_status) { 2332 case BIOC_SSONLINE: 2333 func = AMI_STATE_ON; 2334 break; 2335 2336 case BIOC_SSOFFLINE: 2337 func = AMI_STATE_FAIL; 2338 break; 2339 2340 case BIOC_SSHOTSPARE: 2341 if (ami_drv_inq(sc, bs->bs_channel, bs->bs_target, 0, 2342 inqbuf)) { 2343 error = EINVAL; 2344 goto done; 2345 } 2346 2347 func = AMI_STATE_SPARE; 2348 break; 2349 2350 default: 2351 AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocsetstate invalid opcode %x\n" 2352 , DEVNAME(sc), bs->bs_status)); 2353 error = EINVAL; 2354 goto done; 2355 } 2356 2357 if ((error = ami_mgmt(sc, AMI_CHSTATE, bs->bs_channel, bs->bs_target, 2358 func, 0, NULL))) 2359 goto done; 2360 2361 done: 2362 dma_free(inqbuf, sizeof(*inqbuf)); 2363 return (error); 2364 } 2365 2366 #ifndef SMALL_KERNEL 2367 int 2368 ami_create_sensors(struct ami_softc *sc) 2369 { 2370 struct device *dev; 2371 struct scsibus_softc *ssc = NULL; 2372 struct scsi_link *link; 2373 int i; 2374 2375 TAILQ_FOREACH(dev, &alldevs, dv_list) { 2376 if (dev->dv_parent != &sc->sc_dev) 2377 continue; 2378 2379 /* check if this is the scsibus for the logical disks */ 2380 ssc = (struct scsibus_softc *)dev; 2381 if (ssc == sc->sc_scsibus) 2382 break; 2383 } 2384 2385 if (ssc == NULL) 2386 return (1); 2387 2388 sc->sc_sensors = mallocarray(sc->sc_nunits, sizeof(struct ksensor), 2389 M_DEVBUF, M_WAITOK|M_CANFAIL|M_ZERO); 2390 if (sc->sc_sensors == NULL) 2391 return (1); 2392 2393 strlcpy(sc->sc_sensordev.xname, DEVNAME(sc), 2394 sizeof(sc->sc_sensordev.xname)); 2395 2396 for (i = 0; i < sc->sc_nunits; i++) { 2397 link = scsi_get_link(ssc, i, 0); 2398 if (link == NULL) 2399 goto bad; 2400 2401 dev = link->device_softc; 2402 2403 sc->sc_sensors[i].type = SENSOR_DRIVE; 2404 sc->sc_sensors[i].status = SENSOR_S_UNKNOWN; 2405 2406 strlcpy(sc->sc_sensors[i].desc, dev->dv_xname, 2407 sizeof(sc->sc_sensors[i].desc)); 2408 2409 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]); 2410 } 2411 2412 sc->sc_bd = malloc(sizeof(*sc->sc_bd), M_DEVBUF, M_WAITOK|M_CANFAIL); 2413 if (sc->sc_bd == NULL) 2414 goto bad; 2415 2416 if (sensor_task_register(sc, ami_refresh_sensors, 10) == NULL) 2417 goto freebd; 2418 2419 sensordev_install(&sc->sc_sensordev); 2420 2421 return (0); 2422 2423 freebd: 2424 free(sc->sc_bd, M_DEVBUF, sizeof(*sc->sc_bd)); 2425 bad: 2426 free(sc->sc_sensors, M_DEVBUF, sc->sc_nunits * sizeof(struct ksensor)); 2427 2428 return (1); 2429 } 2430 2431 void 2432 ami_refresh_sensors(void *arg) 2433 { 2434 struct ami_softc *sc = arg; 2435 int i; 2436 2437 if (ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, 0, sizeof(*sc->sc_bd), 2438 sc->sc_bd)) { 2439 for (i = 0; i < sc->sc_nunits; i++) { 2440 sc->sc_sensors[i].value = 0; /* unknown */ 2441 sc->sc_sensors[i].status = SENSOR_S_UNKNOWN; 2442 } 2443 return; 2444 } 2445 2446 for (i = 0; i < sc->sc_nunits; i++) { 2447 switch (sc->sc_bd->ald[i].adl_status) { 2448 case AMI_RDRV_OFFLINE: 2449 sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL; 2450 sc->sc_sensors[i].status = SENSOR_S_CRIT; 2451 break; 2452 2453 case AMI_RDRV_DEGRADED: 2454 sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL; 2455 sc->sc_sensors[i].status = SENSOR_S_WARN; 2456 break; 2457 2458 case AMI_RDRV_OPTIMAL: 2459 sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE; 2460 sc->sc_sensors[i].status = SENSOR_S_OK; 2461 break; 2462 2463 default: 2464 sc->sc_sensors[i].value = 0; /* unknown */ 2465 sc->sc_sensors[i].status = SENSOR_S_UNKNOWN; 2466 } 2467 } 2468 } 2469 #endif /* SMALL_KERNEL */ 2470 #endif /* NBIO > 0 */ 2471 2472 #ifdef AMI_DEBUG 2473 void 2474 ami_print_mbox(struct ami_iocmd *mbox) 2475 { 2476 int i; 2477 2478 printf("acc_cmd: %d aac_id: %d acc_busy: %d acc_nstat: %d ", 2479 mbox->acc_cmd, mbox->acc_id, mbox->acc_busy, mbox->acc_nstat); 2480 printf("acc_status: %d acc_poll: %d acc_ack: %d\n", 2481 mbox->acc_status, mbox->acc_poll, mbox->acc_ack); 2482 2483 printf("acc_cmplidl: "); 2484 for (i = 0; i < AMI_MAXSTATACK; i++) { 2485 printf("[%d] = %d ", i, mbox->acc_cmplidl[i]); 2486 } 2487 2488 printf("\n"); 2489 } 2490 #endif /* AMI_DEBUG */ 2491