1/* $NetBSD: mly.c,v 1.56 2021/09/03 22:33:17 andvar Exp $ */ 2 3/*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran, Thor Lancelot Simon, and Eric Haszlakiewicz. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/*- 33 * Copyright (c) 2000, 2001 Michael Smith 34 * Copyright (c) 2000 BSDi 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 56 * SUCH DAMAGE. 57 * 58 * from FreeBSD: mly.c,v 1.8 2001/07/14 00:12:22 msmith Exp 59 */ 60 61/* 62 * Driver for the Mylex AcceleRAID and eXtremeRAID family with v6 firmware. 63 * 64 * TODO: 65 * 66 * o Make mly->mly_btl a hash, then MLY_BTL_RESCAN becomes a SIMPLEQ. 67 * o Handle FC and multiple LUNs. 68 * o Fix mmbox usage. 69 * o Fix transfer speed fudge. 70 */ 71 72#include <sys/cdefs.h> 73__KERNEL_RCSID(0, "$NetBSD: mly.c,v 1.56 2021/09/03 22:33:17 andvar Exp $"); 74 75#include <sys/param.h> 76#include <sys/systm.h> 77#include <sys/device.h> 78#include <sys/kernel.h> 79#include <sys/queue.h> 80#include <sys/buf.h> 81#include <sys/endian.h> 82#include <sys/conf.h> 83#include <sys/malloc.h> 84#include <sys/ioctl.h> 85#include <sys/scsiio.h> 86#include <sys/kthread.h> 87#include <sys/kauth.h> 88 89#include <sys/bus.h> 90 91#include <dev/scsipi/scsi_all.h> 92#include <dev/scsipi/scsipi_all.h> 93#include <dev/scsipi/scsiconf.h> 94 95#include <dev/pci/pcireg.h> 96#include <dev/pci/pcivar.h> 97#include <dev/pci/pcidevs.h> 98 99#include <dev/pci/mlyreg.h> 100#include <dev/pci/mlyio.h> 101#include <dev/pci/mlyvar.h> 102#include <dev/pci/mly_tables.h> 103 104static void mly_attach(device_t, device_t, void *); 105static int mly_match(device_t, cfdata_t, void *); 106static const struct mly_ident *mly_find_ident(struct pci_attach_args *); 107static int mly_fwhandshake(struct mly_softc *); 108static int mly_flush(struct mly_softc *); 109static int mly_intr(void *); 110static void mly_shutdown(void *); 111 112static int mly_alloc_ccbs(struct mly_softc *); 113static void mly_check_event(struct mly_softc *); 114static void mly_complete_event(struct mly_softc *, struct mly_ccb *); 115static void mly_complete_rescan(struct mly_softc *, struct mly_ccb *); 116static int mly_dmamem_alloc(struct mly_softc *, int, bus_dmamap_t *, 117 void **, bus_addr_t *, bus_dma_segment_t *); 118static void mly_dmamem_free(struct mly_softc *, int, bus_dmamap_t, 119 void *, bus_dma_segment_t *); 120static int mly_enable_mmbox(struct mly_softc *); 121static void mly_fetch_event(struct mly_softc *); 122static int mly_get_controllerinfo(struct mly_softc *); 123static int mly_get_eventstatus(struct mly_softc *); 124static int mly_ioctl(struct mly_softc *, struct mly_cmd_ioctl *, 125 void **, size_t, void *, size_t *); 126static void mly_padstr(char *, const char *, int); 127static void mly_process_event(struct mly_softc *, struct mly_event *); 128static void mly_release_ccbs(struct mly_softc *); 129static int mly_scan_btl(struct mly_softc *, int, int); 130static void mly_scan_channel(struct mly_softc *, int); 131static void mly_thread(void *); 132 133static int mly_ccb_alloc(struct mly_softc *, struct mly_ccb **); 134static void mly_ccb_complete(struct mly_softc *, struct mly_ccb *); 135static void mly_ccb_enqueue(struct mly_softc *, struct mly_ccb *); 136static void mly_ccb_free(struct mly_softc *, struct mly_ccb *); 137static int mly_ccb_map(struct mly_softc *, struct mly_ccb *); 138static int mly_ccb_poll(struct mly_softc *, struct mly_ccb *, int); 139static int mly_ccb_submit(struct mly_softc *, struct mly_ccb *); 140static void mly_ccb_unmap(struct mly_softc *, struct mly_ccb *); 141static int mly_ccb_wait(struct mly_softc *, struct mly_ccb *, int); 142 143static void mly_get_xfer_mode(struct mly_softc *, int, 144 struct scsipi_xfer_mode *); 145static void mly_scsipi_complete(struct mly_softc *, struct mly_ccb *); 146static int mly_scsipi_ioctl(struct scsipi_channel *, u_long, void *, 147 int, struct proc *); 148static void mly_scsipi_minphys(struct buf *); 149static void mly_scsipi_request(struct scsipi_channel *, 150 scsipi_adapter_req_t, void *); 151 152static int mly_user_command(struct mly_softc *, struct mly_user_command *); 153static int mly_user_health(struct mly_softc *, struct mly_user_health *); 154 155extern struct cfdriver mly_cd; 156 157CFATTACH_DECL_NEW(mly, sizeof(struct mly_softc), 158 mly_match, mly_attach, NULL, NULL); 159 160dev_type_open(mlyopen); 161dev_type_close(mlyclose); 162dev_type_ioctl(mlyioctl); 163 164const struct cdevsw mly_cdevsw = { 165 .d_open = mlyopen, 166 .d_close = mlyclose, 167 .d_read = noread, 168 .d_write = nowrite, 169 .d_ioctl = mlyioctl, 170 .d_stop = nostop, 171 .d_tty = notty, 172 .d_poll = nopoll, 173 .d_mmap = nommap, 174 .d_kqfilter = nokqfilter, 175 .d_discard = nodiscard, 176 .d_flag = D_OTHER 177}; 178 179static struct mly_ident { 180 u_short vendor; 181 u_short product; 182 u_short subvendor; 183 u_short subproduct; 184 int hwif; 185 const char *desc; 186} const mly_ident[] = { 187 { 188 PCI_VENDOR_MYLEX, 189 PCI_PRODUCT_MYLEX_EXTREMERAID, 190 PCI_VENDOR_MYLEX, 191 0x0040, 192 MLY_HWIF_STRONGARM, 193 "eXtremeRAID 2000" 194 }, 195 { 196 PCI_VENDOR_MYLEX, 197 PCI_PRODUCT_MYLEX_EXTREMERAID, 198 PCI_VENDOR_MYLEX, 199 0x0030, 200 MLY_HWIF_STRONGARM, 201 "eXtremeRAID 3000" 202 }, 203 { 204 PCI_VENDOR_MYLEX, 205 PCI_PRODUCT_MYLEX_ACCELERAID, 206 PCI_VENDOR_MYLEX, 207 0x0050, 208 MLY_HWIF_I960RX, 209 "AcceleRAID 352" 210 }, 211 { 212 PCI_VENDOR_MYLEX, 213 PCI_PRODUCT_MYLEX_ACCELERAID, 214 PCI_VENDOR_MYLEX, 215 0x0052, 216 MLY_HWIF_I960RX, 217 "AcceleRAID 170" 218 }, 219 { 220 PCI_VENDOR_MYLEX, 221 PCI_PRODUCT_MYLEX_ACCELERAID, 222 PCI_VENDOR_MYLEX, 223 0x0054, 224 MLY_HWIF_I960RX, 225 "AcceleRAID 160" 226 }, 227}; 228 229static void *mly_sdh; 230 231/* 232 * Try to find a `mly_ident' entry corresponding to this board. 233 */ 234static const struct mly_ident * 235mly_find_ident(struct pci_attach_args *pa) 236{ 237 const struct mly_ident *mpi, *maxmpi; 238 pcireg_t reg; 239 240 mpi = mly_ident; 241 maxmpi = mpi + sizeof(mly_ident) / sizeof(mly_ident[0]); 242 243 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_I2O) 244 return (NULL); 245 246 for (; mpi < maxmpi; mpi++) { 247 if (PCI_VENDOR(pa->pa_id) != mpi->vendor || 248 PCI_PRODUCT(pa->pa_id) != mpi->product) 249 continue; 250 251 if (mpi->subvendor == 0x0000) 252 return (mpi); 253 254 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 255 256 if (PCI_VENDOR(reg) == mpi->subvendor && 257 PCI_PRODUCT(reg) == mpi->subproduct) 258 return (mpi); 259 } 260 261 return (NULL); 262} 263 264/* 265 * Match a supported board. 266 */ 267static int 268mly_match(device_t parent, cfdata_t cfdata, void *aux) 269{ 270 271 return (mly_find_ident(aux) != NULL); 272} 273 274/* 275 * Attach a supported board. 276 */ 277static void 278mly_attach(device_t parent, device_t self, void *aux) 279{ 280 struct pci_attach_args *pa; 281 struct mly_softc *mly; 282 struct mly_ioctl_getcontrollerinfo *mi; 283 const struct mly_ident *ident; 284 pci_chipset_tag_t pc; 285 pci_intr_handle_t ih; 286 bus_space_handle_t memh, ioh; 287 bus_space_tag_t memt, iot; 288 pcireg_t reg; 289 const char *intrstr; 290 int ior, memr, i, rv, state; 291 struct scsipi_adapter *adapt; 292 struct scsipi_channel *chan; 293 char intrbuf[PCI_INTRSTR_LEN]; 294 295 mly = device_private(self); 296 mly->mly_dv = self; 297 pa = aux; 298 pc = pa->pa_pc; 299 ident = mly_find_ident(pa); 300 state = 0; 301 302 mly->mly_dmat = pa->pa_dmat; 303 mly->mly_hwif = ident->hwif; 304 305 printf(": Mylex %s\n", ident->desc); 306 307 /* 308 * Map the PCI register window. 309 */ 310 memr = -1; 311 ior = -1; 312 313 for (i = 0x10; i <= 0x14; i += 4) { 314 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, i); 315 316 if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) { 317 if (ior == -1 && PCI_MAPREG_IO_SIZE(reg) != 0) 318 ior = i; 319 } else { 320 if (memr == -1 && PCI_MAPREG_MEM_SIZE(reg) != 0) 321 memr = i; 322 } 323 } 324 325 if (memr != -1) 326 if (pci_mapreg_map(pa, memr, PCI_MAPREG_TYPE_MEM, 0, 327 &memt, &memh, NULL, NULL)) 328 memr = -1; 329 if (ior != -1) 330 if (pci_mapreg_map(pa, ior, PCI_MAPREG_TYPE_IO, 0, 331 &iot, &ioh, NULL, NULL)) 332 ior = -1; 333 334 if (memr != -1) { 335 mly->mly_iot = memt; 336 mly->mly_ioh = memh; 337 } else if (ior != -1) { 338 mly->mly_iot = iot; 339 mly->mly_ioh = ioh; 340 } else { 341 aprint_error_dev(self, "can't map i/o or memory space\n"); 342 return; 343 } 344 345 /* 346 * Enable the device. 347 */ 348 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 349 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 350 reg | PCI_COMMAND_MASTER_ENABLE); 351 352 /* 353 * Map and establish the interrupt. 354 */ 355 if (pci_intr_map(pa, &ih)) { 356 aprint_error_dev(self, "can't map interrupt\n"); 357 return; 358 } 359 intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); 360 mly->mly_ih = pci_intr_establish_xname(pc, ih, IPL_BIO, mly_intr, mly, 361 device_xname(self)); 362 if (mly->mly_ih == NULL) { 363 aprint_error_dev(self, "can't establish interrupt"); 364 if (intrstr != NULL) 365 aprint_error(" at %s", intrstr); 366 aprint_error("\n"); 367 return; 368 } 369 370 if (intrstr != NULL) 371 aprint_normal_dev(self, "interrupting at %s\n", intrstr); 372 373 /* 374 * Take care of interface-specific tasks. 375 */ 376 switch (mly->mly_hwif) { 377 case MLY_HWIF_I960RX: 378 mly->mly_doorbell_true = 0x00; 379 mly->mly_cmd_mailbox = MLY_I960RX_COMMAND_MAILBOX; 380 mly->mly_status_mailbox = MLY_I960RX_STATUS_MAILBOX; 381 mly->mly_idbr = MLY_I960RX_IDBR; 382 mly->mly_odbr = MLY_I960RX_ODBR; 383 mly->mly_error_status = MLY_I960RX_ERROR_STATUS; 384 mly->mly_interrupt_status = MLY_I960RX_INTERRUPT_STATUS; 385 mly->mly_interrupt_mask = MLY_I960RX_INTERRUPT_MASK; 386 break; 387 388 case MLY_HWIF_STRONGARM: 389 mly->mly_doorbell_true = 0xff; 390 mly->mly_cmd_mailbox = MLY_STRONGARM_COMMAND_MAILBOX; 391 mly->mly_status_mailbox = MLY_STRONGARM_STATUS_MAILBOX; 392 mly->mly_idbr = MLY_STRONGARM_IDBR; 393 mly->mly_odbr = MLY_STRONGARM_ODBR; 394 mly->mly_error_status = MLY_STRONGARM_ERROR_STATUS; 395 mly->mly_interrupt_status = MLY_STRONGARM_INTERRUPT_STATUS; 396 mly->mly_interrupt_mask = MLY_STRONGARM_INTERRUPT_MASK; 397 break; 398 } 399 400 /* 401 * Allocate and map the scatter/gather lists. 402 */ 403 rv = mly_dmamem_alloc(mly, MLY_SGL_SIZE * MLY_MAX_CCBS, 404 &mly->mly_sg_dmamap, (void **)&mly->mly_sg, 405 &mly->mly_sg_busaddr, &mly->mly_sg_seg); 406 if (rv) { 407 printf("%s: unable to allocate S/G maps\n", 408 device_xname(self)); 409 goto bad; 410 } 411 state++; 412 413 /* 414 * Allocate and map the memory mailbox. 415 */ 416 rv = mly_dmamem_alloc(mly, sizeof(struct mly_mmbox), 417 &mly->mly_mmbox_dmamap, (void **)&mly->mly_mmbox, 418 &mly->mly_mmbox_busaddr, &mly->mly_mmbox_seg); 419 if (rv) { 420 aprint_error_dev(self, "unable to allocate mailboxes\n"); 421 goto bad; 422 } 423 state++; 424 425 /* 426 * Initialise per-controller queues. 427 */ 428 SLIST_INIT(&mly->mly_ccb_free); 429 SIMPLEQ_INIT(&mly->mly_ccb_queue); 430 431 /* 432 * Disable interrupts before we start talking to the controller. 433 */ 434 mly_outb(mly, mly->mly_interrupt_mask, MLY_INTERRUPT_MASK_DISABLE); 435 436 /* 437 * Wait for the controller to come ready, handshaking with the 438 * firmware if required. This is typically only necessary on 439 * platforms where the controller BIOS does not run. 440 */ 441 if (mly_fwhandshake(mly)) { 442 aprint_error_dev(self, "unable to bring controller online\n"); 443 goto bad; 444 } 445 446 /* 447 * Allocate initial command buffers, obtain controller feature 448 * information, and then reallocate command buffers, since we'll 449 * know how many we want. 450 */ 451 if (mly_alloc_ccbs(mly)) { 452 aprint_error_dev(self, "unable to allocate CCBs\n"); 453 goto bad; 454 } 455 state++; 456 if (mly_get_controllerinfo(mly)) { 457 aprint_error_dev(self, "unable to retrieve controller info\n"); 458 goto bad; 459 } 460 mly_release_ccbs(mly); 461 if (mly_alloc_ccbs(mly)) { 462 aprint_error_dev(self, "unable to allocate CCBs\n"); 463 state--; 464 goto bad; 465 } 466 467 /* 468 * Get the current event counter for health purposes, populate the 469 * initial health status buffer. 470 */ 471 if (mly_get_eventstatus(mly)) { 472 aprint_error_dev(self, "unable to retrieve event status\n"); 473 goto bad; 474 } 475 476 /* 477 * Enable memory-mailbox mode. 478 */ 479 if (mly_enable_mmbox(mly)) { 480 aprint_error_dev(self, "unable to enable memory mailbox\n"); 481 goto bad; 482 } 483 484 /* 485 * Print a little information about the controller. 486 */ 487 mi = mly->mly_controllerinfo; 488 489 printf("%s: %d physical channel%s, firmware %d.%02d-%d-%02d " 490 "(%02d%02d%02d%02d), %dMB RAM\n", device_xname(self), 491 mi->physical_channels_present, 492 (mi->physical_channels_present) > 1 ? "s" : "", 493 mi->fw_major, mi->fw_minor, mi->fw_turn, mi->fw_build, 494 mi->fw_century, mi->fw_year, mi->fw_month, mi->fw_day, 495 le16toh(mi->memory_size)); 496 497 /* 498 * Register our `shutdownhook'. 499 */ 500 if (mly_sdh == NULL) 501 shutdownhook_establish(mly_shutdown, NULL); 502 503 /* 504 * Clear any previous BTL information. For each bus that scsipi 505 * wants to scan, we'll receive the SCBUSIOLLSCAN ioctl and retrieve 506 * all BTL info at that point. 507 */ 508 memset(&mly->mly_btl, 0, sizeof(mly->mly_btl)); 509 510 mly->mly_nchans = mly->mly_controllerinfo->physical_channels_present + 511 mly->mly_controllerinfo->virtual_channels_present; 512 513 /* 514 * Attach to scsipi. 515 */ 516 adapt = &mly->mly_adapt; 517 memset(adapt, 0, sizeof(*adapt)); 518 adapt->adapt_dev = self; 519 adapt->adapt_nchannels = mly->mly_nchans; 520 adapt->adapt_openings = mly->mly_ncmds - MLY_CCBS_RESV; 521 adapt->adapt_max_periph = mly->mly_ncmds - MLY_CCBS_RESV; 522 adapt->adapt_request = mly_scsipi_request; 523 adapt->adapt_minphys = mly_scsipi_minphys; 524 adapt->adapt_ioctl = mly_scsipi_ioctl; 525 526 for (i = 0; i < mly->mly_nchans; i++) { 527 chan = &mly->mly_chans[i]; 528 memset(chan, 0, sizeof(*chan)); 529 chan->chan_adapter = adapt; 530 chan->chan_bustype = &scsi_bustype; 531 chan->chan_channel = i; 532 chan->chan_ntargets = MLY_MAX_TARGETS; 533 chan->chan_nluns = MLY_MAX_LUNS; 534 chan->chan_id = mly->mly_controllerparam->initiator_id; 535 chan->chan_flags = SCSIPI_CHAN_NOSETTLE; 536 config_found(self, chan, scsiprint, CFARGS_NONE); 537 } 538 539 /* 540 * Now enable interrupts... 541 */ 542 mly_outb(mly, mly->mly_interrupt_mask, MLY_INTERRUPT_MASK_ENABLE); 543 544 /* 545 * Finally, create our monitoring thread. 546 */ 547 mly->mly_state |= MLY_STATE_INITOK; 548 rv = kthread_create(PRI_NONE, 0, NULL, mly_thread, mly, 549 &mly->mly_thread, "%s", device_xname(self)); 550 if (rv != 0) 551 aprint_error_dev(self, "unable to create thread (%d)\n", rv); 552 return; 553 554 bad: 555 if (state > 2) 556 mly_release_ccbs(mly); 557 if (state > 1) 558 mly_dmamem_free(mly, sizeof(struct mly_mmbox), 559 mly->mly_mmbox_dmamap, (void *)mly->mly_mmbox, 560 &mly->mly_mmbox_seg); 561 if (state > 0) 562 mly_dmamem_free(mly, MLY_SGL_SIZE * MLY_MAX_CCBS, 563 mly->mly_sg_dmamap, (void *)mly->mly_sg, 564 &mly->mly_sg_seg); 565} 566 567/* 568 * Scan all possible devices on the specified channel. 569 */ 570static void 571mly_scan_channel(struct mly_softc *mly, int bus) 572{ 573 int s, target; 574 575 for (target = 0; target < MLY_MAX_TARGETS; target++) { 576 s = splbio(); 577 if (!mly_scan_btl(mly, bus, target)) { 578 tsleep(&mly->mly_btl[bus][target], PRIBIO, "mlyscan", 579 0); 580 } 581 splx(s); 582 } 583} 584 585/* 586 * Shut down all configured `mly' devices. 587 */ 588static void 589mly_shutdown(void *cookie) 590{ 591 struct mly_softc *mly; 592 int i; 593 594 for (i = 0; i < mly_cd.cd_ndevs; i++) { 595 if ((mly = device_lookup_private(&mly_cd, i)) == NULL) 596 continue; 597 598 if (mly_flush(mly)) 599 aprint_error_dev(mly->mly_dv, "unable to flush cache\n"); 600 } 601} 602 603/* 604 * Fill in the mly_controllerinfo and mly_controllerparam fields in the 605 * softc. 606 */ 607static int 608mly_get_controllerinfo(struct mly_softc *mly) 609{ 610 struct mly_cmd_ioctl mci; 611 int rv; 612 613 /* 614 * Build the getcontrollerinfo ioctl and send it. 615 */ 616 memset(&mci, 0, sizeof(mci)); 617 mci.sub_ioctl = MDACIOCTL_GETCONTROLLERINFO; 618 rv = mly_ioctl(mly, &mci, (void **)&mly->mly_controllerinfo, 619 sizeof(*mly->mly_controllerinfo), NULL, NULL); 620 if (rv != 0) 621 return (rv); 622 623 /* 624 * Build the getcontrollerparameter ioctl and send it. 625 */ 626 memset(&mci, 0, sizeof(mci)); 627 mci.sub_ioctl = MDACIOCTL_GETCONTROLLERPARAMETER; 628 rv = mly_ioctl(mly, &mci, (void **)&mly->mly_controllerparam, 629 sizeof(*mly->mly_controllerparam), NULL, NULL); 630 631 return (rv); 632} 633 634/* 635 * Rescan a device, possibly as a consequence of getting an event which 636 * suggests that it may have changed. Must be called with interrupts 637 * blocked. 638 */ 639static int 640mly_scan_btl(struct mly_softc *mly, int bus, int target) 641{ 642 struct mly_ccb *mc; 643 struct mly_cmd_ioctl *mci; 644 int rv; 645 646 if (target == mly->mly_controllerparam->initiator_id) { 647 mly->mly_btl[bus][target].mb_flags = MLY_BTL_PROTECTED; 648 return (EIO); 649 } 650 651 /* Don't re-scan if a scan is already in progress. */ 652 if ((mly->mly_btl[bus][target].mb_flags & MLY_BTL_SCANNING) != 0) 653 return (EBUSY); 654 655 /* Get a command. */ 656 if ((rv = mly_ccb_alloc(mly, &mc)) != 0) 657 return (rv); 658 659 /* Set up the data buffer. */ 660 mc->mc_data = malloc(sizeof(union mly_devinfo), 661 M_DEVBUF, M_NOWAIT|M_ZERO); 662 663 mc->mc_flags |= MLY_CCB_DATAIN; 664 mc->mc_complete = mly_complete_rescan; 665 666 /* 667 * Build the ioctl. 668 */ 669 mci = (struct mly_cmd_ioctl *)&mc->mc_packet->ioctl; 670 mci->opcode = MDACMD_IOCTL; 671 mci->timeout = 30 | MLY_TIMEOUT_SECONDS; 672 memset(&mci->param, 0, sizeof(mci->param)); 673 674 if (MLY_BUS_IS_VIRTUAL(mly, bus)) { 675 mc->mc_length = sizeof(struct mly_ioctl_getlogdevinfovalid); 676 mci->data_size = htole32(mc->mc_length); 677 mci->sub_ioctl = MDACIOCTL_GETLOGDEVINFOVALID; 678 _lto3l(MLY_LOGADDR(0, MLY_LOGDEV_ID(mly, bus, target)), 679 mci->addr); 680 } else { 681 mc->mc_length = sizeof(struct mly_ioctl_getphysdevinfovalid); 682 mci->data_size = htole32(mc->mc_length); 683 mci->sub_ioctl = MDACIOCTL_GETPHYSDEVINFOVALID; 684 _lto3l(MLY_PHYADDR(0, bus, target, 0), mci->addr); 685 } 686 687 /* 688 * Dispatch the command. 689 */ 690 if ((rv = mly_ccb_map(mly, mc)) != 0) { 691 free(mc->mc_data, M_DEVBUF); 692 mly_ccb_free(mly, mc); 693 return(rv); 694 } 695 696 mly->mly_btl[bus][target].mb_flags |= MLY_BTL_SCANNING; 697 mly_ccb_enqueue(mly, mc); 698 return (0); 699} 700 701/* 702 * Handle the completion of a rescan operation. 703 */ 704static void 705mly_complete_rescan(struct mly_softc *mly, struct mly_ccb *mc) 706{ 707 struct mly_ioctl_getlogdevinfovalid *ldi; 708 struct mly_ioctl_getphysdevinfovalid *pdi; 709 struct mly_cmd_ioctl *mci; 710 struct mly_btl btl, *btlp; 711 struct scsipi_xfer_mode xm; 712 int bus, target, rescan; 713 u_int tmp; 714 715 mly_ccb_unmap(mly, mc); 716 717 /* 718 * Recover the bus and target from the command. We need these even 719 * in the case where we don't have a useful response. 720 */ 721 mci = (struct mly_cmd_ioctl *)&mc->mc_packet->ioctl; 722 tmp = _3ltol(mci->addr); 723 rescan = 0; 724 725 if (mci->sub_ioctl == MDACIOCTL_GETLOGDEVINFOVALID) { 726 bus = MLY_LOGDEV_BUS(mly, MLY_LOGADDR_DEV(tmp)); 727 target = MLY_LOGDEV_TARGET(mly, MLY_LOGADDR_DEV(tmp)); 728 } else { 729 bus = MLY_PHYADDR_CHANNEL(tmp); 730 target = MLY_PHYADDR_TARGET(tmp); 731 } 732 733 btlp = &mly->mly_btl[bus][target]; 734 735 /* The default result is 'no device'. */ 736 memset(&btl, 0, sizeof(btl)); 737 btl.mb_flags = MLY_BTL_PROTECTED; 738 739 /* If the rescan completed OK, we have possibly-new BTL data. */ 740 if (mc->mc_status != 0) 741 goto out; 742 743 if (mc->mc_length == sizeof(*ldi)) { 744 ldi = (struct mly_ioctl_getlogdevinfovalid *)mc->mc_data; 745 tmp = le32toh(ldi->logical_device_number); 746 747 if (MLY_LOGDEV_BUS(mly, tmp) != bus || 748 MLY_LOGDEV_TARGET(mly, tmp) != target) { 749#ifdef MLYDEBUG 750 printf("%s: WARNING: BTL rescan (logical) for %d:%d " 751 "returned data for %d:%d instead\n", 752 device_xname(mly->mly_dv), bus, target, 753 MLY_LOGDEV_BUS(mly, tmp), 754 MLY_LOGDEV_TARGET(mly, tmp)); 755#endif 756 goto out; 757 } 758 759 btl.mb_flags = MLY_BTL_LOGICAL | MLY_BTL_TQING; 760 btl.mb_type = ldi->raid_level; 761 btl.mb_state = ldi->state; 762 } else if (mc->mc_length == sizeof(*pdi)) { 763 pdi = (struct mly_ioctl_getphysdevinfovalid *)mc->mc_data; 764 765 if (pdi->channel != bus || pdi->target != target) { 766#ifdef MLYDEBUG 767 printf("%s: WARNING: BTL rescan (physical) for %d:%d " 768 " returned data for %d:%d instead\n", 769 device_xname(mly->mly_dv), 770 bus, target, pdi->channel, pdi->target); 771#endif 772 goto out; 773 } 774 775 btl.mb_flags = MLY_BTL_PHYSICAL; 776 btl.mb_type = MLY_DEVICE_TYPE_PHYSICAL; 777 btl.mb_state = pdi->state; 778 btl.mb_speed = pdi->speed; 779 btl.mb_width = pdi->width; 780 781 if (pdi->state != MLY_DEVICE_STATE_UNCONFIGURED) 782 btl.mb_flags |= MLY_BTL_PROTECTED; 783 if (pdi->command_tags != 0) 784 btl.mb_flags |= MLY_BTL_TQING; 785 } else { 786 printf("%s: BTL rescan result invalid\n", device_xname(mly->mly_dv)); 787 goto out; 788 } 789 790 /* Decide whether we need to rescan the device. */ 791 if (btl.mb_flags != btlp->mb_flags || 792 btl.mb_speed != btlp->mb_speed || 793 btl.mb_width != btlp->mb_width) 794 rescan = 1; 795 796 out: 797 *btlp = btl; 798 799 if (rescan && (btl.mb_flags & MLY_BTL_PROTECTED) == 0) { 800 xm.xm_target = target; 801 mly_get_xfer_mode(mly, bus, &xm); 802 /* XXX SCSI mid-layer rescan goes here. */ 803 } 804 805 /* Wake anybody waiting on the device to be rescanned. */ 806 wakeup(btlp); 807 808 free(mc->mc_data, M_DEVBUF); 809 mly_ccb_free(mly, mc); 810} 811 812/* 813 * Get the current health status and set the 'next event' counter to suit. 814 */ 815static int 816mly_get_eventstatus(struct mly_softc *mly) 817{ 818 struct mly_cmd_ioctl mci; 819 struct mly_health_status *mh; 820 int rv; 821 822 /* Build the gethealthstatus ioctl and send it. */ 823 memset(&mci, 0, sizeof(mci)); 824 mh = NULL; 825 mci.sub_ioctl = MDACIOCTL_GETHEALTHSTATUS; 826 827 rv = mly_ioctl(mly, &mci, (void *)&mh, sizeof(*mh), NULL, NULL); 828 if (rv) 829 return (rv); 830 831 /* Get the event counter. */ 832 mly->mly_event_change = le32toh(mh->change_counter); 833 mly->mly_event_waiting = le32toh(mh->next_event); 834 mly->mly_event_counter = le32toh(mh->next_event); 835 836 /* Save the health status into the memory mailbox */ 837 memcpy(&mly->mly_mmbox->mmm_health.status, mh, sizeof(*mh)); 838 839 bus_dmamap_sync(mly->mly_dmat, mly->mly_mmbox_dmamap, 840 offsetof(struct mly_mmbox, mmm_health), 841 sizeof(mly->mly_mmbox->mmm_health), 842 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 843 844 free(mh, M_DEVBUF); 845 return (0); 846} 847 848/* 849 * Enable memory mailbox mode. 850 */ 851static int 852mly_enable_mmbox(struct mly_softc *mly) 853{ 854 struct mly_cmd_ioctl mci; 855 u_int8_t *sp; 856 u_int64_t tmp; 857 int rv; 858 859 /* Build the ioctl and send it. */ 860 memset(&mci, 0, sizeof(mci)); 861 mci.sub_ioctl = MDACIOCTL_SETMEMORYMAILBOX; 862 863 /* Set buffer addresses. */ 864 tmp = mly->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_command); 865 mci.param.setmemorymailbox.command_mailbox_physaddr = htole64(tmp); 866 867 tmp = mly->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_status); 868 mci.param.setmemorymailbox.status_mailbox_physaddr = htole64(tmp); 869 870 tmp = mly->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_health); 871 mci.param.setmemorymailbox.health_buffer_physaddr = htole64(tmp); 872 873 /* Set buffer sizes - abuse of data_size field is revolting. */ 874 sp = (u_int8_t *)&mci.data_size; 875 sp[0] = (sizeof(union mly_cmd_packet) * MLY_MMBOX_COMMANDS) >> 10; 876 sp[1] = (sizeof(union mly_status_packet) * MLY_MMBOX_STATUS) >> 10; 877 mci.param.setmemorymailbox.health_buffer_size = 878 sizeof(union mly_health_region) >> 10; 879 880 rv = mly_ioctl(mly, &mci, NULL, 0, NULL, NULL); 881 if (rv) 882 return (rv); 883 884 mly->mly_state |= MLY_STATE_MMBOX_ACTIVE; 885 return (0); 886} 887 888/* 889 * Flush all pending I/O from the controller. 890 */ 891static int 892mly_flush(struct mly_softc *mly) 893{ 894 struct mly_cmd_ioctl mci; 895 896 /* Build the ioctl */ 897 memset(&mci, 0, sizeof(mci)); 898 mci.sub_ioctl = MDACIOCTL_FLUSHDEVICEDATA; 899 mci.param.deviceoperation.operation_device = 900 MLY_OPDEVICE_PHYSICAL_CONTROLLER; 901 902 /* Pass it off to the controller */ 903 return (mly_ioctl(mly, &mci, NULL, 0, NULL, NULL)); 904} 905 906/* 907 * Perform an ioctl command. 908 * 909 * If (data) is not NULL, the command requires data transfer to the 910 * controller. If (*data) is NULL the command requires data transfer from 911 * the controller, and we will allocate a buffer for it. 912 */ 913static int 914mly_ioctl(struct mly_softc *mly, struct mly_cmd_ioctl *ioctl, void **data, 915 size_t datasize, void *sense_buffer, 916 size_t *sense_length) 917{ 918 struct mly_ccb *mc; 919 struct mly_cmd_ioctl *mci; 920 u_int8_t status; 921 int rv; 922 923 mc = NULL; 924 if ((rv = mly_ccb_alloc(mly, &mc)) != 0) 925 goto bad; 926 927 /* 928 * Copy the ioctl structure, but save some important fields and then 929 * fixup. 930 */ 931 mci = &mc->mc_packet->ioctl; 932 ioctl->sense_buffer_address = htole64(mci->sense_buffer_address); 933 ioctl->maximum_sense_size = mci->maximum_sense_size; 934 *mci = *ioctl; 935 mci->opcode = MDACMD_IOCTL; 936 mci->timeout = 30 | MLY_TIMEOUT_SECONDS; 937 938 /* Handle the data buffer. */ 939 if (data != NULL) { 940 if (*data == NULL) { 941 /* Allocate data buffer */ 942 mc->mc_data = malloc(datasize, M_DEVBUF, M_NOWAIT); 943 mc->mc_flags |= MLY_CCB_DATAIN; 944 } else { 945 mc->mc_data = *data; 946 mc->mc_flags |= MLY_CCB_DATAOUT; 947 } 948 mc->mc_length = datasize; 949 mc->mc_packet->generic.data_size = htole32(datasize); 950 } 951 952 /* Run the command. */ 953 if (datasize > 0) 954 if ((rv = mly_ccb_map(mly, mc)) != 0) 955 goto bad; 956 rv = mly_ccb_poll(mly, mc, 30000); 957 if (datasize > 0) 958 mly_ccb_unmap(mly, mc); 959 if (rv != 0) 960 goto bad; 961 962 /* Clean up and return any data. */ 963 status = mc->mc_status; 964 965 if (status != 0) 966 printf("mly_ioctl: command status %d\n", status); 967 968 if (mc->mc_sense > 0 && sense_buffer != NULL) { 969 memcpy(sense_buffer, mc->mc_packet, mc->mc_sense); 970 *sense_length = mc->mc_sense; 971 goto bad; 972 } 973 974 /* Should we return a data pointer? */ 975 if (data != NULL && *data == NULL) 976 *data = mc->mc_data; 977 978 /* Command completed OK. */ 979 rv = (status != 0 ? EIO : 0); 980 981 bad: 982 if (mc != NULL) { 983 /* Do we need to free a data buffer we allocated? */ 984 if (rv != 0 && mc->mc_data != NULL && 985 (data == NULL || *data == NULL)) 986 free(mc->mc_data, M_DEVBUF); 987 mly_ccb_free(mly, mc); 988 } 989 990 return (rv); 991} 992 993/* 994 * Check for event(s) outstanding in the controller. 995 */ 996static void 997mly_check_event(struct mly_softc *mly) 998{ 999 1000 bus_dmamap_sync(mly->mly_dmat, mly->mly_mmbox_dmamap, 1001 offsetof(struct mly_mmbox, mmm_health), 1002 sizeof(mly->mly_mmbox->mmm_health), 1003 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1004 1005 /* 1006 * The controller may have updated the health status information, so 1007 * check for it here. Note that the counters are all in host 1008 * memory, so this check is very cheap. Also note that we depend on 1009 * checking on completion 1010 */ 1011 if (le32toh(mly->mly_mmbox->mmm_health.status.change_counter) != 1012 mly->mly_event_change) { 1013 mly->mly_event_change = 1014 le32toh(mly->mly_mmbox->mmm_health.status.change_counter); 1015 mly->mly_event_waiting = 1016 le32toh(mly->mly_mmbox->mmm_health.status.next_event); 1017 1018 /* Wake up anyone that might be interested in this. */ 1019 wakeup(&mly->mly_event_change); 1020 } 1021 1022 bus_dmamap_sync(mly->mly_dmat, mly->mly_mmbox_dmamap, 1023 offsetof(struct mly_mmbox, mmm_health), 1024 sizeof(mly->mly_mmbox->mmm_health), 1025 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1026 1027 if (mly->mly_event_counter != mly->mly_event_waiting) 1028 mly_fetch_event(mly); 1029} 1030 1031/* 1032 * Fetch one event from the controller. If we fail due to resource 1033 * starvation, we'll be retried the next time a command completes. 1034 */ 1035static void 1036mly_fetch_event(struct mly_softc *mly) 1037{ 1038 struct mly_ccb *mc; 1039 struct mly_cmd_ioctl *mci; 1040 int s; 1041 u_int32_t event; 1042 1043 /* Get a command. */ 1044 if (mly_ccb_alloc(mly, &mc)) 1045 return; 1046 1047 /* Set up the data buffer. */ 1048 mc->mc_data = malloc(sizeof(struct mly_event), M_DEVBUF, 1049 M_NOWAIT|M_ZERO); 1050 1051 mc->mc_length = sizeof(struct mly_event); 1052 mc->mc_flags |= MLY_CCB_DATAIN; 1053 mc->mc_complete = mly_complete_event; 1054 1055 /* 1056 * Get an event number to fetch. It's possible that we've raced 1057 * with another context for the last event, in which case there will 1058 * be no more events. 1059 */ 1060 s = splbio(); 1061 if (mly->mly_event_counter == mly->mly_event_waiting) { 1062 splx(s); 1063 free(mc->mc_data, M_DEVBUF); 1064 mly_ccb_free(mly, mc); 1065 return; 1066 } 1067 event = mly->mly_event_counter++; 1068 splx(s); 1069 1070 /* 1071 * Build the ioctl. 1072 * 1073 * At this point we are committed to sending this request, as it 1074 * will be the only one constructed for this particular event 1075 * number. 1076 */ 1077 mci = (struct mly_cmd_ioctl *)&mc->mc_packet->ioctl; 1078 mci->opcode = MDACMD_IOCTL; 1079 mci->data_size = htole32(sizeof(struct mly_event)); 1080 _lto3l(MLY_PHYADDR(0, 0, (event >> 16) & 0xff, (event >> 24) & 0xff), 1081 mci->addr); 1082 mci->timeout = 30 | MLY_TIMEOUT_SECONDS; 1083 mci->sub_ioctl = MDACIOCTL_GETEVENT; 1084 mci->param.getevent.sequence_number_low = htole16(event & 0xffff); 1085 1086 /* 1087 * Submit the command. 1088 */ 1089 if (mly_ccb_map(mly, mc) != 0) 1090 goto bad; 1091 mly_ccb_enqueue(mly, mc); 1092 return; 1093 1094 bad: 1095 printf("%s: couldn't fetch event %u\n", device_xname(mly->mly_dv), event); 1096 free(mc->mc_data, M_DEVBUF); 1097 mly_ccb_free(mly, mc); 1098} 1099 1100/* 1101 * Handle the completion of an event poll. 1102 */ 1103static void 1104mly_complete_event(struct mly_softc *mly, struct mly_ccb *mc) 1105{ 1106 struct mly_event *me; 1107 1108 me = (struct mly_event *)mc->mc_data; 1109 mly_ccb_unmap(mly, mc); 1110 mly_ccb_free(mly, mc); 1111 1112 /* If the event was successfully fetched, process it. */ 1113 if (mc->mc_status == SCSI_OK) 1114 mly_process_event(mly, me); 1115 else 1116 aprint_error_dev(mly->mly_dv, "unable to fetch event; status = 0x%x\n", 1117 mc->mc_status); 1118 1119 free(me, M_DEVBUF); 1120 1121 /* Check for another event. */ 1122 mly_check_event(mly); 1123} 1124 1125/* 1126 * Process a controller event. Called with interrupts blocked (i.e., at 1127 * interrupt time). 1128 */ 1129static void 1130mly_process_event(struct mly_softc *mly, struct mly_event *me) 1131{ 1132 struct scsi_sense_data *ssd; 1133 int bus, target, event, class, action; 1134 const char *fp, *tp; 1135 1136 ssd = (struct scsi_sense_data *)&me->sense[0]; 1137 1138 /* 1139 * Errors can be reported using vendor-unique sense data. In this 1140 * case, the event code will be 0x1c (Request sense data present), 1141 * the sense key will be 0x09 (vendor specific), the MSB of the ASC 1142 * will be set, and the actual event code will be a 16-bit value 1143 * comprised of the ASCQ (low byte) and low seven bits of the ASC 1144 * (low seven bits of the high byte). 1145 */ 1146 if (le32toh(me->code) == 0x1c && 1147 SSD_SENSE_KEY(ssd->flags) == SKEY_VENDOR_SPECIFIC && 1148 (ssd->asc & 0x80) != 0) { 1149 event = ((int)(ssd->asc & ~0x80) << 8) + 1150 ssd->ascq; 1151 } else 1152 event = le32toh(me->code); 1153 1154 /* Look up event, get codes. */ 1155 fp = mly_describe_code(mly_table_event, event); 1156 1157 /* Quiet event? */ 1158 class = fp[0]; 1159#ifdef notyet 1160 if (isupper(class) && bootverbose) 1161 class = tolower(class); 1162#endif 1163 1164 /* Get action code, text string. */ 1165 action = fp[1]; 1166 tp = fp + 3; 1167 1168 /* 1169 * Print some information about the event. 1170 * 1171 * This code uses a table derived from the corresponding portion of 1172 * the Linux driver, and thus the parser is very similar. 1173 */ 1174 switch (class) { 1175 case 'p': 1176 /* 1177 * Error on physical drive. 1178 */ 1179 printf("%s: physical device %d:%d %s\n", device_xname(mly->mly_dv), 1180 me->channel, me->target, tp); 1181 if (action == 'r') 1182 mly->mly_btl[me->channel][me->target].mb_flags |= 1183 MLY_BTL_RESCAN; 1184 break; 1185 1186 case 'l': 1187 case 'm': 1188 /* 1189 * Error on logical unit, or message about logical unit. 1190 */ 1191 bus = MLY_LOGDEV_BUS(mly, me->lun); 1192 target = MLY_LOGDEV_TARGET(mly, me->lun); 1193 printf("%s: logical device %d:%d %s\n", device_xname(mly->mly_dv), 1194 bus, target, tp); 1195 if (action == 'r') 1196 mly->mly_btl[bus][target].mb_flags |= MLY_BTL_RESCAN; 1197 break; 1198 1199 case 's': 1200 /* 1201 * Report of sense data. 1202 */ 1203 if ((SSD_SENSE_KEY(ssd->flags) == SKEY_NO_SENSE || 1204 SSD_SENSE_KEY(ssd->flags) == SKEY_NOT_READY) && 1205 ssd->asc == 0x04 && 1206 (ssd->ascq == 0x01 || 1207 ssd->ascq == 0x02)) { 1208 /* Ignore NO_SENSE or NOT_READY in one case */ 1209 break; 1210 } 1211 1212 /* 1213 * XXX Should translate this if SCSIVERBOSE. 1214 */ 1215 printf("%s: physical device %d:%d %s\n", device_xname(mly->mly_dv), 1216 me->channel, me->target, tp); 1217 printf("%s: sense key %d asc %02x ascq %02x\n", 1218 device_xname(mly->mly_dv), SSD_SENSE_KEY(ssd->flags), 1219 ssd->asc, ssd->ascq); 1220 printf("%s: info %x%x%x%x csi %x%x%x%x\n", 1221 device_xname(mly->mly_dv), ssd->info[0], ssd->info[1], 1222 ssd->info[2], ssd->info[3], ssd->csi[0], 1223 ssd->csi[1], ssd->csi[2], 1224 ssd->csi[3]); 1225 if (action == 'r') 1226 mly->mly_btl[me->channel][me->target].mb_flags |= 1227 MLY_BTL_RESCAN; 1228 break; 1229 1230 case 'e': 1231 printf("%s: ", device_xname(mly->mly_dv)); 1232 printf(tp, me->target, me->lun); 1233 break; 1234 1235 case 'c': 1236 printf("%s: controller %s\n", device_xname(mly->mly_dv), tp); 1237 break; 1238 1239 case '?': 1240 printf("%s: %s - %d\n", device_xname(mly->mly_dv), tp, event); 1241 break; 1242 1243 default: 1244 /* Probably a 'noisy' event being ignored. */ 1245 break; 1246 } 1247} 1248 1249/* 1250 * Perform periodic activities. 1251 */ 1252static void 1253mly_thread(void *cookie) 1254{ 1255 struct mly_softc *mly; 1256 struct mly_btl *btl; 1257 int s, bus, target, done; 1258 1259 mly = (struct mly_softc *)cookie; 1260 1261 for (;;) { 1262 /* Check for new events. */ 1263 mly_check_event(mly); 1264 1265 /* Re-scan up to 1 device. */ 1266 s = splbio(); 1267 done = 0; 1268 for (bus = 0; bus < mly->mly_nchans && !done; bus++) { 1269 for (target = 0; target < MLY_MAX_TARGETS; target++) { 1270 /* Perform device rescan? */ 1271 btl = &mly->mly_btl[bus][target]; 1272 if ((btl->mb_flags & MLY_BTL_RESCAN) != 0) { 1273 btl->mb_flags ^= MLY_BTL_RESCAN; 1274 mly_scan_btl(mly, bus, target); 1275 done = 1; 1276 break; 1277 } 1278 } 1279 } 1280 splx(s); 1281 1282 /* Sleep for N seconds. */ 1283 tsleep(mly_thread, PWAIT, "mlyzzz", 1284 hz * MLY_PERIODIC_INTERVAL); 1285 } 1286} 1287 1288/* 1289 * Submit a command to the controller and poll on completion. Return 1290 * non-zero on timeout. 1291 */ 1292static int 1293mly_ccb_poll(struct mly_softc *mly, struct mly_ccb *mc, int timo) 1294{ 1295 int rv; 1296 1297 if ((rv = mly_ccb_submit(mly, mc)) != 0) 1298 return (rv); 1299 1300 for (timo *= 10; timo != 0; timo--) { 1301 if ((mc->mc_flags & MLY_CCB_COMPLETE) != 0) 1302 break; 1303 mly_intr(mly); 1304 DELAY(100); 1305 } 1306 1307 return (timo == 0); 1308} 1309 1310/* 1311 * Submit a command to the controller and sleep on completion. Return 1312 * non-zero on timeout. 1313 */ 1314static int 1315mly_ccb_wait(struct mly_softc *mly, struct mly_ccb *mc, int timo) 1316{ 1317 int rv, s; 1318 1319 mly_ccb_enqueue(mly, mc); 1320 1321 s = splbio(); 1322 if ((mc->mc_flags & MLY_CCB_COMPLETE) != 0) { 1323 splx(s); 1324 return (0); 1325 } 1326 rv = tsleep(mc, PRIBIO, "mlywccb", timo * hz / 1000); 1327 splx(s); 1328 1329 return (rv); 1330} 1331 1332/* 1333 * If a CCB is specified, enqueue it. Pull CCBs off the software queue in 1334 * the order that they were enqueued and try to submit their command blocks 1335 * to the controller for execution. 1336 */ 1337void 1338mly_ccb_enqueue(struct mly_softc *mly, struct mly_ccb *mc) 1339{ 1340 int s; 1341 1342 s = splbio(); 1343 1344 if (mc != NULL) 1345 SIMPLEQ_INSERT_TAIL(&mly->mly_ccb_queue, mc, mc_link.simpleq); 1346 1347 while ((mc = SIMPLEQ_FIRST(&mly->mly_ccb_queue)) != NULL) { 1348 if (mly_ccb_submit(mly, mc)) 1349 break; 1350 SIMPLEQ_REMOVE_HEAD(&mly->mly_ccb_queue, mc_link.simpleq); 1351 } 1352 1353 splx(s); 1354} 1355 1356/* 1357 * Deliver a command to the controller. 1358 */ 1359static int 1360mly_ccb_submit(struct mly_softc *mly, struct mly_ccb *mc) 1361{ 1362 union mly_cmd_packet *pkt; 1363 int s, off; 1364 1365 mc->mc_packet->generic.command_id = htole16(mc->mc_slot); 1366 1367 bus_dmamap_sync(mly->mly_dmat, mly->mly_pkt_dmamap, 1368 mc->mc_packetphys - mly->mly_pkt_busaddr, 1369 sizeof(union mly_cmd_packet), 1370 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1371 1372 s = splbio(); 1373 1374 /* 1375 * Do we have to use the hardware mailbox? 1376 */ 1377 if ((mly->mly_state & MLY_STATE_MMBOX_ACTIVE) == 0) { 1378 /* 1379 * Check to see if the controller is ready for us. 1380 */ 1381 if (mly_idbr_true(mly, MLY_HM_CMDSENT)) { 1382 splx(s); 1383 return (EBUSY); 1384 } 1385 1386 /* 1387 * It's ready, send the command. 1388 */ 1389 mly_outl(mly, mly->mly_cmd_mailbox, 1390 (u_int64_t)mc->mc_packetphys & 0xffffffff); 1391 mly_outl(mly, mly->mly_cmd_mailbox + 4, 1392 (u_int64_t)mc->mc_packetphys >> 32); 1393 mly_outb(mly, mly->mly_idbr, MLY_HM_CMDSENT); 1394 } else { 1395 pkt = &mly->mly_mmbox->mmm_command[mly->mly_mmbox_cmd_idx]; 1396 off = (char *)pkt - (char *)mly->mly_mmbox; 1397 1398 bus_dmamap_sync(mly->mly_dmat, mly->mly_mmbox_dmamap, 1399 off, sizeof(mly->mly_mmbox->mmm_command[0]), 1400 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1401 1402 /* Check to see if the next index is free yet. */ 1403 if (pkt->mmbox.flag != 0) { 1404 splx(s); 1405 return (EBUSY); 1406 } 1407 1408 /* Copy in new command */ 1409 memcpy(pkt->mmbox.data, mc->mc_packet->mmbox.data, 1410 sizeof(pkt->mmbox.data)); 1411 1412 /* Copy flag last. */ 1413 pkt->mmbox.flag = mc->mc_packet->mmbox.flag; 1414 1415 bus_dmamap_sync(mly->mly_dmat, mly->mly_mmbox_dmamap, 1416 off, sizeof(mly->mly_mmbox->mmm_command[0]), 1417 BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 1418 1419 /* Signal controller and update index. */ 1420 mly_outb(mly, mly->mly_idbr, MLY_AM_CMDSENT); 1421 mly->mly_mmbox_cmd_idx = 1422 (mly->mly_mmbox_cmd_idx + 1) % MLY_MMBOX_COMMANDS; 1423 } 1424 1425 splx(s); 1426 return (0); 1427} 1428 1429/* 1430 * Pick up completed commands from the controller and handle accordingly. 1431 */ 1432int 1433mly_intr(void *cookie) 1434{ 1435 struct mly_ccb *mc; 1436 union mly_status_packet *sp; 1437 u_int16_t slot; 1438 int forus, off; 1439 struct mly_softc *mly; 1440 1441 mly = cookie; 1442 forus = 0; 1443 1444 /* 1445 * Pick up hardware-mailbox commands. 1446 */ 1447 if (mly_odbr_true(mly, MLY_HM_STSREADY)) { 1448 slot = mly_inw(mly, mly->mly_status_mailbox); 1449 1450 if (slot < MLY_SLOT_MAX) { 1451 mc = mly->mly_ccbs + (slot - MLY_SLOT_START); 1452 mc->mc_status = 1453 mly_inb(mly, mly->mly_status_mailbox + 2); 1454 mc->mc_sense = 1455 mly_inb(mly, mly->mly_status_mailbox + 3); 1456 mc->mc_resid = 1457 mly_inl(mly, mly->mly_status_mailbox + 4); 1458 1459 mly_ccb_complete(mly, mc); 1460 } else { 1461 /* Slot 0xffff may mean "extremely bogus command". */ 1462 printf("%s: got HM completion for illegal slot %u\n", 1463 device_xname(mly->mly_dv), slot); 1464 } 1465 1466 /* Unconditionally acknowledge status. */ 1467 mly_outb(mly, mly->mly_odbr, MLY_HM_STSREADY); 1468 mly_outb(mly, mly->mly_idbr, MLY_HM_STSACK); 1469 forus = 1; 1470 } 1471 1472 /* 1473 * Pick up memory-mailbox commands. 1474 */ 1475 if (mly_odbr_true(mly, MLY_AM_STSREADY)) { 1476 for (;;) { 1477 sp = &mly->mly_mmbox->mmm_status[mly->mly_mmbox_sts_idx]; 1478 off = (char *)sp - (char *)mly->mly_mmbox; 1479 1480 bus_dmamap_sync(mly->mly_dmat, mly->mly_mmbox_dmamap, 1481 off, sizeof(mly->mly_mmbox->mmm_command[0]), 1482 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); 1483 1484 /* Check for more status. */ 1485 if (sp->mmbox.flag == 0) 1486 break; 1487 1488 /* Get slot number. */ 1489 slot = le16toh(sp->status.command_id); 1490 if (slot < MLY_SLOT_MAX) { 1491 mc = mly->mly_ccbs + (slot - MLY_SLOT_START); 1492 mc->mc_status = sp->status.status; 1493 mc->mc_sense = sp->status.sense_length; 1494 mc->mc_resid = le32toh(sp->status.residue); 1495 mly_ccb_complete(mly, mc); 1496 } else { 1497 /* 1498 * Slot 0xffff may mean "extremely bogus 1499 * command". 1500 */ 1501 printf("%s: got AM completion for illegal " 1502 "slot %u at %d\n", device_xname(mly->mly_dv), 1503 slot, mly->mly_mmbox_sts_idx); 1504 } 1505 1506 /* Clear and move to next index. */ 1507 sp->mmbox.flag = 0; 1508 mly->mly_mmbox_sts_idx = 1509 (mly->mly_mmbox_sts_idx + 1) % MLY_MMBOX_STATUS; 1510 } 1511 1512 /* Acknowledge that we have collected status value(s). */ 1513 mly_outb(mly, mly->mly_odbr, MLY_AM_STSREADY); 1514 forus = 1; 1515 } 1516 1517 /* 1518 * Run the queue. 1519 */ 1520 if (forus && ! SIMPLEQ_EMPTY(&mly->mly_ccb_queue)) 1521 mly_ccb_enqueue(mly, NULL); 1522 1523 return (forus); 1524} 1525 1526/* 1527 * Process completed commands 1528 */ 1529static void 1530mly_ccb_complete(struct mly_softc *mly, struct mly_ccb *mc) 1531{ 1532 void (*complete)(struct mly_softc *, struct mly_ccb *); 1533 1534 bus_dmamap_sync(mly->mly_dmat, mly->mly_pkt_dmamap, 1535 mc->mc_packetphys - mly->mly_pkt_busaddr, 1536 sizeof(union mly_cmd_packet), 1537 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1538 1539 complete = mc->mc_complete; 1540 mc->mc_flags |= MLY_CCB_COMPLETE; 1541 1542 /* 1543 * Call completion handler or wake up sleeping consumer. 1544 */ 1545 if (complete != NULL) 1546 (*complete)(mly, mc); 1547 else 1548 wakeup(mc); 1549} 1550 1551/* 1552 * Allocate a command. 1553 */ 1554int 1555mly_ccb_alloc(struct mly_softc *mly, struct mly_ccb **mcp) 1556{ 1557 struct mly_ccb *mc; 1558 int s; 1559 1560 s = splbio(); 1561 mc = SLIST_FIRST(&mly->mly_ccb_free); 1562 if (mc != NULL) 1563 SLIST_REMOVE_HEAD(&mly->mly_ccb_free, mc_link.slist); 1564 splx(s); 1565 1566 *mcp = mc; 1567 return (mc == NULL ? EAGAIN : 0); 1568} 1569 1570/* 1571 * Release a command back to the freelist. 1572 */ 1573void 1574mly_ccb_free(struct mly_softc *mly, struct mly_ccb *mc) 1575{ 1576 int s; 1577 1578 /* 1579 * Fill in parts of the command that may cause confusion if a 1580 * consumer doesn't when we are later allocated. 1581 */ 1582 mc->mc_data = NULL; 1583 mc->mc_flags = 0; 1584 mc->mc_complete = NULL; 1585 mc->mc_private = NULL; 1586 mc->mc_packet->generic.command_control = 0; 1587 1588 /* 1589 * By default, we set up to overwrite the command packet with sense 1590 * information. 1591 */ 1592 mc->mc_packet->generic.sense_buffer_address = 1593 htole64(mc->mc_packetphys); 1594 mc->mc_packet->generic.maximum_sense_size = 1595 sizeof(union mly_cmd_packet); 1596 1597 s = splbio(); 1598 SLIST_INSERT_HEAD(&mly->mly_ccb_free, mc, mc_link.slist); 1599 splx(s); 1600} 1601 1602/* 1603 * Allocate and initialize command and packet structures. 1604 * 1605 * If the controller supports fewer than MLY_MAX_CCBS commands, limit our 1606 * allocation to that number. If we don't yet know how many commands the 1607 * controller supports, allocate a very small set (suitable for initialization 1608 * purposes only). 1609 */ 1610static int 1611mly_alloc_ccbs(struct mly_softc *mly) 1612{ 1613 struct mly_ccb *mc; 1614 int i, rv; 1615 1616 if (mly->mly_controllerinfo == NULL) 1617 mly->mly_ncmds = MLY_CCBS_RESV; 1618 else { 1619 i = le16toh(mly->mly_controllerinfo->maximum_parallel_commands); 1620 mly->mly_ncmds = uimin(MLY_MAX_CCBS, i); 1621 } 1622 1623 /* 1624 * Allocate enough space for all the command packets in one chunk 1625 * and map them permanently into controller-visible space. 1626 */ 1627 rv = mly_dmamem_alloc(mly, 1628 mly->mly_ncmds * sizeof(union mly_cmd_packet), 1629 &mly->mly_pkt_dmamap, (void **)&mly->mly_pkt, 1630 &mly->mly_pkt_busaddr, &mly->mly_pkt_seg); 1631 if (rv) 1632 return (rv); 1633 1634 mly->mly_ccbs = malloc(sizeof(struct mly_ccb) * mly->mly_ncmds, 1635 M_DEVBUF, M_WAITOK|M_ZERO); 1636 1637 for (i = 0; i < mly->mly_ncmds; i++) { 1638 mc = mly->mly_ccbs + i; 1639 mc->mc_slot = MLY_SLOT_START + i; 1640 mc->mc_packet = mly->mly_pkt + i; 1641 mc->mc_packetphys = mly->mly_pkt_busaddr + 1642 (i * sizeof(union mly_cmd_packet)); 1643 1644 rv = bus_dmamap_create(mly->mly_dmat, MLY_MAX_XFER, 1645 MLY_MAX_SEGS, MLY_MAX_XFER, 0, 1646 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 1647 &mc->mc_datamap); 1648 if (rv) { 1649 mly_release_ccbs(mly); 1650 return (rv); 1651 } 1652 1653 mly_ccb_free(mly, mc); 1654 } 1655 1656 return (0); 1657} 1658 1659/* 1660 * Free all the storage held by commands. 1661 * 1662 * Must be called with all commands on the free list. 1663 */ 1664static void 1665mly_release_ccbs(struct mly_softc *mly) 1666{ 1667 struct mly_ccb *mc; 1668 1669 /* Throw away command buffer DMA maps. */ 1670 while (mly_ccb_alloc(mly, &mc) == 0) 1671 bus_dmamap_destroy(mly->mly_dmat, mc->mc_datamap); 1672 1673 /* Release CCB storage. */ 1674 free(mly->mly_ccbs, M_DEVBUF); 1675 1676 /* Release the packet storage. */ 1677 mly_dmamem_free(mly, mly->mly_ncmds * sizeof(union mly_cmd_packet), 1678 mly->mly_pkt_dmamap, (void *)mly->mly_pkt, &mly->mly_pkt_seg); 1679} 1680 1681/* 1682 * Map a command into controller-visible space. 1683 */ 1684static int 1685mly_ccb_map(struct mly_softc *mly, struct mly_ccb *mc) 1686{ 1687 struct mly_cmd_generic *gen; 1688 struct mly_sg_entry *sg; 1689 bus_dma_segment_t *ds; 1690 int flg, nseg, rv; 1691 1692#ifdef DIAGNOSTIC 1693 /* Don't map more than once. */ 1694 if ((mc->mc_flags & MLY_CCB_MAPPED) != 0) 1695 panic("mly_ccb_map: already mapped"); 1696 mc->mc_flags |= MLY_CCB_MAPPED; 1697 1698 /* Does the command have a data buffer? */ 1699 if (mc->mc_data == NULL) 1700 panic("mly_ccb_map: no data buffer"); 1701#endif 1702 1703 rv = bus_dmamap_load(mly->mly_dmat, mc->mc_datamap, mc->mc_data, 1704 mc->mc_length, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING | 1705 ((mc->mc_flags & MLY_CCB_DATAIN) != 0 ? 1706 BUS_DMA_READ : BUS_DMA_WRITE)); 1707 if (rv != 0) 1708 return (rv); 1709 1710 gen = &mc->mc_packet->generic; 1711 1712 /* 1713 * Can we use the transfer structure directly? 1714 */ 1715 if ((nseg = mc->mc_datamap->dm_nsegs) <= 2) { 1716 mc->mc_sgoff = -1; 1717 sg = &gen->transfer.direct.sg[0]; 1718 } else { 1719 mc->mc_sgoff = (mc->mc_slot - MLY_SLOT_START) * 1720 MLY_MAX_SEGS; 1721 sg = mly->mly_sg + mc->mc_sgoff; 1722 gen->command_control |= MLY_CMDCTL_EXTENDED_SG_TABLE; 1723 gen->transfer.indirect.entries[0] = htole16(nseg); 1724 gen->transfer.indirect.table_physaddr[0] = 1725 htole64(mly->mly_sg_busaddr + 1726 (mc->mc_sgoff * sizeof(struct mly_sg_entry))); 1727 } 1728 1729 /* 1730 * Fill the S/G table. 1731 */ 1732 for (ds = mc->mc_datamap->dm_segs; nseg != 0; nseg--, sg++, ds++) { 1733 sg->physaddr = htole64(ds->ds_addr); 1734 sg->length = htole64(ds->ds_len); 1735 } 1736 1737 /* 1738 * Sync up the data map. 1739 */ 1740 if ((mc->mc_flags & MLY_CCB_DATAIN) != 0) 1741 flg = BUS_DMASYNC_PREREAD; 1742 else /* if ((mc->mc_flags & MLY_CCB_DATAOUT) != 0) */ { 1743 gen->command_control |= MLY_CMDCTL_DATA_DIRECTION; 1744 flg = BUS_DMASYNC_PREWRITE; 1745 } 1746 1747 bus_dmamap_sync(mly->mly_dmat, mc->mc_datamap, 0, mc->mc_length, flg); 1748 1749 /* 1750 * Sync up the chained S/G table, if we're using one. 1751 */ 1752 if (mc->mc_sgoff == -1) 1753 return (0); 1754 1755 bus_dmamap_sync(mly->mly_dmat, mly->mly_sg_dmamap, mc->mc_sgoff, 1756 MLY_SGL_SIZE, BUS_DMASYNC_PREWRITE); 1757 1758 return (0); 1759} 1760 1761/* 1762 * Unmap a command from controller-visible space. 1763 */ 1764static void 1765mly_ccb_unmap(struct mly_softc *mly, struct mly_ccb *mc) 1766{ 1767 int flg; 1768 1769#ifdef DIAGNOSTIC 1770 if ((mc->mc_flags & MLY_CCB_MAPPED) == 0) 1771 panic("mly_ccb_unmap: not mapped"); 1772 mc->mc_flags &= ~MLY_CCB_MAPPED; 1773#endif 1774 1775 if ((mc->mc_flags & MLY_CCB_DATAIN) != 0) 1776 flg = BUS_DMASYNC_POSTREAD; 1777 else /* if ((mc->mc_flags & MLY_CCB_DATAOUT) != 0) */ 1778 flg = BUS_DMASYNC_POSTWRITE; 1779 1780 bus_dmamap_sync(mly->mly_dmat, mc->mc_datamap, 0, mc->mc_length, flg); 1781 bus_dmamap_unload(mly->mly_dmat, mc->mc_datamap); 1782 1783 if (mc->mc_sgoff == -1) 1784 return; 1785 1786 bus_dmamap_sync(mly->mly_dmat, mly->mly_sg_dmamap, mc->mc_sgoff, 1787 MLY_SGL_SIZE, BUS_DMASYNC_POSTWRITE); 1788} 1789 1790/* 1791 * Adjust the size of each I/O before it passes to the SCSI layer. 1792 */ 1793static void 1794mly_scsipi_minphys(struct buf *bp) 1795{ 1796 1797 if (bp->b_bcount > MLY_MAX_XFER) 1798 bp->b_bcount = MLY_MAX_XFER; 1799 minphys(bp); 1800} 1801 1802/* 1803 * Start a SCSI command. 1804 */ 1805static void 1806mly_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, 1807 void *arg) 1808{ 1809 struct mly_ccb *mc; 1810 struct mly_cmd_scsi_small *ss; 1811 struct scsipi_xfer *xs; 1812 struct scsipi_periph *periph; 1813 struct mly_softc *mly; 1814 struct mly_btl *btl; 1815 int s, tmp; 1816 1817 mly = device_private(chan->chan_adapter->adapt_dev); 1818 1819 switch (req) { 1820 case ADAPTER_REQ_RUN_XFER: 1821 xs = arg; 1822 periph = xs->xs_periph; 1823 btl = &mly->mly_btl[chan->chan_channel][periph->periph_target]; 1824 s = splbio(); 1825 tmp = btl->mb_flags; 1826 splx(s); 1827 1828 /* 1829 * Check for I/O attempt to a protected or non-existent 1830 * device. 1831 */ 1832 if ((tmp & MLY_BTL_PROTECTED) != 0) { 1833 xs->error = XS_SELTIMEOUT; 1834 scsipi_done(xs); 1835 break; 1836 } 1837 1838#ifdef DIAGNOSTIC 1839 /* XXX Increase if/when we support large SCSI commands. */ 1840 if (xs->cmdlen > MLY_CMD_SCSI_SMALL_CDB) { 1841 printf("%s: cmd too large\n", device_xname(mly->mly_dv)); 1842 xs->error = XS_DRIVER_STUFFUP; 1843 scsipi_done(xs); 1844 break; 1845 } 1846#endif 1847 1848 if (mly_ccb_alloc(mly, &mc)) { 1849 xs->error = XS_RESOURCE_SHORTAGE; 1850 scsipi_done(xs); 1851 break; 1852 } 1853 1854 /* Build the command. */ 1855 mc->mc_data = xs->data; 1856 mc->mc_length = xs->datalen; 1857 mc->mc_complete = mly_scsipi_complete; 1858 mc->mc_private = xs; 1859 1860 /* Build the packet for the controller. */ 1861 ss = &mc->mc_packet->scsi_small; 1862 ss->opcode = MDACMD_SCSI; 1863#ifdef notdef 1864 /* 1865 * XXX FreeBSD does this, but it doesn't fix anything, 1866 * XXX and appears potentially harmful. 1867 */ 1868 ss->command_control |= MLY_CMDCTL_DISABLE_DISCONNECT; 1869#endif 1870 1871 ss->data_size = htole32(xs->datalen); 1872 _lto3l(MLY_PHYADDR(0, chan->chan_channel, 1873 periph->periph_target, periph->periph_lun), ss->addr); 1874 1875 if (xs->timeout < 60 * 1000) 1876 ss->timeout = xs->timeout / 1000 | 1877 MLY_TIMEOUT_SECONDS; 1878 else if (xs->timeout < 60 * 60 * 1000) 1879 ss->timeout = xs->timeout / (60 * 1000) | 1880 MLY_TIMEOUT_MINUTES; 1881 else 1882 ss->timeout = xs->timeout / (60 * 60 * 1000) | 1883 MLY_TIMEOUT_HOURS; 1884 1885 ss->maximum_sense_size = sizeof(xs->sense); 1886 ss->cdb_length = xs->cmdlen; 1887 memcpy(ss->cdb, xs->cmd, xs->cmdlen); 1888 1889 if (mc->mc_length != 0) { 1890 if ((xs->xs_control & XS_CTL_DATA_OUT) != 0) 1891 mc->mc_flags |= MLY_CCB_DATAOUT; 1892 else /* if ((xs->xs_control & XS_CTL_DATA_IN) != 0) */ 1893 mc->mc_flags |= MLY_CCB_DATAIN; 1894 1895 if (mly_ccb_map(mly, mc) != 0) { 1896 xs->error = XS_DRIVER_STUFFUP; 1897 mly_ccb_free(mly, mc); 1898 scsipi_done(xs); 1899 break; 1900 } 1901 } 1902 1903 /* 1904 * Give the command to the controller. 1905 */ 1906 if ((xs->xs_control & XS_CTL_POLL) != 0) { 1907 if (mly_ccb_poll(mly, mc, xs->timeout + 5000)) { 1908 xs->error = XS_REQUEUE; 1909 if (mc->mc_length != 0) 1910 mly_ccb_unmap(mly, mc); 1911 mly_ccb_free(mly, mc); 1912 scsipi_done(xs); 1913 } 1914 } else 1915 mly_ccb_enqueue(mly, mc); 1916 1917 break; 1918 1919 case ADAPTER_REQ_GROW_RESOURCES: 1920 /* 1921 * Not supported. 1922 */ 1923 break; 1924 1925 case ADAPTER_REQ_SET_XFER_MODE: 1926 /* 1927 * We can't change the transfer mode, but at least let 1928 * scsipi know what the adapter has negotiated. 1929 */ 1930 mly_get_xfer_mode(mly, chan->chan_channel, arg); 1931 break; 1932 } 1933} 1934 1935/* 1936 * Handle completion of a SCSI command. 1937 */ 1938static void 1939mly_scsipi_complete(struct mly_softc *mly, struct mly_ccb *mc) 1940{ 1941 struct scsipi_xfer *xs; 1942 struct scsipi_channel *chan; 1943 struct scsipi_inquiry_data *inq; 1944 struct mly_btl *btl; 1945 int target, sl, s; 1946 const char *p; 1947 1948 xs = mc->mc_private; 1949 xs->status = mc->mc_status; 1950 1951 /* 1952 * XXX The `resid' value as returned by the controller appears to be 1953 * bogus, so we always set it to zero. Is it perhaps the transfer 1954 * count? 1955 */ 1956 xs->resid = 0; /* mc->mc_resid; */ 1957 1958 if (mc->mc_length != 0) 1959 mly_ccb_unmap(mly, mc); 1960 1961 switch (mc->mc_status) { 1962 case SCSI_OK: 1963 /* 1964 * In order to report logical device type and status, we 1965 * overwrite the result of the INQUIRY command to logical 1966 * devices. 1967 */ 1968 if (xs->cmd->opcode == INQUIRY) { 1969 chan = xs->xs_periph->periph_channel; 1970 target = xs->xs_periph->periph_target; 1971 btl = &mly->mly_btl[chan->chan_channel][target]; 1972 1973 s = splbio(); 1974 if ((btl->mb_flags & MLY_BTL_LOGICAL) != 0) { 1975 inq = (struct scsipi_inquiry_data *)xs->data; 1976 mly_padstr(inq->vendor, "MYLEX", 8); 1977 p = mly_describe_code(mly_table_device_type, 1978 btl->mb_type); 1979 mly_padstr(inq->product, p, 16); 1980 p = mly_describe_code(mly_table_device_state, 1981 btl->mb_state); 1982 mly_padstr(inq->revision, p, 4); 1983 } 1984 splx(s); 1985 } 1986 1987 xs->error = XS_NOERROR; 1988 break; 1989 1990 case SCSI_CHECK: 1991 sl = mc->mc_sense; 1992 if (sl > sizeof(xs->sense.scsi_sense)) 1993 sl = sizeof(xs->sense.scsi_sense); 1994 memcpy(&xs->sense.scsi_sense, mc->mc_packet, sl); 1995 xs->error = XS_SENSE; 1996 break; 1997 1998 case SCSI_BUSY: 1999 case SCSI_QUEUE_FULL: 2000 xs->error = XS_BUSY; 2001 break; 2002 2003 default: 2004 printf("%s: unknown SCSI status 0x%x\n", 2005 device_xname(mly->mly_dv), xs->status); 2006 xs->error = XS_DRIVER_STUFFUP; 2007 break; 2008 } 2009 2010 mly_ccb_free(mly, mc); 2011 scsipi_done(xs); 2012} 2013 2014/* 2015 * Notify scsipi about a target's transfer mode. 2016 */ 2017static void 2018mly_get_xfer_mode(struct mly_softc *mly, int bus, struct scsipi_xfer_mode *xm) 2019{ 2020 struct mly_btl *btl; 2021 int s; 2022 2023 btl = &mly->mly_btl[bus][xm->xm_target]; 2024 xm->xm_mode = 0; 2025 2026 s = splbio(); 2027 2028 if ((btl->mb_flags & MLY_BTL_PHYSICAL) != 0) { 2029 if (btl->mb_speed == 0) { 2030 xm->xm_period = 0; 2031 xm->xm_offset = 0; 2032 } else { 2033 xm->xm_period = 12; /* XXX */ 2034 xm->xm_offset = 8; /* XXX */ 2035 xm->xm_mode |= PERIPH_CAP_SYNC; /* XXX */ 2036 } 2037 2038 switch (btl->mb_width) { 2039 case 32: 2040 xm->xm_mode = PERIPH_CAP_WIDE32; 2041 break; 2042 case 16: 2043 xm->xm_mode = PERIPH_CAP_WIDE16; 2044 break; 2045 default: 2046 xm->xm_mode = 0; 2047 break; 2048 } 2049 } else /* ((btl->mb_flags & MLY_BTL_LOGICAL) != 0) */ { 2050 xm->xm_mode = PERIPH_CAP_WIDE16 | PERIPH_CAP_SYNC; 2051 xm->xm_period = 12; 2052 xm->xm_offset = 8; 2053 } 2054 2055 if ((btl->mb_flags & MLY_BTL_TQING) != 0) 2056 xm->xm_mode |= PERIPH_CAP_TQING; 2057 2058 splx(s); 2059 2060 scsipi_async_event(&mly->mly_chans[bus], ASYNC_EVENT_XFER_MODE, xm); 2061} 2062 2063/* 2064 * ioctl hook; used here only to initiate low-level rescans. 2065 */ 2066static int 2067mly_scsipi_ioctl(struct scsipi_channel *chan, u_long cmd, void *data, 2068 int flag, struct proc *p) 2069{ 2070 struct mly_softc *mly; 2071 int rv; 2072 2073 mly = device_private(chan->chan_adapter->adapt_dev); 2074 2075 switch (cmd) { 2076 case SCBUSIOLLSCAN: 2077 mly_scan_channel(mly, chan->chan_channel); 2078 rv = 0; 2079 break; 2080 default: 2081 rv = ENOTTY; 2082 break; 2083 } 2084 2085 return (rv); 2086} 2087 2088/* 2089 * Handshake with the firmware while the card is being initialized. 2090 */ 2091static int 2092mly_fwhandshake(struct mly_softc *mly) 2093{ 2094 u_int8_t error; 2095 int spinup; 2096 2097 spinup = 0; 2098 2099 /* Set HM_STSACK and let the firmware initialize. */ 2100 mly_outb(mly, mly->mly_idbr, MLY_HM_STSACK); 2101 DELAY(1000); /* too short? */ 2102 2103 /* If HM_STSACK is still true, the controller is initializing. */ 2104 if (!mly_idbr_true(mly, MLY_HM_STSACK)) 2105 return (0); 2106 2107 printf("%s: controller initialization started\n", 2108 device_xname(mly->mly_dv)); 2109 2110 /* 2111 * Spin waiting for initialization to finish, or for a message to be 2112 * delivered. 2113 */ 2114 while (mly_idbr_true(mly, MLY_HM_STSACK)) { 2115 /* Check for a message */ 2116 if (!mly_error_valid(mly)) 2117 continue; 2118 2119 error = mly_inb(mly, mly->mly_error_status) & ~MLY_MSG_EMPTY; 2120 (void)mly_inb(mly, mly->mly_cmd_mailbox); 2121 (void)mly_inb(mly, mly->mly_cmd_mailbox + 1); 2122 2123 switch (error) { 2124 case MLY_MSG_SPINUP: 2125 if (!spinup) { 2126 printf("%s: drive spinup in progress\n", 2127 device_xname(mly->mly_dv)); 2128 spinup = 1; 2129 } 2130 break; 2131 2132 case MLY_MSG_RACE_RECOVERY_FAIL: 2133 printf("%s: mirror race recovery failed - \n", 2134 device_xname(mly->mly_dv)); 2135 printf("%s: one or more drives offline\n", 2136 device_xname(mly->mly_dv)); 2137 break; 2138 2139 case MLY_MSG_RACE_IN_PROGRESS: 2140 printf("%s: mirror race recovery in progress\n", 2141 device_xname(mly->mly_dv)); 2142 break; 2143 2144 case MLY_MSG_RACE_ON_CRITICAL: 2145 printf("%s: mirror race recovery on critical drive\n", 2146 device_xname(mly->mly_dv)); 2147 break; 2148 2149 case MLY_MSG_PARITY_ERROR: 2150 printf("%s: FATAL MEMORY PARITY ERROR\n", 2151 device_xname(mly->mly_dv)); 2152 return (ENXIO); 2153 2154 default: 2155 printf("%s: unknown initialization code 0x%x\n", 2156 device_xname(mly->mly_dv), error); 2157 break; 2158 } 2159 } 2160 2161 return (0); 2162} 2163 2164/* 2165 * Space-fill a character string 2166 */ 2167static void 2168mly_padstr(char *dst, const char *src, int len) 2169{ 2170 2171 while (len-- > 0) { 2172 if (*src != '\0') 2173 *dst++ = *src++; 2174 else 2175 *dst++ = ' '; 2176 } 2177} 2178 2179/* 2180 * Allocate DMA safe memory. 2181 */ 2182static int 2183mly_dmamem_alloc(struct mly_softc *mly, int size, bus_dmamap_t *dmamap, 2184 void **kva, bus_addr_t *paddr, bus_dma_segment_t *seg) 2185{ 2186 int rseg, rv, state; 2187 2188 state = 0; 2189 2190 if ((rv = bus_dmamem_alloc(mly->mly_dmat, size, PAGE_SIZE, 0, 2191 seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 2192 aprint_error_dev(mly->mly_dv, "dmamem_alloc = %d\n", rv); 2193 goto bad; 2194 } 2195 2196 state++; 2197 2198 if ((rv = bus_dmamem_map(mly->mly_dmat, seg, 1, size, kva, 2199 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 2200 aprint_error_dev(mly->mly_dv, "dmamem_map = %d\n", rv); 2201 goto bad; 2202 } 2203 2204 state++; 2205 2206 if ((rv = bus_dmamap_create(mly->mly_dmat, size, size, 1, 0, 2207 BUS_DMA_NOWAIT, dmamap)) != 0) { 2208 aprint_error_dev(mly->mly_dv, "dmamap_create = %d\n", rv); 2209 goto bad; 2210 } 2211 2212 state++; 2213 2214 if ((rv = bus_dmamap_load(mly->mly_dmat, *dmamap, *kva, size, 2215 NULL, BUS_DMA_NOWAIT)) != 0) { 2216 aprint_error_dev(mly->mly_dv, "dmamap_load = %d\n", rv); 2217 goto bad; 2218 } 2219 2220 *paddr = (*dmamap)->dm_segs[0].ds_addr; 2221 memset(*kva, 0, size); 2222 return (0); 2223 2224 bad: 2225 if (state > 2) 2226 bus_dmamap_destroy(mly->mly_dmat, *dmamap); 2227 if (state > 1) 2228 bus_dmamem_unmap(mly->mly_dmat, *kva, size); 2229 if (state > 0) 2230 bus_dmamem_free(mly->mly_dmat, seg, 1); 2231 2232 return (rv); 2233} 2234 2235/* 2236 * Free DMA safe memory. 2237 */ 2238static void 2239mly_dmamem_free(struct mly_softc *mly, int size, bus_dmamap_t dmamap, 2240 void *kva, bus_dma_segment_t *seg) 2241{ 2242 2243 bus_dmamap_unload(mly->mly_dmat, dmamap); 2244 bus_dmamap_destroy(mly->mly_dmat, dmamap); 2245 bus_dmamem_unmap(mly->mly_dmat, kva, size); 2246 bus_dmamem_free(mly->mly_dmat, seg, 1); 2247} 2248 2249 2250/* 2251 * Accept an open operation on the control device. 2252 */ 2253int 2254mlyopen(dev_t dev, int flag, int mode, struct lwp *l) 2255{ 2256 struct mly_softc *mly; 2257 2258 if ((mly = device_lookup_private(&mly_cd, minor(dev))) == NULL) 2259 return (ENXIO); 2260 if ((mly->mly_state & MLY_STATE_INITOK) == 0) 2261 return (ENXIO); 2262 if ((mly->mly_state & MLY_STATE_OPEN) != 0) 2263 return (EBUSY); 2264 2265 mly->mly_state |= MLY_STATE_OPEN; 2266 return (0); 2267} 2268 2269/* 2270 * Accept the last close on the control device. 2271 */ 2272int 2273mlyclose(dev_t dev, int flag, int mode, 2274 struct lwp *l) 2275{ 2276 struct mly_softc *mly; 2277 2278 mly = device_lookup_private(&mly_cd, minor(dev)); 2279 mly->mly_state &= ~MLY_STATE_OPEN; 2280 return (0); 2281} 2282 2283/* 2284 * Handle control operations. 2285 */ 2286int 2287mlyioctl(dev_t dev, u_long cmd, void *data, int flag, 2288 struct lwp *l) 2289{ 2290 struct mly_softc *mly; 2291 int rv; 2292 2293 mly = device_lookup_private(&mly_cd, minor(dev)); 2294 2295 switch (cmd) { 2296 case MLYIO_COMMAND: 2297 rv = kauth_authorize_device_passthru(l->l_cred, dev, 2298 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL, data); 2299 if (rv) 2300 break; 2301 2302 rv = mly_user_command(mly, (void *)data); 2303 break; 2304 case MLYIO_HEALTH: 2305 rv = mly_user_health(mly, (void *)data); 2306 break; 2307 default: 2308 rv = ENOTTY; 2309 break; 2310 } 2311 2312 return (rv); 2313} 2314 2315/* 2316 * Execute a command passed in from userspace. 2317 * 2318 * The control structure contains the actual command for the controller, as 2319 * well as the user-space data pointer and data size, and an optional sense 2320 * buffer size/pointer. On completion, the data size is adjusted to the 2321 * command residual, and the sense buffer size to the size of the returned 2322 * sense data. 2323 */ 2324static int 2325mly_user_command(struct mly_softc *mly, struct mly_user_command *uc) 2326{ 2327 struct mly_ccb *mc; 2328 int rv, mapped; 2329 2330 if ((rv = mly_ccb_alloc(mly, &mc)) != 0) 2331 return (rv); 2332 2333 mapped = 0; 2334 mc->mc_data = NULL; 2335 2336 /* 2337 * Handle data size/direction. 2338 */ 2339 if ((mc->mc_length = abs(uc->DataTransferLength)) != 0) { 2340 if (mc->mc_length > MAXPHYS) { 2341 rv = EINVAL; 2342 goto out; 2343 } 2344 2345 mc->mc_data = malloc(mc->mc_length, M_DEVBUF, M_WAITOK); 2346 if (mc->mc_data == NULL) { 2347 rv = ENOMEM; 2348 goto out; 2349 } 2350 2351 if (uc->DataTransferLength > 0) { 2352 mc->mc_flags |= MLY_CCB_DATAIN; 2353 memset(mc->mc_data, 0, mc->mc_length); 2354 } 2355 2356 if (uc->DataTransferLength < 0) { 2357 mc->mc_flags |= MLY_CCB_DATAOUT; 2358 rv = copyin(uc->DataTransferBuffer, mc->mc_data, 2359 mc->mc_length); 2360 if (rv != 0) 2361 goto out; 2362 } 2363 2364 if ((rv = mly_ccb_map(mly, mc)) != 0) 2365 goto out; 2366 mapped = 1; 2367 } 2368 2369 /* Copy in the command and execute it. */ 2370 memcpy(mc->mc_packet, &uc->CommandMailbox, sizeof(uc->CommandMailbox)); 2371 2372 if ((rv = mly_ccb_wait(mly, mc, 60000)) != 0) 2373 goto out; 2374 2375 /* Return the data to userspace. */ 2376 if (uc->DataTransferLength > 0) { 2377 rv = copyout(mc->mc_data, uc->DataTransferBuffer, 2378 mc->mc_length); 2379 if (rv != 0) 2380 goto out; 2381 } 2382 2383 /* Return the sense buffer to userspace. */ 2384 if (uc->RequestSenseLength > 0 && mc->mc_sense > 0) { 2385 rv = copyout(mc->mc_packet, uc->RequestSenseBuffer, 2386 uimin(uc->RequestSenseLength, mc->mc_sense)); 2387 if (rv != 0) 2388 goto out; 2389 } 2390 2391 /* Return command results to userspace (caller will copy out). */ 2392 uc->DataTransferLength = mc->mc_resid; 2393 uc->RequestSenseLength = uimin(uc->RequestSenseLength, mc->mc_sense); 2394 uc->CommandStatus = mc->mc_status; 2395 rv = 0; 2396 2397 out: 2398 if (mapped) 2399 mly_ccb_unmap(mly, mc); 2400 if (mc->mc_data != NULL) 2401 free(mc->mc_data, M_DEVBUF); 2402 mly_ccb_free(mly, mc); 2403 2404 return (rv); 2405} 2406 2407/* 2408 * Return health status to userspace. If the health change index in the 2409 * user structure does not match that currently exported by the controller, 2410 * we return the current status immediately. Otherwise, we block until 2411 * either interrupted or new status is delivered. 2412 */ 2413static int 2414mly_user_health(struct mly_softc *mly, struct mly_user_health *uh) 2415{ 2416 struct mly_health_status mh; 2417 int rv, s; 2418 2419 /* Fetch the current health status from userspace. */ 2420 rv = copyin(uh->HealthStatusBuffer, &mh, sizeof(mh)); 2421 if (rv != 0) 2422 return (rv); 2423 2424 /* spin waiting for a status update */ 2425 s = splbio(); 2426 if (mly->mly_event_change == mh.change_counter) 2427 rv = tsleep(&mly->mly_event_change, PRIBIO | PCATCH, 2428 "mlyhealth", 0); 2429 splx(s); 2430 2431 if (rv == 0) { 2432 /* 2433 * Copy the controller's health status buffer out (there is 2434 * a race here if it changes again). 2435 */ 2436 rv = copyout(&mly->mly_mmbox->mmm_health.status, 2437 uh->HealthStatusBuffer, sizeof(uh->HealthStatusBuffer)); 2438 } 2439 2440 return (rv); 2441} 2442