ciss.c revision 172608
158314Sache/*- 221308Sache * Copyright (c) 2001 Michael Smith 321308Sache * Copyright (c) 2004 Paul Saab 4165675Sache * All rights reserved. 521308Sache * 621308Sache * Redistribution and use in source and binary forms, with or without 721308Sache * modification, are permitted provided that the following conditions 821308Sache * are met: 921308Sache * 1. Redistributions of source code must retain the above copyright 1021308Sache * notice, this list of conditions and the following disclaimer. 1158314Sache * 2. Redistributions in binary form must reproduce the above copyright 1221308Sache * notice, this list of conditions and the following disclaimer in the 1321308Sache * documentation and/or other materials provided with the distribution. 1421308Sache * 1521308Sache * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1621308Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1721308Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1821308Sache * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1921308Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2021308Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2121308Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2258314Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2321308Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2421308Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2521308Sache * SUCH DAMAGE. 2621308Sache * 2721308Sache * $FreeBSD: head/sys/dev/ciss/ciss.c 172608 2007-10-13 05:45:45Z iwasaki $ 2821308Sache */ 2921308Sache 3021308Sache/* 3121308Sache * Common Interface for SCSI-3 Support driver. 3221308Sache * 3321308Sache * CISS claims to provide a common interface between a generic SCSI 3421308Sache * transport and an intelligent host adapter. 3526497Sache * 3626497Sache * This driver supports CISS as defined in the document "CISS Command 3721308Sache * Interface for SCSI-3 Support Open Specification", Version 1.04, 3821308Sache * Valence Number 1, dated 20001127, produced by Compaq Computer 3921308Sache * Corporation. This document appears to be a hastily and somewhat 4021308Sache * arbitrarlily cut-down version of a larger (and probably even more 4121308Sache * chaotic and inconsistent) Compaq internal document. Various 4221308Sache * details were also gleaned from Compaq's "cciss" driver for Linux. 4326497Sache * 4421308Sache * We provide a shim layer between the CISS interface and CAM, 4521308Sache * offloading most of the queueing and being-a-disk chores onto CAM. 4621308Sache * Entry to the driver is via the PCI bus attachment (ciss_probe, 47119614Sache * ciss_attach, etc) and via the CAM interface (ciss_cam_action, 4821308Sache * ciss_cam_poll). The Compaq CISS adapters are, however, poor SCSI 4921308Sache * citizens and we have to fake up some responses to get reasonable 5021308Sache * behaviour out of them. In addition, the CISS command set is by no 5121308Sache * means adequate to support the functionality of a RAID controller, 5221308Sache * and thus the supported Compaq adapters utilise portions of the 5321308Sache * control protocol from earlier Compaq adapter families. 5421308Sache * 5521308Sache * Note that we only support the "simple" transport layer over PCI. 5658314Sache * This interface (ab)uses the I2O register set (specifically the post 5758314Sache * queues) to exchange commands with the adapter. Other interfaces 5858314Sache * are available, but we aren't supposed to know about them, and it is 5921308Sache * dubious whether they would provide major performance improvements 6021308Sache * except under extreme load. 6121308Sache * 6221308Sache * Currently the only supported CISS adapters are the Compaq Smart 63119614Sache * Array 5* series (5300, 5i, 532). Even with only three adapters, 64119614Sache * Compaq still manage to have interface variations. 65119614Sache * 66119614Sache * 67119614Sache * Thanks must go to Fred Harris and Darryl DeVinney at Compaq, as 6821308Sache * well as Paul Saab at Yahoo! for their assistance in making this 69119614Sache * driver happen. 70136759Speter * 71119614Sache * More thanks must go to John Cagle at HP for the countless hours 72119614Sache * spent making this driver "work" with the MSA* series storage 73119614Sache * enclosures. Without his help (and nagging), this driver could not 74119614Sache * be used with these enclosures. 75119614Sache */ 7621308Sache 7758314Sache#include <sys/param.h> 7821308Sache#include <sys/systm.h> 7921308Sache#include <sys/malloc.h> 80165675Sache#include <sys/kernel.h> 81165675Sache#include <sys/bus.h> 8221308Sache#include <sys/conf.h> 8321308Sache#include <sys/stat.h> 84165675Sache#include <sys/kthread.h> 85165675Sache#include <sys/queue.h> 86165675Sache#include <sys/sysctl.h> 87165675Sache 88165675Sache#include <cam/cam.h> 89165675Sache#include <cam/cam_ccb.h> 90165675Sache#include <cam/cam_periph.h> 91165675Sache#include <cam/cam_sim.h> 9221308Sache#include <cam/cam_xpt_sim.h> 9321308Sache#include <cam/scsi/scsi_all.h> 9421308Sache#include <cam/scsi/scsi_message.h> 9521308Sache 9621308Sache#include <machine/bus.h> 9721308Sache#include <machine/endian.h> 9821308Sache#include <machine/resource.h> 9921308Sache#include <sys/rman.h> 10021308Sache 10121308Sache#include <dev/pci/pcireg.h> 10221308Sache#include <dev/pci/pcivar.h> 10321308Sache 10421308Sache#include <dev/ciss/cissreg.h> 10521308Sache#include <dev/ciss/cissvar.h> 10621308Sache#include <dev/ciss/cissio.h> 10721308Sache 10821308SacheMALLOC_DEFINE(CISS_MALLOC_CLASS, "ciss_data", "ciss internal data buffers"); 10921308Sache 11021308Sache/* pci interface */ 11121308Sachestatic int ciss_lookup(device_t dev); 11221308Sachestatic int ciss_probe(device_t dev); 11321308Sachestatic int ciss_attach(device_t dev); 11421308Sachestatic int ciss_detach(device_t dev); 11521308Sachestatic int ciss_shutdown(device_t dev); 11621308Sache 11721308Sache/* (de)initialisation functions, control wrappers */ 11821308Sachestatic int ciss_init_pci(struct ciss_softc *sc); 11921308Sachestatic int ciss_wait_adapter(struct ciss_softc *sc); 12075409Sachestatic int ciss_flush_adapter(struct ciss_softc *sc); 12121308Sachestatic int ciss_init_requests(struct ciss_softc *sc); 12221308Sachestatic void ciss_command_map_helper(void *arg, bus_dma_segment_t *segs, 12321308Sache int nseg, int error); 12421308Sachestatic int ciss_identify_adapter(struct ciss_softc *sc); 12521308Sachestatic int ciss_init_logical(struct ciss_softc *sc); 12621308Sachestatic int ciss_init_physical(struct ciss_softc *sc); 127157188Sachestatic int ciss_filter_physical(struct ciss_softc *sc, struct ciss_lun_report *cll); 12821308Sachestatic int ciss_identify_logical(struct ciss_softc *sc, struct ciss_ldrive *ld); 12921308Sachestatic int ciss_get_ldrive_status(struct ciss_softc *sc, struct ciss_ldrive *ld); 13021308Sachestatic int ciss_update_config(struct ciss_softc *sc); 13121308Sachestatic int ciss_accept_media(struct ciss_softc *sc, struct ciss_ldrive *ld); 13221308Sachestatic void ciss_init_sysctl(struct ciss_softc *sc); 13321308Sachestatic void ciss_soft_reset(struct ciss_softc *sc); 134157188Sachestatic void ciss_free(struct ciss_softc *sc); 13521308Sachestatic void ciss_spawn_notify_thread(struct ciss_softc *sc); 136157188Sachestatic void ciss_kill_notify_thread(struct ciss_softc *sc); 137157188Sache 138157188Sache/* request submission/completion */ 139157188Sachestatic int ciss_start(struct ciss_request *cr); 14021308Sachestatic void ciss_done(struct ciss_softc *sc); 14121308Sachestatic void ciss_intr(void *arg); 14221308Sachestatic void ciss_complete(struct ciss_softc *sc); 143157188Sachestatic int ciss_report_request(struct ciss_request *cr, int *command_status, 144165675Sache int *scsi_status); 145157188Sachestatic int ciss_synch_request(struct ciss_request *cr, int timeout); 14621308Sachestatic int ciss_poll_request(struct ciss_request *cr, int timeout); 14721308Sachestatic int ciss_wait_request(struct ciss_request *cr, int timeout); 14821308Sache#if 0 14921308Sachestatic int ciss_abort_request(struct ciss_request *cr); 15021308Sache#endif 15121308Sache 15221308Sache/* request queueing */ 15321308Sachestatic int ciss_get_request(struct ciss_softc *sc, struct ciss_request **crp); 15421308Sachestatic void ciss_preen_command(struct ciss_request *cr); 15521308Sachestatic void ciss_release_request(struct ciss_request *cr); 15621308Sache 15721308Sache/* request helpers */ 15821308Sachestatic int ciss_get_bmic_request(struct ciss_softc *sc, struct ciss_request **crp, 15921308Sache int opcode, void **bufp, size_t bufsize); 16021308Sachestatic int ciss_user_command(struct ciss_softc *sc, IOCTL_Command_struct *ioc); 16121308Sache 16221308Sache/* DMA map/unmap */ 16321308Sachestatic int ciss_map_request(struct ciss_request *cr); 16421308Sachestatic void ciss_request_map_helper(void *arg, bus_dma_segment_t *segs, 16521308Sache int nseg, int error); 16621308Sachestatic void ciss_unmap_request(struct ciss_request *cr); 16721308Sache 16875409Sache/* CAM interface */ 16975409Sachestatic int ciss_cam_init(struct ciss_softc *sc); 17075409Sachestatic void ciss_cam_rescan_target(struct ciss_softc *sc, 17121308Sache int bus, int target); 172165675Sachestatic void ciss_cam_rescan_all(struct ciss_softc *sc); 17375409Sachestatic void ciss_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb); 17421308Sachestatic void ciss_cam_action(struct cam_sim *sim, union ccb *ccb); 17521308Sachestatic int ciss_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio); 17621308Sachestatic int ciss_cam_emulate(struct ciss_softc *sc, struct ccb_scsiio *csio); 17721308Sachestatic void ciss_cam_poll(struct cam_sim *sim); 17821308Sachestatic void ciss_cam_complete(struct ciss_request *cr); 17975409Sachestatic void ciss_cam_complete_fixup(struct ciss_softc *sc, struct ccb_scsiio *csio); 18075409Sachestatic struct cam_periph *ciss_find_periph(struct ciss_softc *sc, 18121308Sache int bus, int target); 18221308Sachestatic int ciss_name_device(struct ciss_softc *sc, int bus, int target); 18375409Sache 18475409Sache/* periodic status monitoring */ 18521308Sachestatic void ciss_periodic(void *arg); 18621308Sachestatic void ciss_disable_adapter(struct ciss_softc *sc); 18721308Sachestatic void ciss_notify_event(struct ciss_softc *sc); 18821308Sachestatic void ciss_notify_complete(struct ciss_request *cr); 18921308Sachestatic int ciss_notify_abort(struct ciss_softc *sc); 19075409Sachestatic int ciss_notify_abort_bmic(struct ciss_softc *sc); 19175409Sachestatic void ciss_notify_hotplug(struct ciss_softc *sc, struct ciss_notify *cn); 19275409Sachestatic void ciss_notify_logical(struct ciss_softc *sc, struct ciss_notify *cn); 19375409Sachestatic void ciss_notify_physical(struct ciss_softc *sc, struct ciss_notify *cn); 19475409Sache 19575409Sache/* debugging output */ 19675409Sachestatic void ciss_print_request(struct ciss_request *cr); 197136759Speterstatic void ciss_print_ldrive(struct ciss_softc *sc, struct ciss_ldrive *ld); 198136759Speterstatic const char *ciss_name_ldrive_status(int status); 199157188Sachestatic int ciss_decode_ldrive_status(int status); 200157188Sachestatic const char *ciss_name_ldrive_org(int org); 201157188Sachestatic const char *ciss_name_command_status(int status); 202157188Sache 203157188Sache/* 204157188Sache * PCI bus interface. 205157188Sache */ 206157188Sachestatic device_method_t ciss_methods[] = { 207157188Sache /* Device interface */ 208165675Sache DEVMETHOD(device_probe, ciss_probe), 209157188Sache DEVMETHOD(device_attach, ciss_attach), 210157188Sache DEVMETHOD(device_detach, ciss_detach), 211157188Sache DEVMETHOD(device_shutdown, ciss_shutdown), 21221308Sache { 0, 0 } 21321308Sache}; 21421308Sache 21575409Sachestatic driver_t ciss_pci_driver = { 21675409Sache "ciss", 217136759Speter ciss_methods, 218136759Speter sizeof(struct ciss_softc) 21921308Sache}; 22021308Sache 22121308Sachestatic devclass_t ciss_devclass; 22221308SacheDRIVER_MODULE(ciss, pci, ciss_pci_driver, ciss_devclass, 0, 0); 22321308SacheMODULE_DEPEND(ciss, cam, 1, 1, 1); 22421308SacheMODULE_DEPEND(ciss, pci, 1, 1, 1); 22521308Sache 22621308Sache/* 22721308Sache * Control device interface. 228136759Speter */ 22921308Sachestatic d_open_t ciss_open; 230136759Speterstatic d_close_t ciss_close; 23121308Sachestatic d_ioctl_t ciss_ioctl; 232165675Sache 233136759Speterstatic struct cdevsw ciss_cdevsw = { 23421308Sache .d_version = D_VERSION, 23521308Sache .d_flags = 0, 236136759Speter .d_open = ciss_open, 23721308Sache .d_close = ciss_close, 23821308Sache .d_ioctl = ciss_ioctl, 23921308Sache .d_name = "ciss", 24021308Sache}; 241136759Speter 242136759Speter/* 243136759Speter * This tunable can be set at boot time and controls whether physical devices 244136759Speter * that are marked hidden by the firmware should be exposed anyways. 245136759Speter */ 246136759Speterstatic unsigned int ciss_expose_hidden_physical = 0; 24721308SacheTUNABLE_INT("hw.ciss.expose_hidden_physical", &ciss_expose_hidden_physical); 24821308Sache 24921308Sache/************************************************************************ 25021308Sache * CISS adapters amazingly don't have a defined programming interface 251119614Sache * value. (One could say some very despairing things about PCI and 25275409Sache * people just not getting the general idea.) So we are forced to 25375409Sache * stick with matching against subvendor/subdevice, and thus have to 254136759Speter * be updated for every new CISS adapter that appears. 25575409Sache */ 256165675Sache#define CISS_BOARD_SA5 (1<<0) 257136759Speter#define CISS_BOARD_SA5B (1<<1) 25821308Sache 25921308Sachestatic struct 26021308Sache{ 261165675Sache u_int16_t subvendor; 26221308Sache u_int16_t subdevice; 263165675Sache int flags; 264165675Sache char *desc; 26521308Sache} ciss_vendor_data[] = { 26621308Sache { 0x0e11, 0x4070, CISS_BOARD_SA5, "Compaq Smart Array 5300" }, 26721308Sache { 0x0e11, 0x4080, CISS_BOARD_SA5B, "Compaq Smart Array 5i" }, 26821308Sache { 0x0e11, 0x4082, CISS_BOARD_SA5B, "Compaq Smart Array 532" }, 26921308Sache { 0x0e11, 0x4083, CISS_BOARD_SA5B, "HP Smart Array 5312" }, 270165675Sache { 0x0e11, 0x4091, CISS_BOARD_SA5, "HP Smart Array 6i" }, 271157188Sache { 0x0e11, 0x409A, CISS_BOARD_SA5, "HP Smart Array 641" }, 27221308Sache { 0x0e11, 0x409B, CISS_BOARD_SA5, "HP Smart Array 642" }, 27321308Sache { 0x0e11, 0x409C, CISS_BOARD_SA5, "HP Smart Array 6400" }, 27421308Sache { 0x0e11, 0x409D, CISS_BOARD_SA5, "HP Smart Array 6400 EM" }, 27521308Sache { 0x103C, 0x3211, CISS_BOARD_SA5, "HP Smart Array E200i" }, 276136759Speter { 0x103C, 0x3212, CISS_BOARD_SA5, "HP Smart Array E200" }, 277136759Speter { 0x103C, 0x3213, CISS_BOARD_SA5, "HP Smart Array E200i" }, 278136759Speter { 0x103C, 0x3214, CISS_BOARD_SA5, "HP Smart Array E200i" }, 279136759Speter { 0x103C, 0x3215, CISS_BOARD_SA5, "HP Smart Array E200i" }, 280136759Speter { 0x103C, 0x3220, CISS_BOARD_SA5, "HP Smart Array" }, 281136759Speter { 0x103C, 0x3222, CISS_BOARD_SA5, "HP Smart Array" }, 282136759Speter { 0x103C, 0x3223, CISS_BOARD_SA5, "HP Smart Array P800" }, 283136759Speter { 0x103C, 0x3225, CISS_BOARD_SA5, "HP Smart Array P600" }, 284136759Speter { 0x103C, 0x3230, CISS_BOARD_SA5, "HP Smart Array" }, 285136759Speter { 0x103C, 0x3231, CISS_BOARD_SA5, "HP Smart Array" }, 286136759Speter { 0x103C, 0x3232, CISS_BOARD_SA5, "HP Smart Array" }, 287136759Speter { 0x103C, 0x3233, CISS_BOARD_SA5, "HP Smart Array" }, 288136759Speter { 0x103C, 0x3234, CISS_BOARD_SA5, "HP Smart Array P400" }, 289136759Speter { 0x103C, 0x3235, CISS_BOARD_SA5, "HP Smart Array P400i" }, 290136759Speter { 0x103C, 0x3236, CISS_BOARD_SA5, "HP Smart Array" }, 291136759Speter { 0x103C, 0x3237, CISS_BOARD_SA5, "HP Smart Array" }, 292136759Speter { 0x103C, 0x3238, CISS_BOARD_SA5, "HP Smart Array" }, 29375409Sache { 0x103C, 0x3239, CISS_BOARD_SA5, "HP Smart Array" }, 294136759Speter { 0x103C, 0x323A, CISS_BOARD_SA5, "HP Smart Array" }, 295136759Speter { 0x103C, 0x323B, CISS_BOARD_SA5, "HP Smart Array" }, 296136759Speter { 0x103C, 0x323C, CISS_BOARD_SA5, "HP Smart Array" }, 297136759Speter { 0, 0, 0, NULL } 298136759Speter}; 299136759Speter 300136759Speter/************************************************************************ 301136759Speter * Find a match for the device in our list of known adapters. 302136759Speter */ 303136759Speterstatic int 304136759Speterciss_lookup(device_t dev) 305136759Speter{ 306136759Speter int i; 307136759Speter 308136759Speter for (i = 0; ciss_vendor_data[i].desc != NULL; i++) 309136759Speter if ((pci_get_subvendor(dev) == ciss_vendor_data[i].subvendor) && 310136759Speter (pci_get_subdevice(dev) == ciss_vendor_data[i].subdevice)) { 31121308Sache return(i); 31221308Sache } 31321308Sache return(-1); 31475409Sache} 31575409Sache 31675409Sache/************************************************************************ 31721308Sache * Match a known CISS adapter. 31821308Sache */ 31921308Sachestatic int 32021308Sacheciss_probe(device_t dev) 32121308Sache{ 32275409Sache int i; 32375409Sache 324136759Speter i = ciss_lookup(dev); 325136759Speter if (i != -1) { 32621308Sache device_set_desc(dev, ciss_vendor_data[i].desc); 32721308Sache return(BUS_PROBE_DEFAULT); 32821308Sache } 32958314Sache return(ENOENT); 33058314Sache} 33158314Sache 33258314Sache/************************************************************************ 33358314Sache * Attach the driver to this adapter. 33458314Sache */ 33558314Sachestatic int 33658314Sacheciss_attach(device_t dev) 337136759Speter{ 33858314Sache struct ciss_softc *sc; 33958314Sache int i, error; 34058314Sache 34121308Sache debug_called(1); 34221308Sache 34321308Sache#ifdef CISS_DEBUG 34421308Sache /* print structure/union sizes */ 34521308Sache debug_struct(ciss_command); 34621308Sache debug_struct(ciss_header); 34721308Sache debug_union(ciss_device_address); 34821308Sache debug_struct(ciss_cdb); 34975409Sache debug_struct(ciss_report_cdb); 35075409Sache debug_struct(ciss_notify_cdb); 35121308Sache debug_struct(ciss_notify); 35221308Sache debug_struct(ciss_message_cdb); 35321308Sache debug_struct(ciss_error_info_pointer); 35421308Sache debug_struct(ciss_error_info); 35521308Sache debug_struct(ciss_sg_entry); 35621308Sache debug_struct(ciss_config_table); 35721308Sache debug_struct(ciss_bmic_cdb); 35821308Sache debug_struct(ciss_bmic_id_ldrive); 35921308Sache debug_struct(ciss_bmic_id_lstatus); 36021308Sache debug_struct(ciss_bmic_id_table); 36121308Sache debug_struct(ciss_bmic_id_pdrive); 36221308Sache debug_struct(ciss_bmic_blink_pdrive); 36321308Sache debug_struct(ciss_bmic_flush_cache); 36421308Sache debug_const(CISS_MAX_REQUESTS); 36521308Sache debug_const(CISS_MAX_LOGICAL); 36675409Sache debug_const(CISS_INTERRUPT_COALESCE_DELAY); 36775409Sache debug_const(CISS_INTERRUPT_COALESCE_COUNT); 36875409Sache debug_const(CISS_COMMAND_ALLOC_SIZE); 36921308Sache debug_const(CISS_COMMAND_SG_LENGTH); 370165675Sache 371157188Sache debug_type(cciss_pci_info_struct); 372157188Sache debug_type(cciss_coalint_struct); 37321308Sache debug_type(cciss_coalint_struct); 37421308Sache debug_type(NodeName_type); 37521308Sache debug_type(NodeName_type); 37621308Sache debug_type(Heartbeat_type); 37721308Sache debug_type(BusTypes_type); 37821308Sache debug_type(FirmwareVer_type); 37921308Sache debug_type(DriverVer_type); 38075409Sache debug_type(IOCTL_Command_struct); 38175409Sache#endif 38275409Sache 383136759Speter sc = device_get_softc(dev); 384136759Speter sc->ciss_dev = dev; 38521308Sache 386165675Sache /* 38775409Sache * Work out adapter type. 38821308Sache */ 38921308Sache i = ciss_lookup(dev); 39021308Sache if (i < 0) { 39121308Sache ciss_printf(sc, "unknown adapter type\n"); 39221308Sache error = ENXIO; 39375409Sache goto out; 39475409Sache } 395136759Speter if (ciss_vendor_data[i].flags & CISS_BOARD_SA5) { 396136759Speter sc->ciss_interrupt_mask = CISS_TL_SIMPLE_INTR_OPQ_SA5; 39721308Sache } else if (ciss_vendor_data[i].flags & CISS_BOARD_SA5B) { 39821308Sache sc->ciss_interrupt_mask = CISS_TL_SIMPLE_INTR_OPQ_SA5B; 39921308Sache } else { 40075409Sache /* really an error on our part */ 40175409Sache ciss_printf(sc, "unable to determine hardware type\n"); 402136759Speter error = ENXIO; 403136759Speter goto out; 40421308Sache } 405165675Sache 40675409Sache /* 40721308Sache * Do PCI-specific init. 40821308Sache */ 40921308Sache if ((error = ciss_init_pci(sc)) != 0) 41058314Sache goto out; 41158314Sache 41258314Sache /* 41358314Sache * Initialise driver queues. 41458314Sache */ 41558314Sache ciss_initq_free(sc); 41658314Sache ciss_initq_busy(sc); 41758314Sache ciss_initq_complete(sc); 41858314Sache ciss_initq_notify(sc); 41958314Sache mtx_init(&sc->ciss_mtx, "cissmtx", NULL, MTX_DEF); 42058314Sache callout_init_mtx(&sc->ciss_periodic, &sc->ciss_mtx, 0); 42158314Sache 42258314Sache /* 42358314Sache * Initalize device sysctls. 42458314Sache */ 425119614Sache ciss_init_sysctl(sc); 426119614Sache 42758314Sache /* 42858314Sache * Initialise command/request pool. 42958314Sache */ 43058314Sache if ((error = ciss_init_requests(sc)) != 0) 43158314Sache goto out; 43258314Sache 433119614Sache /* 434119614Sache * Get adapter information. 43558314Sache */ 43658314Sache if ((error = ciss_identify_adapter(sc)) != 0) 43758314Sache goto out; 43858314Sache 43958314Sache /* 44058314Sache * Find all the physical devices. 44158314Sache */ 44258314Sache if ((error = ciss_init_physical(sc)) != 0) 44358314Sache goto out; 44458314Sache 44558314Sache /* 44658314Sache * Build our private table of logical devices. 44758314Sache */ 44858314Sache if ((error = ciss_init_logical(sc)) != 0) 449119614Sache goto out; 450119614Sache 451119614Sache /* 45258314Sache * Enable interrupts so that the CAM scan can complete. 45358314Sache */ 45458314Sache CISS_TL_SIMPLE_ENABLE_INTERRUPTS(sc); 45558314Sache 45621308Sache /* 45721308Sache * Initialise the CAM interface. 45821308Sache */ 45921308Sache if ((error = ciss_cam_init(sc)) != 0) 46021308Sache goto out; 46121308Sache 462165675Sache /* 463136759Speter * Start the heartbeat routine and event chain. 46421308Sache */ 465119614Sache ciss_periodic(sc); 466119614Sache 467119614Sache /* 468119614Sache * Create the control device. 469119614Sache */ 470119614Sache sc->ciss_dev_t = make_dev(&ciss_cdevsw, device_get_unit(sc->ciss_dev), 471119614Sache UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR, 47221308Sache "ciss%d", device_get_unit(sc->ciss_dev)); 47321308Sache sc->ciss_dev_t->si_drv1 = sc; 47421308Sache 47521308Sache /* 47621308Sache * The adapter is running; synchronous commands can now sleep 47721308Sache * waiting for an interrupt to signal completion. 47821308Sache */ 479157188Sache sc->ciss_flags |= CISS_FLAG_RUNNING; 48021308Sache 48158314Sache ciss_spawn_notify_thread(sc); 48221308Sache 48321308Sache error = 0; 48421308Sache out: 48521308Sache if (error != 0) 486165675Sache ciss_free(sc); 48721308Sache return(error); 48821308Sache} 48921308Sache 49021308Sache/************************************************************************ 49121308Sache * Detach the driver from this adapter. 49221308Sache */ 493136759Speterstatic int 49421308Sacheciss_detach(device_t dev) 49521308Sache{ 49621308Sache struct ciss_softc *sc = device_get_softc(dev); 49721308Sache 498136759Speter debug_called(1); 49921308Sache 50021308Sache mtx_lock(&sc->ciss_mtx); 50121308Sache if (sc->ciss_flags & CISS_FLAG_CONTROL_OPEN) { 50221308Sache mtx_unlock(&sc->ciss_mtx); 50321308Sache return (EBUSY); 50421308Sache } 50521308Sache 50621308Sache /* flush adapter cache */ 50721308Sache ciss_flush_adapter(sc); 50821308Sache 50921308Sache /* release all resources. The mutex is released and freed here too. */ 51021308Sache ciss_free(sc); 51121308Sache 51221308Sache return(0); 51321308Sache} 51421308Sache 51521308Sache/************************************************************************ 516165675Sache * Prepare adapter for system shutdown. 51721308Sache */ 518165675Sachestatic int 51947563Sacheciss_shutdown(device_t dev) 52047563Sache{ 52147563Sache struct ciss_softc *sc = device_get_softc(dev); 522119614Sache 523119614Sache debug_called(1); 52447563Sache 525165675Sache mtx_lock(&sc->ciss_mtx); 526165675Sache /* flush adapter cache */ 52721308Sache ciss_flush_adapter(sc); 52821308Sache 529165675Sache if (sc->ciss_soft_reset) 53021308Sache ciss_soft_reset(sc); 53121308Sache mtx_unlock(&sc->ciss_mtx); 53221308Sache 53321308Sache return(0); 53421308Sache} 53521308Sache 53621308Sachestatic void 53721308Sacheciss_init_sysctl(struct ciss_softc *sc) 53821308Sache{ 53921308Sache 54058314Sache SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->ciss_dev), 54121308Sache SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ciss_dev)), 54221308Sache OID_AUTO, "soft_reset", CTLFLAG_RW, &sc->ciss_soft_reset, 0, ""); 54358314Sache} 54421308Sache 54521308Sache/************************************************************************ 54658314Sache * Perform PCI-specific attachment actions. 54721308Sache */ 54821308Sachestatic int 54921308Sacheciss_init_pci(struct ciss_softc *sc) 55021308Sache{ 551136759Speter uintptr_t cbase, csize, cofs; 55247563Sache int error; 55347563Sache 55447563Sache debug_called(1); 55547563Sache 556119614Sache /* 557119614Sache * Allocate register window first (we need this to find the config 55847563Sache * struct). 55921308Sache */ 56021308Sache error = ENXIO; 56121308Sache sc->ciss_regs_rid = CISS_TL_SIMPLE_BAR_REGS; 56275409Sache if ((sc->ciss_regs_resource = 56321308Sache bus_alloc_resource_any(sc->ciss_dev, SYS_RES_MEMORY, 56421308Sache &sc->ciss_regs_rid, RF_ACTIVE)) == NULL) { 56558314Sache ciss_printf(sc, "can't allocate register window\n"); 56658314Sache return(ENXIO); 56758314Sache } 56858314Sache sc->ciss_regs_bhandle = rman_get_bushandle(sc->ciss_regs_resource); 56958314Sache sc->ciss_regs_btag = rman_get_bustag(sc->ciss_regs_resource); 57058314Sache 57158314Sache /* 57258314Sache * Find the BAR holding the config structure. If it's not the one 573119614Sache * we already mapped for registers, map it too. 574119614Sache */ 57521308Sache sc->ciss_cfg_rid = CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_CFG_BAR) & 0xffff; 57621308Sache if (sc->ciss_cfg_rid != sc->ciss_regs_rid) { 57747563Sache if ((sc->ciss_cfg_resource = 57875409Sache bus_alloc_resource_any(sc->ciss_dev, SYS_RES_MEMORY, 57947563Sache &sc->ciss_cfg_rid, RF_ACTIVE)) == NULL) { 58058314Sache ciss_printf(sc, "can't allocate config window\n"); 58158314Sache return(ENXIO); 58258314Sache } 58358314Sache cbase = (uintptr_t)rman_get_virtual(sc->ciss_cfg_resource); 584119614Sache csize = rman_get_end(sc->ciss_cfg_resource) - 58558314Sache rman_get_start(sc->ciss_cfg_resource) + 1; 58647563Sache } else { 587119614Sache cbase = (uintptr_t)rman_get_virtual(sc->ciss_regs_resource); 58847563Sache csize = rman_get_end(sc->ciss_regs_resource) - 58947563Sache rman_get_start(sc->ciss_regs_resource) + 1; 59021308Sache } 591119614Sache cofs = CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_CFG_OFF); 592119614Sache 593119614Sache /* 594119614Sache * Use the base/size/offset values we just calculated to 595119614Sache * sanity-check the config structure. If it's OK, point to it. 596119614Sache */ 597119614Sache if ((cofs + sizeof(struct ciss_config_table)) > csize) { 598119614Sache ciss_printf(sc, "config table outside window\n"); 599119614Sache return(ENXIO); 600119614Sache } 601119614Sache sc->ciss_cfg = (struct ciss_config_table *)(cbase + cofs); 602119614Sache debug(1, "config struct at %p", sc->ciss_cfg); 603119614Sache 604119614Sache /* 605119614Sache * Validate the config structure. If we supported other transport 606119614Sache * methods, we could select amongst them at this point in time. 60721308Sache */ 60821308Sache if (strncmp(sc->ciss_cfg->signature, "CISS", 4)) { 60921308Sache ciss_printf(sc, "config signature mismatch (got '%c%c%c%c')\n", 610136759Speter sc->ciss_cfg->signature[0], sc->ciss_cfg->signature[1], 61126497Sache sc->ciss_cfg->signature[2], sc->ciss_cfg->signature[3]); 612136759Speter return(ENXIO); 613136759Speter } 614136759Speter 615136759Speter /* 616119614Sache * Put the board into simple mode, and tell it we're using the low 617119614Sache * 4GB of RAM. Set the default interrupt coalescing options. 618136759Speter */ 619119614Sache if (!(sc->ciss_cfg->supported_methods & CISS_TRANSPORT_METHOD_SIMPLE)) { 62021308Sache ciss_printf(sc, "adapter does not support 'simple' transport layer\n"); 62175409Sache return(ENXIO); 62275409Sache } 62375409Sache sc->ciss_cfg->requested_method = CISS_TRANSPORT_METHOD_SIMPLE; 62475409Sache sc->ciss_cfg->command_physlimit = 0; 62575409Sache sc->ciss_cfg->interrupt_coalesce_delay = CISS_INTERRUPT_COALESCE_DELAY; 62675409Sache sc->ciss_cfg->interrupt_coalesce_count = CISS_INTERRUPT_COALESCE_COUNT; 62726497Sache 62875409Sache#ifdef __i386__ 62921308Sache sc->ciss_cfg->host_driver |= CISS_DRIVER_SCSI_PREFETCH; 630165675Sache#endif 63175409Sache 63275409Sache if (ciss_update_config(sc)) { 63375409Sache ciss_printf(sc, "adapter refuses to accept config update (IDBR 0x%x)\n", 63475409Sache CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_IDBR)); 63575409Sache return(ENXIO); 636136759Speter } 637136759Speter if (!(sc->ciss_cfg->active_method != CISS_TRANSPORT_METHOD_SIMPLE)) { 638136759Speter ciss_printf(sc, 639165675Sache "adapter refuses to go into 'simple' transport mode (0x%x, 0x%x)\n", 640136759Speter sc->ciss_cfg->supported_methods, sc->ciss_cfg->active_method); 641165675Sache return(ENXIO); 642165675Sache } 643165675Sache 644136759Speter /* 645165675Sache * Wait for the adapter to come ready. 646165675Sache */ 647165675Sache if ((error = ciss_wait_adapter(sc)) != 0) 648165675Sache return(error); 649165675Sache 650165675Sache /* 651165675Sache * Turn off interrupts before we go routing anything. 652165675Sache */ 653165675Sache CISS_TL_SIMPLE_DISABLE_INTERRUPTS(sc); 654136759Speter 655165675Sache /* 656136759Speter * Allocate and set up our interrupt. 657165675Sache */ 658136759Speter sc->ciss_irq_rid = 0; 659165675Sache if ((sc->ciss_irq_resource = 660165675Sache bus_alloc_resource_any(sc->ciss_dev, SYS_RES_IRQ, &sc->ciss_irq_rid, 661165675Sache RF_ACTIVE | RF_SHAREABLE)) == NULL) { 662165675Sache ciss_printf(sc, "can't allocate interrupt\n"); 663165675Sache return(ENXIO); 664165675Sache } 665136759Speter if (bus_setup_intr(sc->ciss_dev, sc->ciss_irq_resource, 666136759Speter INTR_TYPE_CAM|INTR_MPSAFE, NULL, ciss_intr, sc, 667136759Speter &sc->ciss_intr)) { 668165675Sache ciss_printf(sc, "can't set up interrupt\n"); 669165675Sache return(ENXIO); 670165675Sache } 671119614Sache 672165675Sache /* 67326497Sache * Allocate the parent bus DMA tag appropriate for our PCI 67426497Sache * interface. 67575409Sache * 67675409Sache * Note that "simple" adapters can only address within a 32-bit 67775409Sache * span. 678165675Sache */ 67975409Sache if (bus_dma_tag_create(NULL, /* parent */ 68075409Sache 1, 0, /* alignment, boundary */ 68175409Sache BUS_SPACE_MAXADDR, /* lowaddr */ 68226497Sache BUS_SPACE_MAXADDR, /* highaddr */ 683119614Sache NULL, NULL, /* filter, filterarg */ 684119614Sache BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 685119614Sache CISS_COMMAND_SG_LENGTH, /* nsegments */ 686119614Sache BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 687119614Sache BUS_DMA_ALLOCNOW, /* flags */ 688119614Sache NULL, NULL, /* lockfunc, lockarg */ 689119614Sache &sc->ciss_parent_dmat)) { 690119614Sache ciss_printf(sc, "can't allocate parent DMA tag\n"); 691119614Sache return(ENOMEM); 692119614Sache } 693119614Sache 69426497Sache /* 695119614Sache * Create DMA tag for mapping buffers into adapter-addressable 69626497Sache * space. 69721308Sache */ 69821308Sache if (bus_dma_tag_create(sc->ciss_parent_dmat, /* parent */ 699119614Sache 1, 0, /* alignment, boundary */ 700119614Sache BUS_SPACE_MAXADDR, /* lowaddr */ 701119614Sache BUS_SPACE_MAXADDR, /* highaddr */ 702136759Speter NULL, NULL, /* filter, filterarg */ 703119614Sache MAXBSIZE, CISS_COMMAND_SG_LENGTH, /* maxsize, nsegments */ 704119614Sache BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 705119614Sache 0, /* flags */ 706119614Sache busdma_lock_mutex, &sc->ciss_mtx, /* lockfunc, lockarg */ 707119614Sache &sc->ciss_buffer_dmat)) { 708119614Sache ciss_printf(sc, "can't allocate buffer DMA tag\n"); 709119614Sache return(ENOMEM); 710119614Sache } 711136759Speter return(0); 712119614Sache} 713119614Sache 714119614Sache/************************************************************************ 715119614Sache * Wait for the adapter to come ready. 716136759Speter */ 717119614Sachestatic int 718119614Sacheciss_wait_adapter(struct ciss_softc *sc) 719119614Sache{ 720119614Sache int i; 72121308Sache 72221308Sache debug_called(1); 72321308Sache 724119614Sache /* 725119614Sache * Wait for the adapter to come ready. 72621308Sache */ 72721308Sache if (!(sc->ciss_cfg->active_method & CISS_TRANSPORT_METHOD_READY)) { 72821308Sache ciss_printf(sc, "waiting for adapter to come ready...\n"); 72921308Sache for (i = 0; !(sc->ciss_cfg->active_method & CISS_TRANSPORT_METHOD_READY); i++) { 73021308Sache DELAY(1000000); /* one second */ 731165675Sache if (i > 30) { 73221308Sache ciss_printf(sc, "timed out waiting for adapter to come ready\n"); 73321308Sache return(EIO); 73421308Sache } 735119614Sache } 736119614Sache } 737119614Sache return(0); 73821308Sache} 739119614Sache 74021308Sache/************************************************************************ 74121308Sache * Flush the adapter cache. 74221308Sache */ 74321308Sachestatic int 74421308Sacheciss_flush_adapter(struct ciss_softc *sc) 74575409Sache{ 74621308Sache struct ciss_request *cr; 74775409Sache struct ciss_bmic_flush_cache *cbfc; 74858314Sache int error, command_status; 74921308Sache 75021308Sache debug_called(1); 75121308Sache 75221308Sache cr = NULL; 75321308Sache cbfc = NULL; 75421308Sache 75521308Sache /* 75621308Sache * Build a BMIC request to flush the cache. We don't disable 75721308Sache * it, as we may be going to do more I/O (eg. we are emulating 75821308Sache * the Synchronise Cache command). 75921308Sache */ 76021308Sache if ((cbfc = malloc(sizeof(*cbfc), CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO)) == NULL) { 76121308Sache error = ENOMEM; 76221308Sache goto out; 76321308Sache } 76421308Sache if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_FLUSH_CACHE, 76521308Sache (void **)&cbfc, sizeof(*cbfc))) != 0) 76675409Sache goto out; 76747563Sache 76847563Sache /* 76921308Sache * Submit the request and wait for it to complete. 77047563Sache */ 77147563Sache if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) { 77247563Sache ciss_printf(sc, "error sending BMIC FLUSH_CACHE command (%d)\n", error); 77321308Sache goto out; 77475409Sache } 77521308Sache 77621308Sache /* 77775409Sache * Check response. 77858314Sache */ 77921308Sache ciss_report_request(cr, &command_status, NULL); 78021308Sache switch(command_status) { 78121308Sache case CISS_CMD_STATUS_SUCCESS: 78221308Sache break; 78321308Sache default: 78421308Sache ciss_printf(sc, "error flushing cache (%s)\n", 78521308Sache ciss_name_command_status(command_status)); 78621308Sache error = EIO; 78721308Sache goto out; 78821308Sache } 78921308Sache 79021308Sacheout: 79121308Sache if (cbfc != NULL) 79275409Sache free(cbfc, CISS_MALLOC_CLASS); 79347563Sache if (cr != NULL) 79447563Sache ciss_release_request(cr); 79558314Sache return(error); 79647563Sache} 79747563Sache 79847563Sachestatic void 79921308Sacheciss_soft_reset(struct ciss_softc *sc) 80021308Sache{ 80121308Sache struct ciss_request *cr = NULL; 80221308Sache struct ciss_command *cc; 80321308Sache int i, error = 0; 80421308Sache 80521308Sache for (i = 0; i < sc->ciss_max_logical_bus; i++) { 80621308Sache /* only reset proxy controllers */ 80721308Sache if (sc->ciss_controllers[i].physical.bus == 0) 808119614Sache continue; 809119614Sache 810119614Sache if ((error = ciss_get_request(sc, &cr)) != 0) 811119614Sache break; 812119614Sache 813119614Sache if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_SOFT_RESET, 814119614Sache NULL, 0)) != 0) 815119614Sache break; 816119614Sache 817119614Sache cc = CISS_FIND_COMMAND(cr); 818119614Sache cc->header.address = sc->ciss_controllers[i]; 819119614Sache 820119614Sache if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) 821119614Sache break; 822119614Sache 823119614Sache ciss_release_request(cr); 824119614Sache } 825165675Sache 826119614Sache if (error) 827119614Sache ciss_printf(sc, "error resetting controller (%d)\n", error); 828119614Sache 829119614Sache if (cr != NULL) 830119614Sache ciss_release_request(cr); 831119614Sache} 832119614Sache 833119614Sache/************************************************************************ 834119614Sache * Allocate memory for the adapter command structures, initialise 835119614Sache * the request structures. 836119614Sache * 837119614Sache * Note that the entire set of commands are allocated in a single 838119614Sache * contiguous slab. 83921308Sache */ 84021308Sachestatic int 841119614Sacheciss_init_requests(struct ciss_softc *sc) 84221308Sache{ 843119614Sache struct ciss_request *cr; 844119614Sache int i; 845119614Sache 846119614Sache debug_called(1); 847119614Sache 848119614Sache /* 849119614Sache * Calculate the number of request structures/commands we are 850119614Sache * going to provide for this adapter. 851119614Sache */ 852119614Sache sc->ciss_max_requests = min(CISS_MAX_REQUESTS, sc->ciss_cfg->max_outstanding_commands); 853119614Sache 85421308Sache if (bootverbose) 85521308Sache ciss_printf(sc, "using %d of %d available commands\n", 856165675Sache sc->ciss_max_requests, sc->ciss_cfg->max_outstanding_commands); 85721308Sache 858165675Sache /* 85921308Sache * Create the DMA tag for commands. 86021308Sache */ 86121308Sache if (bus_dma_tag_create(sc->ciss_parent_dmat, /* parent */ 86221308Sache 1, 0, /* alignment, boundary */ 86358314Sache BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 86421308Sache BUS_SPACE_MAXADDR, /* highaddr */ 86521308Sache NULL, NULL, /* filter, filterarg */ 86621308Sache CISS_COMMAND_ALLOC_SIZE * 867165675Sache sc->ciss_max_requests, 1, /* maxsize, nsegments */ 86875409Sache BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 86921308Sache BUS_DMA_ALLOCNOW, /* flags */ 87021308Sache NULL, NULL, /* lockfunc, lockarg */ 87121308Sache &sc->ciss_command_dmat)) { 87221308Sache ciss_printf(sc, "can't allocate command DMA tag\n"); 87321308Sache return(ENOMEM); 87421308Sache } 87521308Sache /* 87621308Sache * Allocate memory and make it available for DMA. 87721308Sache */ 87821308Sache if (bus_dmamem_alloc(sc->ciss_command_dmat, (void **)&sc->ciss_command, 87975409Sache BUS_DMA_NOWAIT, &sc->ciss_command_map)) { 88021308Sache ciss_printf(sc, "can't allocate command memory\n"); 881157188Sache return(ENOMEM); 88221308Sache } 88321308Sache bus_dmamap_load(sc->ciss_command_dmat, sc->ciss_command_map, sc->ciss_command, 88421308Sache CISS_COMMAND_ALLOC_SIZE * sc->ciss_max_requests, 88521308Sache ciss_command_map_helper, sc, 0); 88621308Sache bzero(sc->ciss_command, CISS_COMMAND_ALLOC_SIZE * sc->ciss_max_requests); 88721308Sache 88821308Sache /* 88921308Sache * Set up the request and command structures, push requests onto 89075409Sache * the free queue. 891119614Sache */ 892119614Sache for (i = 1; i < sc->ciss_max_requests; i++) { 893119614Sache cr = &sc->ciss_request[i]; 894119614Sache cr->cr_sc = sc; 895119614Sache cr->cr_tag = i; 896119614Sache bus_dmamap_create(sc->ciss_buffer_dmat, 0, &cr->cr_datamap); 89721308Sache ciss_enqueue_free(cr); 89821308Sache } 89921308Sache return(0); 90021308Sache} 90121308Sache 90221308Sachestatic void 90321308Sacheciss_command_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error) 90421308Sache{ 90521308Sache struct ciss_softc *sc = (struct ciss_softc *)arg; 90621308Sache 90721308Sache sc->ciss_command_phys = segs->ds_addr; 90821308Sache} 90921308Sache 91021308Sache/************************************************************************ 91121308Sache * Identify the adapter, print some information about it. 912165675Sache */ 913165675Sachestatic int 914157188Sacheciss_identify_adapter(struct ciss_softc *sc) 915157188Sache{ 91621308Sache struct ciss_request *cr; 91721308Sache int error, command_status; 91821308Sache 919157188Sache debug_called(1); 920157188Sache 921157188Sache cr = NULL; 922157188Sache 923157188Sache /* 924157188Sache * Get a request, allocate storage for the adapter data. 925157188Sache */ 926165675Sache if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_ID_CTLR, 927165675Sache (void **)&sc->ciss_id, 928165675Sache sizeof(*sc->ciss_id))) != 0) 929165675Sache goto out; 930165675Sache 931157188Sache /* 932157188Sache * Submit the request and wait for it to complete. 933157188Sache */ 934157188Sache if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) { 935157188Sache ciss_printf(sc, "error sending BMIC ID_CTLR command (%d)\n", error); 936157188Sache goto out; 937157188Sache } 93821308Sache 93921308Sache /* 94021308Sache * Check response. 94121308Sache */ 94221308Sache ciss_report_request(cr, &command_status, NULL); 94321308Sache switch(command_status) { 94421308Sache case CISS_CMD_STATUS_SUCCESS: /* buffer right size */ 94521308Sache break; 94621308Sache case CISS_CMD_STATUS_DATA_UNDERRUN: 94721308Sache case CISS_CMD_STATUS_DATA_OVERRUN: 94821308Sache ciss_printf(sc, "data over/underrun reading adapter information\n"); 949157188Sache default: 950157188Sache ciss_printf(sc, "error reading adapter information (%s)\n", 951157188Sache ciss_name_command_status(command_status)); 952157188Sache error = EIO; 95321308Sache goto out; 95426497Sache } 95521308Sache 95621308Sache /* sanity-check reply */ 95721308Sache if (!sc->ciss_id->big_map_supported) { 95821308Sache ciss_printf(sc, "adapter does not support BIG_MAP\n"); 95921308Sache error = ENXIO; 96021308Sache goto out; 96121308Sache } 96221308Sache 96321308Sache#if 0 96421308Sache /* XXX later revisions may not need this */ 96521308Sache sc->ciss_flags |= CISS_FLAG_FAKE_SYNCH; 96621308Sache#endif 96721308Sache 96821308Sache /* XXX only really required for old 5300 adapters? */ 96921308Sache sc->ciss_flags |= CISS_FLAG_BMIC_ABORT; 97021308Sache 97121308Sache /* print information */ 97226497Sache if (bootverbose) { 97375409Sache#if 0 /* XXX proxy volumes??? */ 97421308Sache ciss_printf(sc, " %d logical drive%s configured\n", 97521308Sache sc->ciss_id->configured_logical_drives, 97621308Sache (sc->ciss_id->configured_logical_drives == 1) ? "" : "s"); 97721308Sache#endif 97821308Sache ciss_printf(sc, " firmware %4.4s\n", sc->ciss_id->running_firmware_revision); 97921308Sache ciss_printf(sc, " %d SCSI channels\n", sc->ciss_id->scsi_bus_count); 98021308Sache 98121308Sache ciss_printf(sc, " signature '%.4s'\n", sc->ciss_cfg->signature); 98221308Sache ciss_printf(sc, " valence %d\n", sc->ciss_cfg->valence); 98321308Sache ciss_printf(sc, " supported I/O methods 0x%b\n", 98475409Sache sc->ciss_cfg->supported_methods, 98547563Sache "\20\1READY\2simple\3performant\4MEMQ\n"); 98647563Sache ciss_printf(sc, " active I/O method 0x%b\n", 98747563Sache sc->ciss_cfg->active_method, "\20\2simple\3performant\4MEMQ\n"); 988157188Sache ciss_printf(sc, " 4G page base 0x%08x\n", 98947563Sache sc->ciss_cfg->command_physlimit); 99021308Sache ciss_printf(sc, " interrupt coalesce delay %dus\n", 99121308Sache sc->ciss_cfg->interrupt_coalesce_delay); 99221308Sache ciss_printf(sc, " interrupt coalesce count %d\n", 99321308Sache sc->ciss_cfg->interrupt_coalesce_count); 99421308Sache ciss_printf(sc, " max outstanding commands %d\n", 99521308Sache sc->ciss_cfg->max_outstanding_commands); 99621308Sache ciss_printf(sc, " bus types 0x%b\n", sc->ciss_cfg->bus_types, 99775409Sache "\20\1ultra2\2ultra3\10fibre1\11fibre2\n"); 99821308Sache ciss_printf(sc, " server name '%.16s'\n", sc->ciss_cfg->server_name); 999165675Sache ciss_printf(sc, " heartbeat 0x%x\n", sc->ciss_cfg->heartbeat); 1000165675Sache } 1001165675Sache 1002165675Sacheout: 1003165675Sache if (error) { 100421308Sache if (sc->ciss_id != NULL) { 100558314Sache free(sc->ciss_id, CISS_MALLOC_CLASS); 100658314Sache sc->ciss_id = NULL; 100758314Sache } 100875409Sache } 100975409Sache if (cr != NULL) 101058314Sache ciss_release_request(cr); 101121308Sache return(error); 1012119614Sache} 1013157188Sache 1014119614Sache/************************************************************************ 1015119614Sache * Helper routine for generating a list of logical and physical luns. 101621308Sache */ 101721308Sachestatic struct ciss_lun_report * 101821308Sacheciss_report_luns(struct ciss_softc *sc, int opcode, int nunits) 101921308Sache{ 102021308Sache struct ciss_request *cr; 102121308Sache struct ciss_command *cc; 1022165675Sache struct ciss_report_cdb *crc; 1023165675Sache struct ciss_lun_report *cll; 102421308Sache int command_status; 1025157188Sache int report_size; 1026157188Sache int error = 0; 1027157188Sache 1028157188Sache debug_called(1); 1029157188Sache 103021308Sache cr = NULL; 103121308Sache cll = NULL; 103221308Sache 103321308Sache /* 103421308Sache * Get a request, allocate storage for the address list. 1035165675Sache */ 1036119614Sache if ((error = ciss_get_request(sc, &cr)) != 0) 1037157188Sache goto out; 1038119614Sache report_size = sizeof(*cll) + nunits * sizeof(union ciss_device_address); 1039157188Sache if ((cll = malloc(report_size, CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO)) == NULL) { 1040157188Sache ciss_printf(sc, "can't allocate memory for lun report\n"); 1041157188Sache error = ENOMEM; 1042157188Sache goto out; 1043157188Sache } 1044157188Sache 104521308Sache /* 104621308Sache * Build the Report Logical/Physical LUNs command. 1047157188Sache */ 1048157188Sache cc = CISS_FIND_COMMAND(cr); 1049157188Sache cr->cr_data = cll; 1050157188Sache cr->cr_length = report_size; 1051119614Sache cr->cr_flags = CISS_REQ_DATAIN; 105221308Sache 1053119614Sache cc->header.address.physical.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL; 1054119614Sache cc->header.address.physical.bus = 0; 105521308Sache cc->header.address.physical.target = 0; 105621308Sache cc->cdb.cdb_length = sizeof(*crc); 105721308Sache cc->cdb.type = CISS_CDB_TYPE_COMMAND; 105821308Sache cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE; 105921308Sache cc->cdb.direction = CISS_CDB_DIRECTION_READ; 106021308Sache cc->cdb.timeout = 30; /* XXX better suggestions? */ 106121308Sache 106221308Sache crc = (struct ciss_report_cdb *)&(cc->cdb.cdb[0]); 106321308Sache bzero(crc, sizeof(*crc)); 106421308Sache crc->opcode = opcode; 106521308Sache crc->length = htonl(report_size); /* big-endian field */ 106621308Sache cll->list_size = htonl(report_size - sizeof(*cll)); /* big-endian field */ 106721308Sache 106821308Sache /* 1069165675Sache * Submit the request and wait for it to complete. (timeout 107075409Sache * here should be much greater than above) 107121308Sache */ 107247563Sache if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) { 1073165675Sache ciss_printf(sc, "error sending %d LUN command (%d)\n", opcode, error); 107475409Sache goto out; 107521308Sache } 107621308Sache 107747563Sache /* 107821308Sache * Check response. Note that data over/underrun is OK. 107921308Sache */ 108047563Sache ciss_report_request(cr, &command_status, NULL); 108147563Sache switch(command_status) { 108275409Sache case CISS_CMD_STATUS_SUCCESS: /* buffer right size */ 108321308Sache case CISS_CMD_STATUS_DATA_UNDERRUN: /* buffer too large, not bad */ 1084165675Sache break; 108521308Sache case CISS_CMD_STATUS_DATA_OVERRUN: 108621308Sache ciss_printf(sc, "WARNING: more units than driver limit (%d)\n", 108721308Sache CISS_MAX_LOGICAL); 108821308Sache break; 108921308Sache default: 109021308Sache ciss_printf(sc, "error detecting logical drive configuration (%s)\n", 109121308Sache ciss_name_command_status(command_status)); 109275409Sache error = EIO; 109347563Sache goto out; 109421308Sache } 109521308Sache ciss_release_request(cr); 109621308Sache cr = NULL; 109721308Sache 1098165675Sacheout: 109921308Sache if (cr != NULL) 110021308Sache ciss_release_request(cr); 110121308Sache if (error && cll != NULL) { 110221308Sache free(cll, CISS_MALLOC_CLASS); 110347563Sache cll = NULL; 110421308Sache } 110521308Sache return(cll); 110621308Sache} 110721308Sache 110821308Sache/************************************************************************ 110921308Sache * Find logical drives on the adapter. 111021308Sache */ 111147563Sachestatic int 111247563Sacheciss_init_logical(struct ciss_softc *sc) 111347563Sache{ 111475409Sache struct ciss_lun_report *cll; 111521308Sache int error = 0, i, j; 111647563Sache int ndrives; 111721308Sache 111821308Sache debug_called(1); 111921308Sache 112021308Sache cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_LOGICAL_LUNS, 112121308Sache CISS_MAX_LOGICAL); 112221308Sache if (cll == NULL) { 112321308Sache error = ENXIO; 112475409Sache goto out; 112575409Sache } 112621308Sache 112721308Sache /* sanity-check reply */ 112821308Sache ndrives = (ntohl(cll->list_size) / sizeof(union ciss_device_address)); 112921308Sache if ((ndrives < 0) || (ndrives >= CISS_MAX_LOGICAL)) { 113021308Sache ciss_printf(sc, "adapter claims to report absurd number of logical drives (%d > %d)\n", 113121308Sache ndrives, CISS_MAX_LOGICAL); 113221308Sache error = ENXIO; 113321308Sache goto out; 113421308Sache } 113521308Sache 113675409Sache /* 113726497Sache * Save logical drive information. 113821308Sache */ 113921308Sache if (bootverbose) { 114075409Sache ciss_printf(sc, "%d logical drive%s\n", 114175409Sache ndrives, (ndrives > 1 || ndrives == 0) ? "s" : ""); 114221308Sache } 1143165675Sache 114421308Sache sc->ciss_logical = 114521308Sache malloc(sc->ciss_max_logical_bus * sizeof(struct ciss_ldrive *), 114621308Sache CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO); 114721308Sache if (sc->ciss_logical == NULL) { 114821308Sache error = ENXIO; 114921308Sache goto out; 115021308Sache } 115175409Sache 115258314Sache for (i = 0; i <= sc->ciss_max_logical_bus; i++) { 115358314Sache sc->ciss_logical[i] = 115421308Sache malloc(CISS_MAX_LOGICAL * sizeof(struct ciss_ldrive), 115575409Sache CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO); 115658314Sache if (sc->ciss_logical[i] == NULL) { 115721308Sache error = ENXIO; 115821308Sache goto out; 115958314Sache } 116058314Sache 116158314Sache for (j = 0; j < CISS_MAX_LOGICAL; j++) 116258314Sache sc->ciss_logical[i][j].cl_status = CISS_LD_NONEXISTENT; 116321308Sache } 116421308Sache 116521308Sache 116621308Sache for (i = 0; i < CISS_MAX_LOGICAL; i++) { 116721308Sache if (i < ndrives) { 116821308Sache struct ciss_ldrive *ld; 116921308Sache int bus, target; 117021308Sache 117121308Sache bus = CISS_LUN_TO_BUS(cll->lun[i].logical.lun); 117221308Sache target = CISS_LUN_TO_TARGET(cll->lun[i].logical.lun); 117321308Sache ld = &sc->ciss_logical[bus][target]; 117421308Sache 117521308Sache ld->cl_address = cll->lun[i]; 117621308Sache ld->cl_controller = &sc->ciss_controllers[bus]; 117721308Sache if (ciss_identify_logical(sc, ld) != 0) 117821308Sache continue; 117921308Sache /* 118021308Sache * If the drive has had media exchanged, we should bring it online. 118121308Sache */ 118221308Sache if (ld->cl_lstatus->media_exchanged) 118321308Sache ciss_accept_media(sc, ld); 118421308Sache 118521308Sache } 118621308Sache } 118747563Sache 118821308Sache out: 118921308Sache if (cll != NULL) 119021308Sache free(cll, CISS_MALLOC_CLASS); 119121308Sache return(error); 119221308Sache} 119321308Sache 119421308Sachestatic int 119521308Sacheciss_init_physical(struct ciss_softc *sc) 119621308Sache{ 119721308Sache struct ciss_lun_report *cll; 1198119614Sache int error = 0, i; 1199119614Sache int nphys; 1200119614Sache int bus, target; 1201165675Sache 1202119614Sache debug_called(1); 120321308Sache 120421308Sache bus = 0; 120521308Sache target = 0; 120621308Sache 120721308Sache cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_PHYSICAL_LUNS, 120821308Sache CISS_MAX_PHYSICAL); 1209157188Sache if (cll == NULL) { 1210157188Sache error = ENXIO; 1211157188Sache goto out; 1212157188Sache } 121375409Sache 1214119614Sache nphys = (ntohl(cll->list_size) / sizeof(union ciss_device_address)); 121521308Sache 1216119614Sache if (bootverbose) { 1217119614Sache ciss_printf(sc, "%d physical device%s\n", 1218119614Sache nphys, (nphys > 1 || nphys == 0) ? "s" : ""); 1219119614Sache } 1220119614Sache 1221119614Sache /* 1222119614Sache * Figure out the bus mapping. 1223119614Sache * Logical buses include both the local logical bus for local arrays and 1224119614Sache * proxy buses for remote arrays. Physical buses are numbered by the 1225119614Sache * controller and represent physical buses that hold physical devices. 1226119614Sache * We shift these bus numbers so that everything fits into a single flat 1227119614Sache * numbering space for CAM. Logical buses occupy the first 32 CAM bus 1228119614Sache * numbers, and the physical bus numbers are shifted to be above that. 1229119614Sache * This results in the various driver arrays being indexed as follows: 1230119614Sache * 1231119614Sache * ciss_controllers[] - indexed by logical bus 1232136759Speter * ciss_cam_sim[] - indexed by both logical and physical, with physical 1233119614Sache * being shifted by 32. 1234119614Sache * ciss_logical[][] - indexed by logical bus 1235119614Sache * ciss_physical[][] - indexed by physical bus 1236119614Sache * 1237136759Speter * XXX This is getting more and more hackish. CISS really doesn't play 1238119614Sache * well with a standard SCSI model; devices are addressed via magic 1239119614Sache * cookies, not via b/t/l addresses. Since there is no way to store 1240119614Sache * the cookie in the CAM device object, we have to keep these lookup 1241119614Sache * tables handy so that the devices can be found quickly at the cost 1242119614Sache * of wasting memory and having a convoluted lookup scheme. This 1243119614Sache * driver should probably be converted to block interface. 1244119614Sache */ 1245119614Sache /* 1246119614Sache * If the L2 and L3 SCSI addresses are 0, this signifies a proxy 1247119614Sache * controller. A proxy controller is another physical controller 1248119614Sache * behind the primary PCI controller. We need to know about this 1249119614Sache * so that BMIC commands can be properly targeted. There can be 1250119614Sache * proxy controllers attached to a single PCI controller, so 1251119614Sache * find the highest numbered one so the array can be properly 1252119614Sache * sized. 1253119614Sache */ 1254136759Speter sc->ciss_max_logical_bus = 1; 1255119614Sache for (i = 0; i < nphys; i++) { 1256119614Sache if (cll->lun[i].physical.extra_address == 0) { 1257119614Sache bus = cll->lun[i].physical.bus; 1258119614Sache sc->ciss_max_logical_bus = max(sc->ciss_max_logical_bus, bus) + 1; 1259119614Sache } else { 1260119614Sache bus = CISS_EXTRA_BUS2(cll->lun[i].physical.extra_address); 1261119614Sache sc->ciss_max_physical_bus = max(sc->ciss_max_physical_bus, bus); 1262119614Sache } 1263119614Sache } 1264119614Sache 1265119614Sache sc->ciss_controllers = 1266119614Sache malloc(sc->ciss_max_logical_bus * sizeof (union ciss_device_address), 1267119614Sache CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO); 1268119614Sache 1269119614Sache if (sc->ciss_controllers == NULL) { 127021308Sache ciss_printf(sc, "Could not allocate memory for controller map\n"); 1271119614Sache error = ENOMEM; 1272119614Sache goto out; 1273119614Sache } 1274119614Sache 1275119614Sache /* setup a map of controller addresses */ 1276119614Sache for (i = 0; i < nphys; i++) { 1277157188Sache if (cll->lun[i].physical.extra_address == 0) { 1278119614Sache sc->ciss_controllers[cll->lun[i].physical.bus] = cll->lun[i]; 1279119614Sache } 1280119614Sache } 1281119614Sache 128221308Sache sc->ciss_physical = 1283119614Sache malloc(sc->ciss_max_physical_bus * sizeof(struct ciss_pdrive *), 128421308Sache CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO); 128521308Sache if (sc->ciss_physical == NULL) { 1286119614Sache ciss_printf(sc, "Could not allocate memory for physical device map\n"); 1287119614Sache error = ENOMEM; 1288119614Sache goto out; 1289136759Speter } 1290136759Speter 1291136759Speter for (i = 0; i < sc->ciss_max_physical_bus; i++) { 1292136759Speter sc->ciss_physical[i] = 1293119614Sache malloc(sizeof(struct ciss_pdrive) * CISS_MAX_PHYSTGT, 1294136759Speter CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO); 1295136759Speter if (sc->ciss_physical[i] == NULL) { 1296119614Sache ciss_printf(sc, "Could not allocate memory for target map\n"); 1297136759Speter error = ENOMEM; 1298136759Speter goto out; 1299136759Speter } 1300136759Speter } 1301136759Speter 1302136759Speter ciss_filter_physical(sc, cll); 1303136759Speter 1304136759Speterout: 1305136759Speter if (cll != NULL) 1306136759Speter free(cll, CISS_MALLOC_CLASS); 1307136759Speter 1308136759Speter return(error); 1309136759Speter} 1310136759Speter 1311136759Speterstatic int 1312136759Speterciss_filter_physical(struct ciss_softc *sc, struct ciss_lun_report *cll) 1313136759Speter{ 1314136759Speter u_int32_t ea; 1315136759Speter int i, nphys; 1316136759Speter int bus, target; 1317136759Speter 1318136759Speter nphys = (ntohl(cll->list_size) / sizeof(union ciss_device_address)); 1319136759Speter for (i = 0; i < nphys; i++) { 1320136759Speter if (cll->lun[i].physical.extra_address == 0) 1321119614Sache continue; 1322119614Sache 1323119614Sache /* 132421308Sache * Filter out devices that we don't want. Level 3 LUNs could 132521308Sache * probably be supported, but the docs don't give enough of a 132621308Sache * hint to know how. 132721308Sache * 132821308Sache * The mode field of the physical address is likely set to have 132921308Sache * hard disks masked out. Honor it unless the user has overridden 133021308Sache * us with the tunable. We also munge the inquiry data for these 133121308Sache * disks so that they only show up as passthrough devices. Keeping 133221308Sache * them visible in this fashion is useful for doing things like 133321308Sache * flashing firmware. 133421308Sache */ 133521308Sache ea = cll->lun[i].physical.extra_address; 133621308Sache if ((CISS_EXTRA_BUS3(ea) != 0) || (CISS_EXTRA_TARGET3(ea) != 0) || 133721308Sache (CISS_EXTRA_MODE2(ea) == 0x3)) 133821308Sache continue; 133921308Sache if ((ciss_expose_hidden_physical == 0) && 1340119614Sache (cll->lun[i].physical.mode == CISS_HDR_ADDRESS_MODE_MASK_PERIPHERAL)) 1341119614Sache continue; 1342119614Sache 1343119614Sache /* 1344119614Sache * Note: CISS firmware numbers physical busses starting at '1', not 1345119614Sache * '0'. This numbering is internal to the firmware and is only 1346119614Sache * used as a hint here. 1347119614Sache */ 1348119614Sache bus = CISS_EXTRA_BUS2(ea) - 1; 1349119614Sache target = CISS_EXTRA_TARGET2(ea); 1350119614Sache sc->ciss_physical[bus][target].cp_address = cll->lun[i]; 1351136759Speter sc->ciss_physical[bus][target].cp_online = 1; 1352136759Speter } 1353119614Sache 1354119614Sache return (0); 1355136759Speter} 1356119614Sache 1357119614Sachestatic int 1358119614Sacheciss_inquiry_logical(struct ciss_softc *sc, struct ciss_ldrive *ld) 1359119614Sache{ 1360119614Sache struct ciss_request *cr; 1361119614Sache struct ciss_command *cc; 1362119614Sache struct scsi_inquiry *inq; 1363119614Sache int error; 1364119614Sache int command_status; 1365119614Sache 1366119614Sache cr = NULL; 1367119614Sache 1368119614Sache bzero(&ld->cl_geometry, sizeof(ld->cl_geometry)); 1369119614Sache 137021308Sache if ((error = ciss_get_request(sc, &cr)) != 0) 137121308Sache goto out; 137221308Sache 137321308Sache cc = CISS_FIND_COMMAND(cr); 137421308Sache cr->cr_data = &ld->cl_geometry; 137521308Sache cr->cr_length = sizeof(ld->cl_geometry); 137621308Sache cr->cr_flags = CISS_REQ_DATAIN; 137721308Sache 137821308Sache cc->header.address = ld->cl_address; 1379119614Sache cc->cdb.cdb_length = 6; 1380119614Sache cc->cdb.type = CISS_CDB_TYPE_COMMAND; 1381119614Sache cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE; 138221308Sache cc->cdb.direction = CISS_CDB_DIRECTION_READ; 138321308Sache cc->cdb.timeout = 30; 138421308Sache 138521308Sache inq = (struct scsi_inquiry *)&(cc->cdb.cdb[0]); 138621308Sache inq->opcode = INQUIRY; 138721308Sache inq->byte2 = SI_EVPD; 1388119614Sache inq->page_code = CISS_VPD_LOGICAL_DRIVE_GEOMETRY; 1389119614Sache inq->length = sizeof(ld->cl_geometry); 1390119614Sache 1391119614Sache if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) { 1392119614Sache ciss_printf(sc, "error getting geometry (%d)\n", error); 1393119614Sache goto out; 139421308Sache } 1395119614Sache 139621308Sache ciss_report_request(cr, &command_status, NULL); 139721308Sache switch(command_status) { 1398119614Sache case CISS_CMD_STATUS_SUCCESS: 1399119614Sache case CISS_CMD_STATUS_DATA_UNDERRUN: 1400119614Sache break; 1401119614Sache case CISS_CMD_STATUS_DATA_OVERRUN: 1402119614Sache ciss_printf(sc, "WARNING: Data overrun\n"); 1403119614Sache break; 140421308Sache default: 1405119614Sache ciss_printf(sc, "Error detecting logical drive geometry (%s)\n", 1406119614Sache ciss_name_command_status(command_status)); 1407119614Sache break; 1408119614Sache } 1409119614Sache 1410119614Sacheout: 141121308Sache if (cr != NULL) 141221308Sache ciss_release_request(cr); 141321308Sache return(error); 141421308Sache} 141521308Sache/************************************************************************ 141621308Sache * Identify a logical drive, initialise state related to it. 141721308Sache */ 1418157188Sachestatic int 141921308Sacheciss_identify_logical(struct ciss_softc *sc, struct ciss_ldrive *ld) 142021308Sache{ 142121308Sache struct ciss_request *cr; 142221308Sache struct ciss_command *cc; 142321308Sache struct ciss_bmic_cdb *cbc; 142421308Sache int error, command_status; 142521308Sache 142621308Sache debug_called(1); 142721308Sache 142821308Sache cr = NULL; 142921308Sache 143021308Sache /* 143121308Sache * Build a BMIC request to fetch the drive ID. 143221308Sache */ 143321308Sache if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_ID_LDRIVE, 1434165675Sache (void **)&ld->cl_ldrive, 143521308Sache sizeof(*ld->cl_ldrive))) != 0) 143621308Sache goto out; 143775409Sache cc = CISS_FIND_COMMAND(cr); 1438165675Sache cc->header.address = *ld->cl_controller; /* target controller */ 143921308Sache cbc = (struct ciss_bmic_cdb *)&(cc->cdb.cdb[0]); 144058314Sache cbc->log_drive = CISS_LUN_TO_TARGET(ld->cl_address.logical.lun); 144158314Sache 144258314Sache /* 144375409Sache * Submit the request and wait for it to complete. 144458314Sache */ 144521308Sache if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) { 1446119614Sache ciss_printf(sc, "error sending BMIC LDRIVE command (%d)\n", error); 1447157188Sache goto out; 1448157188Sache } 1449157188Sache 1450157188Sache /* 1451157188Sache * Check response. 1452157188Sache */ 1453119614Sache ciss_report_request(cr, &command_status, NULL); 1454119614Sache switch(command_status) { 145521308Sache case CISS_CMD_STATUS_SUCCESS: /* buffer right size */ 145621308Sache break; 1457165675Sache case CISS_CMD_STATUS_DATA_UNDERRUN: 1458165675Sache case CISS_CMD_STATUS_DATA_OVERRUN: 1459165675Sache ciss_printf(sc, "data over/underrun reading logical drive ID\n"); 146021308Sache default: 1461165675Sache ciss_printf(sc, "error reading logical drive ID (%s)\n", 1462165675Sache ciss_name_command_status(command_status)); 1463165675Sache error = EIO; 1464165675Sache goto out; 1465165675Sache } 1466165675Sache ciss_release_request(cr); 1467165675Sache cr = NULL; 1468165675Sache 1469165675Sache /* 147021308Sache * Build a CISS BMIC command to get the logical drive status. 1471119614Sache */ 1472119614Sache if ((error = ciss_get_ldrive_status(sc, ld)) != 0) 1473119614Sache goto out; 1474119614Sache 147521308Sache /* 1476119614Sache * Get the logical drive geometry. 1477119614Sache */ 1478119614Sache if ((error = ciss_inquiry_logical(sc, ld)) != 0) 1479119614Sache goto out; 148021308Sache 148121308Sache /* 148221308Sache * Print the drive's basic characteristics. 148321308Sache */ 148421308Sache if (bootverbose) { 148521308Sache ciss_printf(sc, "logical drive (b%dt%d): %s, %dMB ", 1486119614Sache CISS_LUN_TO_BUS(ld->cl_address.logical.lun), 1487119614Sache CISS_LUN_TO_TARGET(ld->cl_address.logical.lun), 1488119614Sache ciss_name_ldrive_org(ld->cl_ldrive->fault_tolerance), 1489119614Sache ((ld->cl_ldrive->blocks_available / (1024 * 1024)) * 1490119614Sache ld->cl_ldrive->block_size)); 1491119614Sache 1492119614Sache ciss_print_ldrive(sc, ld); 1493119614Sache } 1494119614Sacheout: 1495119614Sache if (error != 0) { 1496119614Sache /* make the drive not-exist */ 1497119614Sache ld->cl_status = CISS_LD_NONEXISTENT; 149821308Sache if (ld->cl_ldrive != NULL) { 149921308Sache free(ld->cl_ldrive, CISS_MALLOC_CLASS); 150021308Sache ld->cl_ldrive = NULL; 1501119614Sache } 1502119614Sache if (ld->cl_lstatus != NULL) { 1503119614Sache free(ld->cl_lstatus, CISS_MALLOC_CLASS); 1504119614Sache ld->cl_lstatus = NULL; 1505119614Sache } 1506119614Sache } 150721308Sache if (cr != NULL) 150821308Sache ciss_release_request(cr); 150921308Sache 151021308Sache return(error); 151121308Sache} 151221308Sache 151321308Sache/************************************************************************ 1514119614Sache * Get status for a logical drive. 151521308Sache * 151675409Sache * XXX should we also do this in response to Test Unit Ready? 151721308Sache */ 151875409Sachestatic int 151921308Sacheciss_get_ldrive_status(struct ciss_softc *sc, struct ciss_ldrive *ld) 152021308Sache{ 152175409Sache struct ciss_request *cr; 152221308Sache struct ciss_command *cc; 1523119614Sache struct ciss_bmic_cdb *cbc; 1524119614Sache int error, command_status; 152521308Sache 1526157188Sache /* 152721308Sache * Build a CISS BMIC command to get the logical drive status. 152821308Sache */ 152921308Sache if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_ID_LSTATUS, 153021308Sache (void **)&ld->cl_lstatus, 153147563Sache sizeof(*ld->cl_lstatus))) != 0) 153221308Sache goto out; 1533119614Sache cc = CISS_FIND_COMMAND(cr); 153421308Sache cc->header.address = *ld->cl_controller; /* target controller */ 153521308Sache cbc = (struct ciss_bmic_cdb *)&(cc->cdb.cdb[0]); 153621308Sache cbc->log_drive = CISS_LUN_TO_TARGET(ld->cl_address.logical.lun); 153721308Sache 153821308Sache /* 153921308Sache * Submit the request and wait for it to complete. 154021308Sache */ 1541119614Sache if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) { 154221308Sache ciss_printf(sc, "error sending BMIC LSTATUS command (%d)\n", error); 154321308Sache goto out; 154421308Sache } 154521308Sache 154621308Sache /* 154721308Sache * Check response. 154821308Sache */ 1549136759Speter ciss_report_request(cr, &command_status, NULL); 1550136759Speter switch(command_status) { 1551136759Speter case CISS_CMD_STATUS_SUCCESS: /* buffer right size */ 1552136759Speter break; 1553136759Speter case CISS_CMD_STATUS_DATA_UNDERRUN: 1554136759Speter case CISS_CMD_STATUS_DATA_OVERRUN: 1555119614Sache ciss_printf(sc, "data over/underrun reading logical drive status\n"); 1556136759Speter default: 1557119614Sache ciss_printf(sc, "error reading logical drive status (%s)\n", 155821308Sache ciss_name_command_status(command_status)); 155921308Sache error = EIO; 156021308Sache goto out; 156121308Sache } 156221308Sache 156321308Sache /* 1564119614Sache * Set the drive's summary status based on the returned status. 1565157188Sache * 1566157188Sache * XXX testing shows that a failed JBOD drive comes back at next 1567157188Sache * boot in "queued for expansion" mode. WTF? 1568157188Sache */ 156921308Sache ld->cl_status = ciss_decode_ldrive_status(ld->cl_lstatus->status); 157021308Sache 157121308Sacheout: 157221308Sache if (cr != NULL) 157321308Sache ciss_release_request(cr); 1574119614Sache return(error); 157521308Sache} 157621308Sache 157721308Sache/************************************************************************ 157821308Sache * Notify the adapter of a config update. 157921308Sache */ 158021308Sachestatic int 1581119614Sacheciss_update_config(struct ciss_softc *sc) 158221308Sache{ 1583119614Sache int i; 1584119614Sache 158521308Sache debug_called(1); 158621308Sache 158721308Sache CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IDBR, CISS_TL_SIMPLE_IDBR_CFG_TABLE); 158821308Sache for (i = 0; i < 1000; i++) { 158921308Sache if (!(CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_IDBR) & 159021308Sache CISS_TL_SIMPLE_IDBR_CFG_TABLE)) { 1591119614Sache return(0); 159221308Sache } 159321308Sache DELAY(1000); 159421308Sache } 159521308Sache return(1); 159621308Sache} 159721308Sache 159821308Sache/************************************************************************ 159921308Sache * Accept new media into a logical drive. 1600157188Sache * 160121308Sache * XXX The drive has previously been offline; it would be good if we 160221308Sache * could make sure it's not open right now. 1603119614Sache */ 1604119614Sachestatic int 1605119614Sacheciss_accept_media(struct ciss_softc *sc, struct ciss_ldrive *ld) 1606119614Sache{ 1607119614Sache struct ciss_request *cr; 1608119614Sache struct ciss_command *cc; 160947563Sache struct ciss_bmic_cdb *cbc; 161047563Sache int command_status; 1611119614Sache int error = 0, ldrive; 161247563Sache 1613119614Sache ldrive = CISS_LUN_TO_TARGET(ld->cl_address.logical.lun); 161447563Sache 161521308Sache debug(0, "bringing logical drive %d back online"); 161621308Sache 161721308Sache /* 161821308Sache * Build a CISS BMIC command to bring the drive back online. 161921308Sache */ 162021308Sache if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_ACCEPT_MEDIA, 162121308Sache NULL, 0)) != 0) 162221308Sache goto out; 162321308Sache cc = CISS_FIND_COMMAND(cr); 162421308Sache cc->header.address = *ld->cl_controller; /* target controller */ 162521308Sache cbc = (struct ciss_bmic_cdb *)&(cc->cdb.cdb[0]); 162621308Sache cbc->log_drive = ldrive; 162721308Sache 162821308Sache /* 162921308Sache * Submit the request and wait for it to complete. 163021308Sache */ 163121308Sache if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) { 163221308Sache ciss_printf(sc, "error sending BMIC ACCEPT MEDIA command (%d)\n", error); 163321308Sache goto out; 163458314Sache } 163558314Sache 1636136759Speter /* 1637136759Speter * Check response. 163858314Sache */ 163958314Sache ciss_report_request(cr, &command_status, NULL); 164058314Sache switch(command_status) { 164158314Sache case CISS_CMD_STATUS_SUCCESS: /* all OK */ 1642136759Speter /* we should get a logical drive status changed event here */ 164358314Sache break; 164458314Sache default: 164558314Sache ciss_printf(cr->cr_sc, "error accepting media into failed logical drive (%s)\n", 164658314Sache ciss_name_command_status(command_status)); 164758314Sache break; 164858314Sache } 164958314Sache 165058314Sacheout: 1651136759Speter if (cr != NULL) 1652136759Speter ciss_release_request(cr); 1653136759Speter return(error); 165458314Sache} 165558314Sache 165658314Sache/************************************************************************ 165758314Sache * Release adapter resources. 165858314Sache */ 165958314Sachestatic void 166058314Sacheciss_free(struct ciss_softc *sc) 1661119614Sache{ 1662157188Sache struct ciss_request *cr; 1663119614Sache int i, j; 1664119614Sache 166558314Sache debug_called(1); 166658314Sache 166758314Sache /* we're going away */ 166858314Sache sc->ciss_flags |= CISS_FLAG_ABORTING; 166975409Sache 167058314Sache /* terminate the periodic heartbeat routine */ 167158314Sache callout_stop(&sc->ciss_periodic); 167258314Sache 167358314Sache /* cancel the Event Notify chain */ 167458314Sache ciss_notify_abort(sc); 167558314Sache 167658314Sache ciss_kill_notify_thread(sc); 167758314Sache 167858314Sache /* disconnect from CAM */ 167958314Sache if (sc->ciss_cam_sim) { 168058314Sache for (i = 0; i < sc->ciss_max_logical_bus; i++) { 168158314Sache if (sc->ciss_cam_sim[i]) { 168258314Sache xpt_bus_deregister(cam_sim_path(sc->ciss_cam_sim[i])); 168358314Sache cam_sim_free(sc->ciss_cam_sim[i], 0); 168458314Sache } 168558314Sache } 168658314Sache for (i = CISS_PHYSICAL_BASE; i < sc->ciss_max_physical_bus + 168758314Sache CISS_PHYSICAL_BASE; i++) { 1688136759Speter if (sc->ciss_cam_sim[i]) { 1689136759Speter xpt_bus_deregister(cam_sim_path(sc->ciss_cam_sim[i])); 169058314Sache cam_sim_free(sc->ciss_cam_sim[i], 0); 169158314Sache } 169258314Sache } 169321308Sache free(sc->ciss_cam_sim, CISS_MALLOC_CLASS); 169421308Sache } 169521308Sache if (sc->ciss_cam_devq) 169621308Sache cam_simq_free(sc->ciss_cam_devq); 1697165675Sache 1698165675Sache /* remove the control device */ 169921308Sache mtx_unlock(&sc->ciss_mtx); 170021308Sache if (sc->ciss_dev_t != NULL) 1701165675Sache destroy_dev(sc->ciss_dev_t); 170221308Sache 170347563Sache /* Final cleanup of the callout. */ 170421308Sache callout_drain(&sc->ciss_periodic); 170521308Sache mtx_destroy(&sc->ciss_mtx); 170621308Sache 170721308Sache /* free the controller data */ 170821308Sache if (sc->ciss_id != NULL) 170921308Sache free(sc->ciss_id, CISS_MALLOC_CLASS); 171021308Sache 171121308Sache /* release I/O resources */ 1712157188Sache if (sc->ciss_regs_resource != NULL) 1713157188Sache bus_release_resource(sc->ciss_dev, SYS_RES_MEMORY, 171421308Sache sc->ciss_regs_rid, sc->ciss_regs_resource); 171521308Sache if (sc->ciss_cfg_resource != NULL) 171621308Sache bus_release_resource(sc->ciss_dev, SYS_RES_MEMORY, 171721308Sache sc->ciss_cfg_rid, sc->ciss_cfg_resource); 171821308Sache if (sc->ciss_intr != NULL) 171975409Sache bus_teardown_intr(sc->ciss_dev, sc->ciss_irq_resource, sc->ciss_intr); 172021308Sache if (sc->ciss_irq_resource != NULL) 172121308Sache bus_release_resource(sc->ciss_dev, SYS_RES_IRQ, 1722157188Sache sc->ciss_irq_rid, sc->ciss_irq_resource); 1723157188Sache 172421308Sache /* destroy DMA tags */ 1725157188Sache if (sc->ciss_parent_dmat) 1726157188Sache bus_dma_tag_destroy(sc->ciss_parent_dmat); 1727119614Sache 1728119614Sache while ((cr = ciss_dequeue_free(sc)) != NULL) 1729119614Sache bus_dmamap_destroy(sc->ciss_buffer_dmat, cr->cr_datamap); 1730136759Speter if (sc->ciss_buffer_dmat) 1731157188Sache bus_dma_tag_destroy(sc->ciss_buffer_dmat); 1732157188Sache 1733157188Sache /* destroy command memory and DMA tag */ 1734136759Speter if (sc->ciss_command != NULL) { 1735157188Sache bus_dmamap_unload(sc->ciss_command_dmat, sc->ciss_command_map); 1736165675Sache bus_dmamem_free(sc->ciss_command_dmat, sc->ciss_command, sc->ciss_command_map); 1737165675Sache } 1738165675Sache if (sc->ciss_command_dmat) 1739165675Sache bus_dma_tag_destroy(sc->ciss_command_dmat); 1740165675Sache 1741165675Sache if (sc->ciss_logical) { 1742165675Sache for (i = 0; i <= sc->ciss_max_logical_bus; i++) { 1743165675Sache for (j = 0; j < CISS_MAX_LOGICAL; j++) { 1744136759Speter if (sc->ciss_logical[i][j].cl_ldrive) 1745157188Sache free(sc->ciss_logical[i][j].cl_ldrive, CISS_MALLOC_CLASS); 1746119614Sache if (sc->ciss_logical[i][j].cl_lstatus) 1747157188Sache free(sc->ciss_logical[i][j].cl_lstatus, CISS_MALLOC_CLASS); 174821308Sache } 1749157188Sache free(sc->ciss_logical[i], CISS_MALLOC_CLASS); 1750157188Sache } 1751157188Sache free(sc->ciss_logical, CISS_MALLOC_CLASS); 1752157188Sache } 175321308Sache 175421308Sache if (sc->ciss_physical) { 175521308Sache for (i = 0; i < sc->ciss_max_physical_bus; i++) 1756157188Sache free(sc->ciss_physical[i], CISS_MALLOC_CLASS); 1757157188Sache free(sc->ciss_physical, CISS_MALLOC_CLASS); 1758157188Sache } 1759157188Sache 1760157188Sache if (sc->ciss_controllers) 1761157188Sache free(sc->ciss_controllers, CISS_MALLOC_CLASS); 1762165675Sache 176375409Sache} 176421308Sache 176521308Sache/************************************************************************ 176621308Sache * Give a command to the adapter. 176721308Sache * 176875409Sache * Note that this uses the simple transport layer directly. If we 176921308Sache * want to add support for other layers, we'll need a switch of some 1770157188Sache * sort. 177121308Sache * 177221308Sache * Note that the simple transport layer has no way of refusing a 1773157188Sache * command; we only have as many request structures as the adapter 177421308Sache * supports commands, so we don't have to check (this presumes that 177521308Sache * the adapter can handle commands as fast as we throw them at it). 177621308Sache */ 177721308Sachestatic int 177821308Sacheciss_start(struct ciss_request *cr) 177921308Sache{ 178021308Sache struct ciss_command *cc; /* XXX debugging only */ 178121308Sache int error; 178221308Sache 178321308Sache cc = CISS_FIND_COMMAND(cr); 1784165675Sache debug(2, "post command %d tag %d ", cr->cr_tag, cc->header.host_tag); 1785165675Sache 1786165675Sache /* 1787165675Sache * Map the request's data. 1788165675Sache */ 1789165675Sache if ((error = ciss_map_request(cr))) 1790165675Sache return(error); 1791165675Sache 1792119614Sache#if 0 1793119614Sache ciss_print_request(cr); 1794165675Sache#endif 1795165675Sache 1796165675Sache return(0); 1797165675Sache} 1798165675Sache 1799165675Sache/************************************************************************ 1800165675Sache * Fetch completed request(s) from the adapter, queue them for 1801165675Sache * completion handling. 1802165675Sache * 1803165675Sache * Note that this uses the simple transport layer directly. If we 1804165675Sache * want to add support for other layers, we'll need a switch of some 1805119614Sache * sort. 180621308Sache * 1807157188Sache * Note that the simple transport mechanism does not require any 180821308Sache * reentrancy protection; the OPQ read is atomic. If there is a 1809157188Sache * chance of a race with something else that might move the request 1810119614Sache * off the busy list, then we will have to lock against that 1811119614Sache * (eg. timeouts, etc.) 1812119614Sache */ 1813119614Sachestatic void 1814119614Sacheciss_done(struct ciss_softc *sc) 1815119614Sache{ 1816119614Sache struct ciss_request *cr; 1817157188Sache struct ciss_command *cc; 1818157188Sache u_int32_t tag, index; 1819119614Sache int complete; 1820157188Sache 182121308Sache debug_called(3); 182221308Sache 182321308Sache /* 182421308Sache * Loop quickly taking requests from the adapter and moving them 182521308Sache * from the busy queue to the completed queue. 182621308Sache */ 182721308Sache complete = 0; 182821308Sache for (;;) { 182921308Sache 183075409Sache /* see if the OPQ contains anything */ 183121308Sache if (!CISS_TL_SIMPLE_OPQ_INTERRUPT(sc)) 183221308Sache break; 183321308Sache 183421308Sache tag = CISS_TL_SIMPLE_FETCH_CMD(sc); 183521308Sache if (tag == CISS_TL_SIMPLE_OPQ_EMPTY) 183621308Sache break; 183758314Sache index = tag >> 2; 183858314Sache debug(2, "completed command %d%s", index, 183958314Sache (tag & CISS_HDR_HOST_TAG_ERROR) ? " with error" : ""); 184075409Sache if (index >= sc->ciss_max_requests) { 184158314Sache ciss_printf(sc, "completed invalid request %d (0x%x)\n", index, tag); 184221308Sache continue; 184321308Sache } 184421308Sache cr = &(sc->ciss_request[index]); 184521308Sache cc = CISS_FIND_COMMAND(cr); 184675409Sache cc->header.host_tag = tag; /* not updated by adapter */ 184721308Sache if (ciss_remove_busy(cr)) { 184875409Sache /* assume this is garbage out of the adapter */ 184921308Sache ciss_printf(sc, "completed nonbusy request %d\n", index); 185058314Sache } else { 185121308Sache ciss_enqueue_complete(cr); 185221308Sache } 185321308Sache complete = 1; 185421308Sache } 185521308Sache 185621308Sache /* 185721308Sache * Invoke completion processing. If we can defer this out of 185821308Sache * interrupt context, that'd be good. 185921308Sache */ 186021308Sache if (complete) 186121308Sache ciss_complete(sc); 186221308Sache} 186321308Sache 186421308Sache/************************************************************************ 186521308Sache * Take an interrupt from the adapter. 186621308Sache */ 186721308Sachestatic void 186821308Sacheciss_intr(void *arg) 186921308Sache{ 187021308Sache struct ciss_softc *sc = (struct ciss_softc *)arg; 187121308Sache 187221308Sache /* 187321308Sache * The only interrupt we recognise indicates that there are 187421308Sache * entries in the outbound post queue. 187521308Sache */ 187621308Sache mtx_lock(&sc->ciss_mtx); 187721308Sache ciss_done(sc); 187821308Sache mtx_unlock(&sc->ciss_mtx); 187921308Sache} 188021308Sache 188121308Sache/************************************************************************ 188221308Sache * Process completed requests. 188321308Sache * 188421308Sache * Requests can be completed in three fashions: 188521308Sache * 188621308Sache * - by invoking a callback function (cr_complete is non-null) 188721308Sache * - by waking up a sleeper (cr_flags has CISS_REQ_SLEEP set) 188821308Sache * - by clearing the CISS_REQ_POLL flag in interrupt/timeout context 188921308Sache */ 189021308Sachestatic void 189121308Sacheciss_complete(struct ciss_softc *sc) 189221308Sache{ 189321308Sache struct ciss_request *cr; 189421308Sache 189521308Sache debug_called(2); 189621308Sache 189721308Sache /* 189821308Sache * Loop taking requests off the completed queue and performing 189921308Sache * completion processing on them. 190021308Sache */ 190121308Sache for (;;) { 190221308Sache if ((cr = ciss_dequeue_complete(sc)) == NULL) 190321308Sache break; 190421308Sache ciss_unmap_request(cr); 190521308Sache 190621308Sache /* 1907119614Sache * If the request has a callback, invoke it. 190821308Sache */ 190921308Sache if (cr->cr_complete != NULL) { 191021308Sache cr->cr_complete(cr); 1911157188Sache continue; 191221308Sache } 191321308Sache 191421308Sache /* 191521308Sache * If someone is sleeping on this request, wake them up. 191621308Sache */ 191721308Sache if (cr->cr_flags & CISS_REQ_SLEEP) { 191821308Sache cr->cr_flags &= ~CISS_REQ_SLEEP; 191921308Sache wakeup(cr); 192021308Sache continue; 192121308Sache } 192221308Sache 192321308Sache /* 192421308Sache * If someone is polling this request for completion, signal. 192521308Sache */ 192621308Sache if (cr->cr_flags & CISS_REQ_POLL) { 192721308Sache cr->cr_flags &= ~CISS_REQ_POLL; 192821308Sache continue; 192921308Sache } 193021308Sache 193121308Sache /* 193221308Sache * Give up and throw the request back on the free queue. This 193321308Sache * should never happen; resources will probably be lost. 1934119614Sache */ 1935119614Sache ciss_printf(sc, "WARNING: completed command with no submitter\n"); 1936119614Sache ciss_enqueue_free(cr); 193721308Sache } 1938119614Sache} 1939119614Sache 194021308Sache/************************************************************************ 194121308Sache * Report on the completion status of a request, and pass back SCSI 1942157188Sache * and command status values. 1943157188Sache */ 1944157188Sachestatic int 1945157188Sacheciss_report_request(struct ciss_request *cr, int *command_status, int *scsi_status) 1946157188Sache{ 194721308Sache struct ciss_command *cc; 1948157188Sache struct ciss_error_info *ce; 1949157188Sache 1950157188Sache debug_called(2); 1951157188Sache 1952157188Sache cc = CISS_FIND_COMMAND(cr); 1953165675Sache ce = (struct ciss_error_info *)&(cc->sg[0]); 195421308Sache 1955157188Sache /* 195621308Sache * We don't consider data under/overrun an error for the Report 195721308Sache * Logical/Physical LUNs commands. 195821308Sache */ 195921308Sache if ((cc->header.host_tag & CISS_HDR_HOST_TAG_ERROR) && 196021308Sache ((ce->command_status == CISS_CMD_STATUS_DATA_OVERRUN) || 196121308Sache (ce->command_status == CISS_CMD_STATUS_DATA_UNDERRUN)) && 196221308Sache ((cc->cdb.cdb[0] == CISS_OPCODE_REPORT_LOGICAL_LUNS) || 196321308Sache (cc->cdb.cdb[0] == CISS_OPCODE_REPORT_PHYSICAL_LUNS) || 1964119614Sache (cc->cdb.cdb[0] == INQUIRY))) { 1965157188Sache cc->header.host_tag &= ~CISS_HDR_HOST_TAG_ERROR; 196621308Sache debug(2, "ignoring irrelevant under/overrun error"); 1967157188Sache } 1968157188Sache 1969157188Sache /* 1970157188Sache * Check the command's error bit, if clear, there's no status and 1971157188Sache * everything is OK. 1972157188Sache */ 1973157188Sache if (!(cc->header.host_tag & CISS_HDR_HOST_TAG_ERROR)) { 1974157188Sache if (scsi_status != NULL) 1975157188Sache *scsi_status = SCSI_STATUS_OK; 1976157188Sache if (command_status != NULL) 1977165675Sache *command_status = CISS_CMD_STATUS_SUCCESS; 197821308Sache return(0); 1979157188Sache } else { 198021308Sache if (command_status != NULL) 198121308Sache *command_status = ce->command_status; 198221308Sache if (scsi_status != NULL) { 198321308Sache if (ce->command_status == CISS_CMD_STATUS_TARGET_STATUS) { 198421308Sache *scsi_status = ce->scsi_status; 198521308Sache } else { 198621308Sache *scsi_status = -1; 198721308Sache } 198821308Sache } 1989157188Sache if (bootverbose) 1990157188Sache ciss_printf(cr->cr_sc, "command status 0x%x (%s) scsi status 0x%x\n", 1991157188Sache ce->command_status, ciss_name_command_status(ce->command_status), 1992157188Sache ce->scsi_status); 1993157188Sache if (ce->command_status == CISS_CMD_STATUS_INVALID_COMMAND) { 199421308Sache ciss_printf(cr->cr_sc, "invalid command, offense size %d at %d, value 0x%x\n", 199521308Sache ce->additional_error_info.invalid_command.offense_size, 199621308Sache ce->additional_error_info.invalid_command.offense_offset, 199721308Sache ce->additional_error_info.invalid_command.offense_value); 199821308Sache } 199921308Sache } 200021308Sache#if 0 200121308Sache ciss_print_request(cr); 200221308Sache#endif 200321308Sache return(1); 200421308Sache} 200521308Sache 200621308Sache/************************************************************************ 200721308Sache * Issue a request and don't return until it's completed. 200821308Sache * 200947563Sache * Depending on adapter status, we may poll or sleep waiting for 201021308Sache * completion. 201121308Sache */ 201221308Sachestatic int 2013157188Sacheciss_synch_request(struct ciss_request *cr, int timeout) 2014165675Sache{ 201575409Sache if (cr->cr_sc->ciss_flags & CISS_FLAG_RUNNING) { 201675409Sache return(ciss_wait_request(cr, timeout)); 2017136759Speter } else { 2018136759Speter return(ciss_poll_request(cr, timeout)); 201921308Sache } 202021308Sache} 2021165675Sache 2022157188Sache/************************************************************************ 2023136759Speter * Issue a request and poll for completion. 202421308Sache * 202521308Sache * Timeout in milliseconds. 202621308Sache */ 202747563Sachestatic int 202821308Sacheciss_poll_request(struct ciss_request *cr, int timeout) 202975409Sache{ 203075409Sache int error; 203121308Sache 203221308Sache debug_called(2); 203321308Sache 2034165675Sache cr->cr_flags |= CISS_REQ_POLL; 2035157188Sache if ((error = ciss_start(cr)) != 0) 203675409Sache return(error); 203775409Sache 2038136759Speter do { 2039136759Speter ciss_done(cr->cr_sc); 2040157188Sache if (!(cr->cr_flags & CISS_REQ_POLL)) 2041157188Sache return(0); 2042157188Sache DELAY(1000); 2043165675Sache } while (timeout-- >= 0); 2044157188Sache return(EWOULDBLOCK); 2045157188Sache} 204621308Sache 204721308Sache/************************************************************************ 204821308Sache * Issue a request and sleep waiting for completion. 204921308Sache * 205021308Sache * Timeout in milliseconds. Note that a spurious wakeup will reset 205121308Sache * the timeout. 205221308Sache */ 2053157195Sachestatic int 205421308Sacheciss_wait_request(struct ciss_request *cr, int timeout) 205547563Sache{ 205621308Sache int s, error; 2057157195Sache 2058157195Sache debug_called(2); 2059157195Sache 2060157195Sache cr->cr_flags |= CISS_REQ_SLEEP; 2061157195Sache if ((error = ciss_start(cr)) != 0) 206221308Sache return(error); 206321308Sache 2064119614Sache s = splcam(); 206521308Sache while ((cr->cr_flags & CISS_REQ_SLEEP) && (error != EWOULDBLOCK)) { 206647563Sache error = msleep(cr, &cr->cr_sc->ciss_mtx, PRIBIO, "cissREQ", (timeout * hz) / 1000); 206721308Sache } 206821308Sache splx(s); 206921308Sache return(error); 207021308Sache} 207121308Sache 2072157195Sache#if 0 2073157195Sache/************************************************************************ 2074119614Sache * Abort a request. Note that a potential exists here to race the 207521308Sache * request being completed; the caller must deal with this. 2076157195Sache */ 207721308Sachestatic int 207821308Sacheciss_abort_request(struct ciss_request *ar) 2079157195Sache{ 2080136759Speter struct ciss_request *cr; 2081157195Sache struct ciss_command *cc; 2082157188Sache struct ciss_message_cdb *cmc; 208321308Sache int error; 208421308Sache 208521308Sache debug_called(1); 208621308Sache 208721308Sache /* get a request */ 208821308Sache if ((error = ciss_get_request(ar->cr_sc, &cr)) != 0) 208921308Sache return(error); 209021308Sache 209121308Sache /* build the abort command */ 209221308Sache cc = CISS_FIND_COMMAND(cr); 209321308Sache cc->header.address.mode.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL; /* addressing? */ 209421308Sache cc->header.address.physical.target = 0; 209521308Sache cc->header.address.physical.bus = 0; 209621308Sache cc->cdb.cdb_length = sizeof(*cmc); 209721308Sache cc->cdb.type = CISS_CDB_TYPE_MESSAGE; 209821308Sache cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE; 209921308Sache cc->cdb.direction = CISS_CDB_DIRECTION_NONE; 210021308Sache cc->cdb.timeout = 30; 210121308Sache 210221308Sache cmc = (struct ciss_message_cdb *)&(cc->cdb.cdb[0]); 210321308Sache cmc->opcode = CISS_OPCODE_MESSAGE_ABORT; 210426497Sache cmc->type = CISS_MESSAGE_ABORT_TASK; 210526497Sache cmc->abort_tag = ar->cr_tag; /* endianness?? */ 210621308Sache 210721308Sache /* 210875409Sache * Send the request and wait for a response. If we believe we 210975409Sache * aborted the request OK, clear the flag that indicates it's 211026497Sache * running. 211121308Sache */ 211221308Sache error = ciss_synch_request(cr, 35 * 1000); 211321308Sache if (!error) 211421308Sache error = ciss_report_request(cr, NULL, NULL); 211521308Sache ciss_release_request(cr); 211621308Sache 211721308Sache return(error); 211821308Sache} 211921308Sache#endif 212021308Sache 212121308Sache 212221308Sache/************************************************************************ 212321308Sache * Fetch and initialise a request 212421308Sache */ 212521308Sachestatic int 212621308Sacheciss_get_request(struct ciss_softc *sc, struct ciss_request **crp) 212721308Sache{ 212826497Sache struct ciss_request *cr; 212926497Sache 213026497Sache debug_called(2); 213175409Sache 213275409Sache /* 213326497Sache * Get a request and clean it up. 213475409Sache */ 213526497Sache if ((cr = ciss_dequeue_free(sc)) == NULL) 213626497Sache return(ENOMEM); 2137119614Sache 213821308Sache cr->cr_data = NULL; 2139119614Sache cr->cr_flags = 0; 214021308Sache cr->cr_complete = NULL; 2141119614Sache cr->cr_private = NULL; 214221308Sache 2143157188Sache ciss_preen_command(cr); 2144157188Sache *crp = cr; 2145157188Sache return(0); 2146119614Sache} 2147119614Sache 2148119614Sachestatic void 2149119614Sacheciss_preen_command(struct ciss_request *cr) 2150119614Sache{ 215121308Sache struct ciss_command *cc; 215275409Sache u_int32_t cmdphys; 215321308Sache 215421308Sache /* 2155119614Sache * Clean up the command structure. 2156119614Sache * 215721308Sache * Note that we set up the error_info structure here, since the 215821308Sache * length can be overwritten by any command. 215921308Sache */ 216021308Sache cc = CISS_FIND_COMMAND(cr); 216121308Sache cc->header.sg_in_list = 0; /* kinda inefficient this way */ 216221308Sache cc->header.sg_total = 0; 216321308Sache cc->header.host_tag = cr->cr_tag << 2; 216421308Sache cc->header.host_tag_zeroes = 0; 216575409Sache cmdphys = CISS_FIND_COMMANDPHYS(cr); 216675409Sache cc->error_info.error_info_address = cmdphys + sizeof(struct ciss_command); 216721308Sache cc->error_info.error_info_length = CISS_COMMAND_ALLOC_SIZE - sizeof(struct ciss_command); 216821308Sache} 216921308Sache 217075409Sache/************************************************************************ 217121308Sache * Release a request to the free list. 2172119614Sache */ 217375409Sachestatic void 217421308Sacheciss_release_request(struct ciss_request *cr) 217521308Sache{ 217621308Sache struct ciss_softc *sc; 217721308Sache 217821308Sache debug_called(2); 217921308Sache 218021308Sache sc = cr->cr_sc; 218175409Sache 218275409Sache /* release the request to the free queue */ 218321308Sache ciss_requeue_free(cr); 2184157188Sache} 218521308Sache 218621308Sache/************************************************************************ 218721308Sache * Allocate a request that will be used to send a BMIC command. Do some 218821308Sache * of the common setup here to avoid duplicating it everywhere else. 218921308Sache */ 219021308Sachestatic int 219121308Sacheciss_get_bmic_request(struct ciss_softc *sc, struct ciss_request **crp, 219275409Sache int opcode, void **bufp, size_t bufsize) 219321308Sache{ 219421308Sache struct ciss_request *cr; 2195157188Sache struct ciss_command *cc; 219675409Sache struct ciss_bmic_cdb *cbc; 219721308Sache void *buf; 219821308Sache int error; 219975409Sache int dataout; 220021308Sache 220121308Sache debug_called(2); 220221308Sache 220321308Sache cr = NULL; 220475409Sache buf = NULL; 220521308Sache 220675409Sache /* 220721308Sache * Get a request. 2208157188Sache */ 220921308Sache if ((error = ciss_get_request(sc, &cr)) != 0) 221021308Sache goto out; 221121308Sache 221221308Sache /* 221321308Sache * Allocate data storage if requested, determine the data direction. 221421308Sache */ 221521308Sache dataout = 0; 221621308Sache if ((bufsize > 0) && (bufp != NULL)) { 221721308Sache if (*bufp == NULL) { 221821308Sache if ((buf = malloc(bufsize, CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO)) == NULL) { 221921308Sache error = ENOMEM; 222026497Sache goto out; 222121308Sache } 222221308Sache } else { 222321308Sache buf = *bufp; 222421308Sache dataout = 1; /* we are given a buffer, so we are writing */ 222521308Sache } 222621308Sache } 222775409Sache 222821308Sache /* 222921308Sache * Build a CISS BMIC command to get the logical drive ID. 2230119614Sache */ 223158314Sache cr->cr_data = buf; 2232165675Sache cr->cr_length = bufsize; 2233165675Sache if (!dataout) 223426497Sache cr->cr_flags = CISS_REQ_DATAIN; 223575409Sache 223621308Sache cc = CISS_FIND_COMMAND(cr); 223721308Sache cc->header.address.physical.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL; 223875409Sache cc->header.address.physical.bus = 0; 223921308Sache cc->header.address.physical.target = 0; 224021308Sache cc->cdb.cdb_length = sizeof(*cbc); 224121308Sache cc->cdb.type = CISS_CDB_TYPE_COMMAND; 224221308Sache cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE; 224321308Sache cc->cdb.direction = dataout ? CISS_CDB_DIRECTION_WRITE : CISS_CDB_DIRECTION_READ; 224421308Sache cc->cdb.timeout = 0; 224521308Sache 224621308Sache cbc = (struct ciss_bmic_cdb *)&(cc->cdb.cdb[0]); 224775409Sache bzero(cbc, sizeof(*cbc)); 224821308Sache cbc->opcode = dataout ? CISS_ARRAY_CONTROLLER_WRITE : CISS_ARRAY_CONTROLLER_READ; 224958314Sache cbc->bmic_opcode = opcode; 225058314Sache cbc->size = htons((u_int16_t)bufsize); 225158314Sache 225275409Sacheout: 225358314Sache if (error) { 225421308Sache if (cr != NULL) 225521308Sache ciss_release_request(cr); 225621308Sache } else { 225721308Sache *crp = cr; 225858314Sache if ((bufp != NULL) && (*bufp == NULL) && (buf != NULL)) 225958314Sache *bufp = buf; 226058314Sache } 226158314Sache return(error); 226258314Sache} 226358314Sache 226458314Sache/************************************************************************ 2265157188Sache * Handle a command passed in from userspace. 226658314Sache */ 226758314Sachestatic int 2268157188Sacheciss_user_command(struct ciss_softc *sc, IOCTL_Command_struct *ioc) 226958314Sache{ 227058314Sache struct ciss_request *cr; 227175409Sache struct ciss_command *cc; 227275409Sache struct ciss_error_info *ce; 2273136759Speter int error = 0; 2274136759Speter 227558314Sache debug_called(1); 2276165675Sache 2277157188Sache cr = NULL; 227858314Sache 227958314Sache /* 228058314Sache * Get a request. 2281157188Sache */ 228258314Sache while (ciss_get_request(sc, &cr) != 0) 228358314Sache msleep(sc, &sc->ciss_mtx, PPAUSE, "cissREQ", hz); 228421308Sache cc = CISS_FIND_COMMAND(cr); 228521308Sache 228621308Sache /* 228721308Sache * Allocate an in-kernel databuffer if required, copy in user data. 228858314Sache */ 228921308Sache cr->cr_length = ioc->buf_size; 229021308Sache if (ioc->buf_size > 0) { 229121308Sache if ((cr->cr_data = malloc(ioc->buf_size, CISS_MALLOC_CLASS, M_NOWAIT)) == NULL) { 229275409Sache error = ENOMEM; 229321308Sache goto out; 229458314Sache } 229558314Sache if ((error = copyin(ioc->buf, cr->cr_data, ioc->buf_size))) { 229658314Sache debug(0, "copyin: bad data buffer %p/%d", ioc->buf, ioc->buf_size); 229775409Sache goto out; 229858314Sache } 229921308Sache } 230058314Sache 230175409Sache /* 230258314Sache * Build the request based on the user command. 230358314Sache */ 230475409Sache bcopy(&ioc->LUN_info, &cc->header.address, sizeof(cc->header.address)); 230575409Sache bcopy(&ioc->Request, &cc->cdb, sizeof(cc->cdb)); 230621308Sache 230721308Sache /* XXX anything else to populate here? */ 230875409Sache 230975409Sache /* 231021308Sache * Run the command. 231158314Sache */ 231221308Sache if ((error = ciss_synch_request(cr, 60 * 1000))) { 231321308Sache debug(0, "request failed - %d", error); 231421308Sache goto out; 231521308Sache } 231675409Sache 231721308Sache /* 231821308Sache * Check to see if the command succeeded. 231921308Sache */ 232021308Sache ce = (struct ciss_error_info *)&(cc->sg[0]); 232158314Sache if ((cc->header.host_tag & CISS_HDR_HOST_TAG_ERROR) == 0) 232221308Sache bzero(ce, sizeof(*ce)); 232321308Sache 232421308Sache /* 232521308Sache * Copy the results back to the user. 232621308Sache */ 232721308Sache bcopy(ce, &ioc->error_info, sizeof(*ce)); 232821308Sache if ((ioc->buf_size > 0) && 232921308Sache (error = copyout(cr->cr_data, ioc->buf, ioc->buf_size))) { 233021308Sache debug(0, "copyout: bad data buffer %p/%d", ioc->buf, ioc->buf_size); 233121308Sache goto out; 233221308Sache } 233321308Sache 233447563Sache /* done OK */ 233521308Sache error = 0; 233621308Sache 233747563Sacheout: 233847563Sache if ((cr != NULL) && (cr->cr_data != NULL)) 233947563Sache free(cr->cr_data, CISS_MALLOC_CLASS); 234047563Sache if (cr != NULL) 234147563Sache ciss_release_request(cr); 234247563Sache return(error); 234347563Sache} 234447563Sache 234547563Sache/************************************************************************ 234658314Sache * Map a request into bus-visible space, initialise the scatter/gather 234758314Sache * list. 234858314Sache */ 234958314Sachestatic int 235058314Sacheciss_map_request(struct ciss_request *cr) 235158314Sache{ 235258314Sache struct ciss_softc *sc; 235358314Sache int error = 0; 235458314Sache 235558314Sache debug_called(2); 235658314Sache 235775409Sache sc = cr->cr_sc; 235858314Sache 235975409Sache /* check that mapping is necessary */ 236058314Sache if (cr->cr_flags & CISS_REQ_MAPPED) 236158314Sache return(0); 236275409Sache 236358314Sache cr->cr_flags |= CISS_REQ_MAPPED; 236458314Sache 236558314Sache bus_dmamap_sync(sc->ciss_command_dmat, sc->ciss_command_map, 236658314Sache BUS_DMASYNC_PREWRITE); 236758314Sache 2368119614Sache if (cr->cr_data != NULL) { 2369119614Sache error = bus_dmamap_load(sc->ciss_buffer_dmat, cr->cr_datamap, 2370119614Sache cr->cr_data, cr->cr_length, 2371119614Sache ciss_request_map_helper, cr, 0); 2372119614Sache if (error != 0) 2373119614Sache return (error); 2374119614Sache } else { 2375136759Speter /* 2376119614Sache * Post the command to the adapter. 2377119614Sache */ 2378119614Sache ciss_enqueue_busy(cr); 2379165675Sache CISS_TL_SIMPLE_POST_CMD(cr->cr_sc, CISS_FIND_COMMANDPHYS(cr)); 2380119614Sache } 2381119614Sache 2382119614Sache return(0); 2383119614Sache} 2384119614Sache 2385165675Sachestatic void 2386165675Sacheciss_request_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2387119614Sache{ 2388119614Sache struct ciss_command *cc; 2389119614Sache struct ciss_request *cr; 2390119614Sache struct ciss_softc *sc; 2391119614Sache int i; 2392119614Sache 2393136759Speter debug_called(2); 2394119614Sache 2395119614Sache cr = (struct ciss_request *)arg; 2396119614Sache sc = cr->cr_sc; 2397119614Sache cc = CISS_FIND_COMMAND(cr); 2398119614Sache 2399119614Sache for (i = 0; i < nseg; i++) { 2400119614Sache cc->sg[i].address = segs[i].ds_addr; 2401119614Sache cc->sg[i].length = segs[i].ds_len; 2402119614Sache cc->sg[i].extension = 0; 2403119614Sache } 2404119614Sache /* we leave the s/g table entirely within the command */ 2405136759Speter cc->header.sg_in_list = nseg; 2406136759Speter cc->header.sg_total = nseg; 2407119614Sache 2408119614Sache if (cr->cr_flags & CISS_REQ_DATAIN) 2409119614Sache bus_dmamap_sync(sc->ciss_buffer_dmat, cr->cr_datamap, BUS_DMASYNC_PREREAD); 2410119614Sache if (cr->cr_flags & CISS_REQ_DATAOUT) 2411119614Sache bus_dmamap_sync(sc->ciss_buffer_dmat, cr->cr_datamap, BUS_DMASYNC_PREWRITE); 2412119614Sache 2413119614Sache /* 2414119614Sache * Post the command to the adapter. 2415119614Sache */ 2416119614Sache ciss_enqueue_busy(cr); 2417119614Sache CISS_TL_SIMPLE_POST_CMD(cr->cr_sc, CISS_FIND_COMMANDPHYS(cr)); 2418119614Sache} 2419119614Sache 2420119614Sache/************************************************************************ 2421119614Sache * Unmap a request from bus-visible space. 2422136759Speter */ 2423119614Sachestatic void 2424119614Sacheciss_unmap_request(struct ciss_request *cr) 2425119614Sache{ 2426119614Sache struct ciss_softc *sc; 2427119614Sache 2428119614Sache debug_called(2); 2429119614Sache 2430119614Sache sc = cr->cr_sc; 2431119614Sache 2432119614Sache /* check that unmapping is necessary */ 2433119614Sache if ((cr->cr_flags & CISS_REQ_MAPPED) == 0) 2434119614Sache return; 2435119614Sache 2436119614Sache bus_dmamap_sync(sc->ciss_command_dmat, sc->ciss_command_map, 2437136759Speter BUS_DMASYNC_POSTWRITE); 2438136759Speter 2439119614Sache if (cr->cr_data == NULL) 2440119614Sache goto out; 2441119614Sache 2442119614Sache if (cr->cr_flags & CISS_REQ_DATAIN) 2443119614Sache bus_dmamap_sync(sc->ciss_buffer_dmat, cr->cr_datamap, BUS_DMASYNC_POSTREAD); 2444119614Sache if (cr->cr_flags & CISS_REQ_DATAOUT) 2445119614Sache bus_dmamap_sync(sc->ciss_buffer_dmat, cr->cr_datamap, BUS_DMASYNC_POSTWRITE); 2446119614Sache 2447119614Sache bus_dmamap_unload(sc->ciss_buffer_dmat, cr->cr_datamap); 2448119614Sacheout: 2449119614Sache cr->cr_flags &= ~CISS_REQ_MAPPED; 2450119614Sache} 2451119614Sache 2452119614Sache/************************************************************************ 2453 * Attach the driver to CAM. 2454 * 2455 * We put all the logical drives on a single SCSI bus. 2456 */ 2457static int 2458ciss_cam_init(struct ciss_softc *sc) 2459{ 2460 int i, maxbus; 2461 2462 debug_called(1); 2463 2464 /* 2465 * Allocate a devq. We can reuse this for the masked physical 2466 * devices if we decide to export these as well. 2467 */ 2468 if ((sc->ciss_cam_devq = cam_simq_alloc(sc->ciss_max_requests)) == NULL) { 2469 ciss_printf(sc, "can't allocate CAM SIM queue\n"); 2470 return(ENOMEM); 2471 } 2472 2473 /* 2474 * Create a SIM. 2475 * 2476 * This naturally wastes a bit of memory. The alternative is to allocate 2477 * and register each bus as it is found, and then track them on a linked 2478 * list. Unfortunately, the driver has a few places where it needs to 2479 * look up the SIM based solely on bus number, and it's unclear whether 2480 * a list traversal would work for these situations. 2481 */ 2482 maxbus = max(sc->ciss_max_logical_bus, sc->ciss_max_physical_bus + 2483 CISS_PHYSICAL_BASE); 2484 sc->ciss_cam_sim = malloc(maxbus * sizeof(struct cam_sim*), 2485 CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO); 2486 if (sc->ciss_cam_sim == NULL) { 2487 ciss_printf(sc, "can't allocate memory for controller SIM\n"); 2488 return(ENOMEM); 2489 } 2490 2491 for (i = 0; i < sc->ciss_max_logical_bus; i++) { 2492 if ((sc->ciss_cam_sim[i] = cam_sim_alloc(ciss_cam_action, ciss_cam_poll, 2493 "ciss", sc, 2494 device_get_unit(sc->ciss_dev), 2495 &sc->ciss_mtx, 2496 sc->ciss_max_requests - 2, 2497 sc->ciss_max_requests - 2, 2498 sc->ciss_cam_devq)) == NULL) { 2499 ciss_printf(sc, "can't allocate CAM SIM for controller %d\n", i); 2500 return(ENOMEM); 2501 } 2502 2503 /* 2504 * Register bus with this SIM. 2505 */ 2506 mtx_lock(&sc->ciss_mtx); 2507 if (i == 0 || sc->ciss_controllers[i].physical.bus != 0) { 2508 if (xpt_bus_register(sc->ciss_cam_sim[i], sc->ciss_dev, i) != 0) { 2509 ciss_printf(sc, "can't register SCSI bus %d\n", i); 2510 mtx_unlock(&sc->ciss_mtx); 2511 return (ENXIO); 2512 } 2513 } 2514 mtx_unlock(&sc->ciss_mtx); 2515 } 2516 2517 for (i = CISS_PHYSICAL_BASE; i < sc->ciss_max_physical_bus + 2518 CISS_PHYSICAL_BASE; i++) { 2519 if ((sc->ciss_cam_sim[i] = cam_sim_alloc(ciss_cam_action, ciss_cam_poll, 2520 "ciss", sc, 2521 device_get_unit(sc->ciss_dev), 2522 &sc->ciss_mtx, 1, 2523 sc->ciss_max_requests - 2, 2524 sc->ciss_cam_devq)) == NULL) { 2525 ciss_printf(sc, "can't allocate CAM SIM for controller %d\n", i); 2526 return (ENOMEM); 2527 } 2528 2529 mtx_lock(&sc->ciss_mtx); 2530 if (xpt_bus_register(sc->ciss_cam_sim[i], sc->ciss_dev, i) != 0) { 2531 ciss_printf(sc, "can't register SCSI bus %d\n", i); 2532 mtx_unlock(&sc->ciss_mtx); 2533 return (ENXIO); 2534 } 2535 mtx_unlock(&sc->ciss_mtx); 2536 } 2537 2538 /* 2539 * Initiate a rescan of the bus. 2540 */ 2541 mtx_lock(&sc->ciss_mtx); 2542 ciss_cam_rescan_all(sc); 2543 mtx_unlock(&sc->ciss_mtx); 2544 2545 return(0); 2546} 2547 2548/************************************************************************ 2549 * Initiate a rescan of the 'logical devices' SIM 2550 */ 2551static void 2552ciss_cam_rescan_target(struct ciss_softc *sc, int bus, int target) 2553{ 2554 struct cam_path *path; 2555 union ccb *ccb; 2556 2557 debug_called(1); 2558 2559 if ((ccb = malloc(sizeof(union ccb), CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO)) == NULL) { 2560 ciss_printf(sc, "rescan failed (can't allocate CCB)\n"); 2561 return; 2562 } 2563 2564 if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->ciss_cam_sim[bus]), 2565 target, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 2566 ciss_printf(sc, "rescan failed (can't create path)\n"); 2567 free(ccb, CISS_MALLOC_CLASS); 2568 return; 2569 } 2570 2571 xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/); 2572 ccb->ccb_h.func_code = XPT_SCAN_BUS; 2573 ccb->ccb_h.cbfcnp = ciss_cam_rescan_callback; 2574 ccb->crcn.flags = CAM_FLAG_NONE; 2575 xpt_action(ccb); 2576 2577 /* scan is now in progress */ 2578} 2579 2580static void 2581ciss_cam_rescan_all(struct ciss_softc *sc) 2582{ 2583 int i; 2584 2585 /* Rescan the logical buses */ 2586 for (i = 0; i < sc->ciss_max_logical_bus; i++) 2587 ciss_cam_rescan_target(sc, i, CAM_TARGET_WILDCARD); 2588 /* Rescan the physical buses */ 2589 for (i = CISS_PHYSICAL_BASE; i < sc->ciss_max_physical_bus + 2590 CISS_PHYSICAL_BASE; i++) 2591 ciss_cam_rescan_target(sc, i, CAM_TARGET_WILDCARD); 2592} 2593 2594static void 2595ciss_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb) 2596{ 2597 xpt_free_path(ccb->ccb_h.path); 2598 free(ccb, CISS_MALLOC_CLASS); 2599} 2600 2601/************************************************************************ 2602 * Handle requests coming from CAM 2603 */ 2604static void 2605ciss_cam_action(struct cam_sim *sim, union ccb *ccb) 2606{ 2607 struct ciss_softc *sc; 2608 struct ccb_scsiio *csio; 2609 int bus, target; 2610 int physical; 2611 2612 sc = cam_sim_softc(sim); 2613 bus = cam_sim_bus(sim); 2614 csio = (struct ccb_scsiio *)&ccb->csio; 2615 target = csio->ccb_h.target_id; 2616 physical = CISS_IS_PHYSICAL(bus); 2617 2618 switch (ccb->ccb_h.func_code) { 2619 2620 /* perform SCSI I/O */ 2621 case XPT_SCSI_IO: 2622 if (!ciss_cam_action_io(sim, csio)) 2623 return; 2624 break; 2625 2626 /* perform geometry calculations */ 2627 case XPT_CALC_GEOMETRY: 2628 { 2629 struct ccb_calc_geometry *ccg = &ccb->ccg; 2630 struct ciss_ldrive *ld; 2631 2632 debug(1, "XPT_CALC_GEOMETRY %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun); 2633 2634 ld = NULL; 2635 if (!physical) 2636 ld = &sc->ciss_logical[bus][target]; 2637 2638 /* 2639 * Use the cached geometry settings unless the fault tolerance 2640 * is invalid. 2641 */ 2642 if (physical || ld->cl_geometry.fault_tolerance == 0xFF) { 2643 u_int32_t secs_per_cylinder; 2644 2645 ccg->heads = 255; 2646 ccg->secs_per_track = 32; 2647 secs_per_cylinder = ccg->heads * ccg->secs_per_track; 2648 ccg->cylinders = ccg->volume_size / secs_per_cylinder; 2649 } else { 2650 ccg->heads = ld->cl_geometry.heads; 2651 ccg->secs_per_track = ld->cl_geometry.sectors; 2652 ccg->cylinders = ntohs(ld->cl_geometry.cylinders); 2653 } 2654 ccb->ccb_h.status = CAM_REQ_CMP; 2655 break; 2656 } 2657 2658 /* handle path attribute inquiry */ 2659 case XPT_PATH_INQ: 2660 { 2661 struct ccb_pathinq *cpi = &ccb->cpi; 2662 2663 debug(1, "XPT_PATH_INQ %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun); 2664 2665 cpi->version_num = 1; 2666 cpi->hba_inquiry = PI_TAG_ABLE; /* XXX is this correct? */ 2667 cpi->target_sprt = 0; 2668 cpi->hba_misc = 0; 2669 cpi->max_target = CISS_MAX_LOGICAL; 2670 cpi->max_lun = 0; /* 'logical drive' channel only */ 2671 cpi->initiator_id = CISS_MAX_LOGICAL; 2672 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2673 strncpy(cpi->hba_vid, "msmith@freebsd.org", HBA_IDLEN); 2674 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 2675 cpi->unit_number = cam_sim_unit(sim); 2676 cpi->bus_id = cam_sim_bus(sim); 2677 cpi->base_transfer_speed = 132 * 1024; /* XXX what to set this to? */ 2678 cpi->transport = XPORT_SPI; 2679 cpi->transport_version = 2; 2680 cpi->protocol = PROTO_SCSI; 2681 cpi->protocol_version = SCSI_REV_2; 2682 ccb->ccb_h.status = CAM_REQ_CMP; 2683 break; 2684 } 2685 2686 case XPT_GET_TRAN_SETTINGS: 2687 { 2688 struct ccb_trans_settings *cts = &ccb->cts; 2689 int bus, target; 2690 struct ccb_trans_settings_spi *spi = 2691 &cts->xport_specific.spi; 2692 2693 bus = cam_sim_bus(sim); 2694 target = cts->ccb_h.target_id; 2695 2696 debug(1, "XPT_GET_TRAN_SETTINGS %d:%d", bus, target); 2697 /* disconnect always OK */ 2698 cts->protocol = PROTO_SCSI; 2699 cts->protocol_version = SCSI_REV_2; 2700 cts->transport = XPORT_SPI; 2701 cts->transport_version = 2; 2702 2703 spi->valid = CTS_SPI_VALID_DISC; 2704 spi->flags = CTS_SPI_FLAGS_DISC_ENB; 2705 2706 cts->ccb_h.status = CAM_REQ_CMP; 2707 break; 2708 } 2709 2710 default: /* we can't do this */ 2711 debug(1, "unspported func_code = 0x%x", ccb->ccb_h.func_code); 2712 ccb->ccb_h.status = CAM_REQ_INVALID; 2713 break; 2714 } 2715 2716 xpt_done(ccb); 2717} 2718 2719/************************************************************************ 2720 * Handle a CAM SCSI I/O request. 2721 */ 2722static int 2723ciss_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio) 2724{ 2725 struct ciss_softc *sc; 2726 int bus, target; 2727 struct ciss_request *cr; 2728 struct ciss_command *cc; 2729 int error; 2730 2731 sc = cam_sim_softc(sim); 2732 bus = cam_sim_bus(sim); 2733 target = csio->ccb_h.target_id; 2734 2735 debug(2, "XPT_SCSI_IO %d:%d:%d", bus, target, csio->ccb_h.target_lun); 2736 2737 /* firmware does not support commands > 10 bytes */ 2738 if (csio->cdb_len > 12/*CISS_CDB_BUFFER_SIZE*/) { 2739 debug(3, " command too large (%d > %d)", csio->cdb_len, CISS_CDB_BUFFER_SIZE); 2740 csio->ccb_h.status = CAM_REQ_CMP_ERR; 2741 } 2742 2743 /* check that the CDB pointer is not to a physical address */ 2744 if ((csio->ccb_h.flags & CAM_CDB_POINTER) && (csio->ccb_h.flags & CAM_CDB_PHYS)) { 2745 debug(3, " CDB pointer is to physical address"); 2746 csio->ccb_h.status = CAM_REQ_CMP_ERR; 2747 } 2748 2749 /* if there is data transfer, it must be to/from a virtual address */ 2750 if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 2751 if (csio->ccb_h.flags & CAM_DATA_PHYS) { /* we can't map it */ 2752 debug(3, " data pointer is to physical address"); 2753 csio->ccb_h.status = CAM_REQ_CMP_ERR; 2754 } 2755 if (csio->ccb_h.flags & CAM_SCATTER_VALID) { /* we want to do the s/g setup */ 2756 debug(3, " data has premature s/g setup"); 2757 csio->ccb_h.status = CAM_REQ_CMP_ERR; 2758 } 2759 } 2760 2761 /* abandon aborted ccbs or those that have failed validation */ 2762 if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 2763 debug(3, "abandoning CCB due to abort/validation failure"); 2764 return(EINVAL); 2765 } 2766 2767 /* handle emulation of some SCSI commands ourself */ 2768 if (ciss_cam_emulate(sc, csio)) 2769 return(0); 2770 2771 /* 2772 * Get a request to manage this command. If we can't, return the 2773 * ccb, freeze the queue and flag so that we unfreeze it when a 2774 * request completes. 2775 */ 2776 if ((error = ciss_get_request(sc, &cr)) != 0) { 2777 xpt_freeze_simq(sim, 1); 2778 csio->ccb_h.status |= CAM_REQUEUE_REQ; 2779 return(error); 2780 } 2781 2782 /* 2783 * Build the command. 2784 */ 2785 cc = CISS_FIND_COMMAND(cr); 2786 cr->cr_data = csio->data_ptr; 2787 cr->cr_length = csio->dxfer_len; 2788 cr->cr_complete = ciss_cam_complete; 2789 cr->cr_private = csio; 2790 2791 /* 2792 * Target the right logical volume. 2793 */ 2794 if (CISS_IS_PHYSICAL(bus)) 2795 cc->header.address = 2796 sc->ciss_physical[CISS_CAM_TO_PBUS(bus)][target].cp_address; 2797 else 2798 cc->header.address = 2799 sc->ciss_logical[bus][target].cl_address; 2800 cc->cdb.cdb_length = csio->cdb_len; 2801 cc->cdb.type = CISS_CDB_TYPE_COMMAND; 2802 cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE; /* XXX ordered tags? */ 2803 if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 2804 cr->cr_flags = CISS_REQ_DATAOUT; 2805 cc->cdb.direction = CISS_CDB_DIRECTION_WRITE; 2806 } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2807 cr->cr_flags = CISS_REQ_DATAIN; 2808 cc->cdb.direction = CISS_CDB_DIRECTION_READ; 2809 } else { 2810 cr->cr_flags = 0; 2811 cc->cdb.direction = CISS_CDB_DIRECTION_NONE; 2812 } 2813 cc->cdb.timeout = (csio->ccb_h.timeout / 1000) + 1; 2814 if (csio->ccb_h.flags & CAM_CDB_POINTER) { 2815 bcopy(csio->cdb_io.cdb_ptr, &cc->cdb.cdb[0], csio->cdb_len); 2816 } else { 2817 bcopy(csio->cdb_io.cdb_bytes, &cc->cdb.cdb[0], csio->cdb_len); 2818 } 2819 2820 /* 2821 * Submit the request to the adapter. 2822 * 2823 * Note that this may fail if we're unable to map the request (and 2824 * if we ever learn a transport layer other than simple, may fail 2825 * if the adapter rejects the command). 2826 */ 2827 if ((error = ciss_start(cr)) != 0) { 2828 xpt_freeze_simq(sim, 1); 2829 if (error == EINPROGRESS) { 2830 csio->ccb_h.status |= CAM_RELEASE_SIMQ; 2831 error = 0; 2832 } else { 2833 csio->ccb_h.status |= CAM_REQUEUE_REQ; 2834 ciss_release_request(cr); 2835 } 2836 return(error); 2837 } 2838 2839 return(0); 2840} 2841 2842/************************************************************************ 2843 * Emulate SCSI commands the adapter doesn't handle as we might like. 2844 */ 2845static int 2846ciss_cam_emulate(struct ciss_softc *sc, struct ccb_scsiio *csio) 2847{ 2848 int bus, target; 2849 u_int8_t opcode; 2850 2851 target = csio->ccb_h.target_id; 2852 bus = cam_sim_bus(xpt_path_sim(csio->ccb_h.path)); 2853 opcode = (csio->ccb_h.flags & CAM_CDB_POINTER) ? 2854 *(u_int8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes[0]; 2855 2856 if (CISS_IS_PHYSICAL(bus)) { 2857 if (sc->ciss_physical[CISS_CAM_TO_PBUS(bus)][target].cp_online != 1) { 2858 csio->ccb_h.status = CAM_SEL_TIMEOUT; 2859 xpt_done((union ccb *)csio); 2860 return(1); 2861 } else 2862 return(0); 2863 } 2864 2865 /* 2866 * Handle requests for volumes that don't exist or are not online. 2867 * A selection timeout is slightly better than an illegal request. 2868 * Other errors might be better. 2869 */ 2870 if (sc->ciss_logical[bus][target].cl_status != CISS_LD_ONLINE) { 2871 csio->ccb_h.status = CAM_SEL_TIMEOUT; 2872 xpt_done((union ccb *)csio); 2873 return(1); 2874 } 2875 2876 /* if we have to fake Synchronise Cache */ 2877 if (sc->ciss_flags & CISS_FLAG_FAKE_SYNCH) { 2878 /* 2879 * If this is a Synchronise Cache command, typically issued when 2880 * a device is closed, flush the adapter and complete now. 2881 */ 2882 if (((csio->ccb_h.flags & CAM_CDB_POINTER) ? 2883 *(u_int8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes[0]) == SYNCHRONIZE_CACHE) { 2884 ciss_flush_adapter(sc); 2885 csio->ccb_h.status = CAM_REQ_CMP; 2886 xpt_done((union ccb *)csio); 2887 return(1); 2888 } 2889 } 2890 2891 return(0); 2892} 2893 2894/************************************************************************ 2895 * Check for possibly-completed commands. 2896 */ 2897static void 2898ciss_cam_poll(struct cam_sim *sim) 2899{ 2900 struct ciss_softc *sc = cam_sim_softc(sim); 2901 2902 debug_called(2); 2903 2904 ciss_done(sc); 2905} 2906 2907/************************************************************************ 2908 * Handle completion of a command - pass results back through the CCB 2909 */ 2910static void 2911ciss_cam_complete(struct ciss_request *cr) 2912{ 2913 struct ciss_softc *sc; 2914 struct ciss_command *cc; 2915 struct ciss_error_info *ce; 2916 struct ccb_scsiio *csio; 2917 int scsi_status; 2918 int command_status; 2919 2920 debug_called(2); 2921 2922 sc = cr->cr_sc; 2923 cc = CISS_FIND_COMMAND(cr); 2924 ce = (struct ciss_error_info *)&(cc->sg[0]); 2925 csio = (struct ccb_scsiio *)cr->cr_private; 2926 2927 /* 2928 * Extract status values from request. 2929 */ 2930 ciss_report_request(cr, &command_status, &scsi_status); 2931 csio->scsi_status = scsi_status; 2932 2933 /* 2934 * Handle specific SCSI status values. 2935 */ 2936 switch(scsi_status) { 2937 /* no status due to adapter error */ 2938 case -1: 2939 debug(0, "adapter error"); 2940 csio->ccb_h.status = CAM_REQ_CMP_ERR; 2941 break; 2942 2943 /* no status due to command completed OK */ 2944 case SCSI_STATUS_OK: /* CISS_SCSI_STATUS_GOOD */ 2945 debug(2, "SCSI_STATUS_OK"); 2946 csio->ccb_h.status = CAM_REQ_CMP; 2947 break; 2948 2949 /* check condition, sense data included */ 2950 case SCSI_STATUS_CHECK_COND: /* CISS_SCSI_STATUS_CHECK_CONDITION */ 2951 debug(0, "SCSI_STATUS_CHECK_COND sense size %d resid %d\n", 2952 ce->sense_length, ce->residual_count); 2953 bzero(&csio->sense_data, SSD_FULL_SIZE); 2954 bcopy(&ce->sense_info[0], &csio->sense_data, ce->sense_length); 2955 csio->sense_len = ce->sense_length; 2956 csio->resid = ce->residual_count; 2957 csio->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; 2958#ifdef CISS_DEBUG 2959 { 2960 struct scsi_sense_data *sns = (struct scsi_sense_data *)&ce->sense_info[0]; 2961 debug(0, "sense key %x", sns->flags & SSD_KEY); 2962 } 2963#endif 2964 break; 2965 2966 case SCSI_STATUS_BUSY: /* CISS_SCSI_STATUS_BUSY */ 2967 debug(0, "SCSI_STATUS_BUSY"); 2968 csio->ccb_h.status = CAM_SCSI_BUSY; 2969 break; 2970 2971 default: 2972 debug(0, "unknown status 0x%x", csio->scsi_status); 2973 csio->ccb_h.status = CAM_REQ_CMP_ERR; 2974 break; 2975 } 2976 2977 /* handle post-command fixup */ 2978 ciss_cam_complete_fixup(sc, csio); 2979 2980 /* tell CAM we're ready for more commands */ 2981 csio->ccb_h.status |= CAM_RELEASE_SIMQ; 2982 2983 xpt_done((union ccb *)csio); 2984 ciss_release_request(cr); 2985} 2986 2987/******************************************************************************** 2988 * Fix up the result of some commands here. 2989 */ 2990static void 2991ciss_cam_complete_fixup(struct ciss_softc *sc, struct ccb_scsiio *csio) 2992{ 2993 struct scsi_inquiry_data *inq; 2994 struct ciss_ldrive *cl; 2995 int bus, target; 2996 2997 if (((csio->ccb_h.flags & CAM_CDB_POINTER) ? 2998 *(u_int8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes[0]) == INQUIRY) { 2999 3000 inq = (struct scsi_inquiry_data *)csio->data_ptr; 3001 target = csio->ccb_h.target_id; 3002 bus = cam_sim_bus(xpt_path_sim(csio->ccb_h.path)); 3003 3004 /* 3005 * Don't let hard drives be seen by the DA driver. They will still be 3006 * attached by the PASS driver. 3007 */ 3008 if (CISS_IS_PHYSICAL(bus)) { 3009 if (SID_TYPE(inq) == T_DIRECT) 3010 inq->device = (inq->device & 0xe0) | T_NODEVICE; 3011 return; 3012 } 3013 3014 cl = &sc->ciss_logical[bus][target]; 3015 3016 padstr(inq->vendor, "COMPAQ", 8); 3017 padstr(inq->product, ciss_name_ldrive_org(cl->cl_ldrive->fault_tolerance), 8); 3018 padstr(inq->revision, ciss_name_ldrive_status(cl->cl_lstatus->status), 16); 3019 } 3020} 3021 3022 3023/******************************************************************************** 3024 * Find a peripheral attached at (target) 3025 */ 3026static struct cam_periph * 3027ciss_find_periph(struct ciss_softc *sc, int bus, int target) 3028{ 3029 struct cam_periph *periph; 3030 struct cam_path *path; 3031 int status; 3032 3033 status = xpt_create_path(&path, NULL, cam_sim_path(sc->ciss_cam_sim[bus]), 3034 target, 0); 3035 if (status == CAM_REQ_CMP) { 3036 periph = cam_periph_find(path, NULL); 3037 xpt_free_path(path); 3038 } else { 3039 periph = NULL; 3040 } 3041 return(periph); 3042} 3043 3044/******************************************************************************** 3045 * Name the device at (target) 3046 * 3047 * XXX is this strictly correct? 3048 */ 3049static int 3050ciss_name_device(struct ciss_softc *sc, int bus, int target) 3051{ 3052 struct cam_periph *periph; 3053 3054 if (CISS_IS_PHYSICAL(bus)) 3055 return (0); 3056 if ((periph = ciss_find_periph(sc, bus, target)) != NULL) { 3057 sprintf(sc->ciss_logical[bus][target].cl_name, "%s%d", 3058 periph->periph_name, periph->unit_number); 3059 return(0); 3060 } 3061 sc->ciss_logical[bus][target].cl_name[0] = 0; 3062 return(ENOENT); 3063} 3064 3065/************************************************************************ 3066 * Periodic status monitoring. 3067 */ 3068static void 3069ciss_periodic(void *arg) 3070{ 3071 struct ciss_softc *sc; 3072 struct ciss_request *cr = NULL; 3073 struct ciss_command *cc = NULL; 3074 int error = 0; 3075 3076 debug_called(1); 3077 3078 sc = (struct ciss_softc *)arg; 3079 3080 /* 3081 * Check the adapter heartbeat. 3082 */ 3083 if (sc->ciss_cfg->heartbeat == sc->ciss_heartbeat) { 3084 sc->ciss_heart_attack++; 3085 debug(0, "adapter heart attack in progress 0x%x/%d", 3086 sc->ciss_heartbeat, sc->ciss_heart_attack); 3087 if (sc->ciss_heart_attack == 3) { 3088 ciss_printf(sc, "ADAPTER HEARTBEAT FAILED\n"); 3089 ciss_disable_adapter(sc); 3090 return; 3091 } 3092 } else { 3093 sc->ciss_heartbeat = sc->ciss_cfg->heartbeat; 3094 sc->ciss_heart_attack = 0; 3095 debug(3, "new heartbeat 0x%x", sc->ciss_heartbeat); 3096 } 3097 3098 /* 3099 * Send the NOP message and wait for a response. 3100 */ 3101 if ((error = ciss_get_request(sc, &cr)) == 0) { 3102 cc = CISS_FIND_COMMAND(cr); 3103 cc->cdb.cdb_length = 1; 3104 cc->cdb.type = CISS_CDB_TYPE_MESSAGE; 3105 cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE; 3106 cc->cdb.direction = CISS_CDB_DIRECTION_WRITE; 3107 cc->cdb.timeout = 0; 3108 cc->cdb.cdb[0] = CISS_OPCODE_MESSAGE_NOP; 3109 3110 if ((error = ciss_synch_request(cr, 10 * 1000)) != 0) { 3111 ciss_printf(sc, "SENDING NOP MESSAGE FAILED\n"); 3112 } 3113 3114 ciss_release_request(cr); 3115 } 3116 3117 /* 3118 * If the notify event request has died for some reason, or has 3119 * not started yet, restart it. 3120 */ 3121 if (!(sc->ciss_flags & CISS_FLAG_NOTIFY_OK)) { 3122 debug(0, "(re)starting Event Notify chain"); 3123 ciss_notify_event(sc); 3124 } 3125 3126 /* 3127 * Reschedule. 3128 */ 3129 callout_reset(&sc->ciss_periodic, CISS_HEARTBEAT_RATE * hz, ciss_periodic, sc); 3130} 3131 3132/************************************************************************ 3133 * Disable the adapter. 3134 * 3135 * The all requests in completed queue is failed with hardware error. 3136 * This will cause failover in a multipath configuration. 3137 */ 3138static void 3139ciss_disable_adapter(struct ciss_softc *sc) 3140{ 3141 struct ciss_request *cr; 3142 struct ciss_command *cc; 3143 struct ciss_error_info *ce; 3144 int s; 3145 3146 s = splcam(); 3147 3148 CISS_TL_SIMPLE_DISABLE_INTERRUPTS(sc); 3149 pci_disable_busmaster(sc->ciss_dev); 3150 sc->ciss_flags &= ~CISS_FLAG_RUNNING; 3151 3152 for (;;) { 3153 if ((cr = ciss_dequeue_busy(sc)) == NULL) 3154 break; 3155 3156 cc = CISS_FIND_COMMAND(cr); 3157 ce = (struct ciss_error_info *)&(cc->sg[0]); 3158 ce->command_status = CISS_CMD_STATUS_HARDWARE_ERROR; 3159 ciss_enqueue_complete(cr); 3160 } 3161 3162 for (;;) { 3163 if ((cr = ciss_dequeue_complete(sc)) == NULL) 3164 break; 3165 3166 /* 3167 * If the request has a callback, invoke it. 3168 */ 3169 if (cr->cr_complete != NULL) { 3170 cr->cr_complete(cr); 3171 continue; 3172 } 3173 3174 /* 3175 * If someone is sleeping on this request, wake them up. 3176 */ 3177 if (cr->cr_flags & CISS_REQ_SLEEP) { 3178 cr->cr_flags &= ~CISS_REQ_SLEEP; 3179 wakeup(cr); 3180 continue; 3181 } 3182 } 3183 3184 splx(s); 3185} 3186 3187/************************************************************************ 3188 * Request a notification response from the adapter. 3189 * 3190 * If (cr) is NULL, this is the first request of the adapter, so 3191 * reset the adapter's message pointer and start with the oldest 3192 * message available. 3193 */ 3194static void 3195ciss_notify_event(struct ciss_softc *sc) 3196{ 3197 struct ciss_request *cr; 3198 struct ciss_command *cc; 3199 struct ciss_notify_cdb *cnc; 3200 int error; 3201 3202 debug_called(1); 3203 3204 cr = sc->ciss_periodic_notify; 3205 3206 /* get a request if we don't already have one */ 3207 if (cr == NULL) { 3208 if ((error = ciss_get_request(sc, &cr)) != 0) { 3209 debug(0, "can't get notify event request"); 3210 goto out; 3211 } 3212 sc->ciss_periodic_notify = cr; 3213 cr->cr_complete = ciss_notify_complete; 3214 debug(1, "acquired request %d", cr->cr_tag); 3215 } 3216 3217 /* 3218 * Get a databuffer if we don't already have one, note that the 3219 * adapter command wants a larger buffer than the actual 3220 * structure. 3221 */ 3222 if (cr->cr_data == NULL) { 3223 if ((cr->cr_data = malloc(CISS_NOTIFY_DATA_SIZE, CISS_MALLOC_CLASS, M_NOWAIT)) == NULL) { 3224 debug(0, "can't get notify event request buffer"); 3225 error = ENOMEM; 3226 goto out; 3227 } 3228 cr->cr_length = CISS_NOTIFY_DATA_SIZE; 3229 } 3230 3231 /* re-setup the request's command (since we never release it) XXX overkill*/ 3232 ciss_preen_command(cr); 3233 3234 /* (re)build the notify event command */ 3235 cc = CISS_FIND_COMMAND(cr); 3236 cc->header.address.physical.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL; 3237 cc->header.address.physical.bus = 0; 3238 cc->header.address.physical.target = 0; 3239 3240 cc->cdb.cdb_length = sizeof(*cnc); 3241 cc->cdb.type = CISS_CDB_TYPE_COMMAND; 3242 cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE; 3243 cc->cdb.direction = CISS_CDB_DIRECTION_READ; 3244 cc->cdb.timeout = 0; /* no timeout, we hope */ 3245 3246 cnc = (struct ciss_notify_cdb *)&(cc->cdb.cdb[0]); 3247 bzero(cr->cr_data, CISS_NOTIFY_DATA_SIZE); 3248 cnc->opcode = CISS_OPCODE_READ; 3249 cnc->command = CISS_COMMAND_NOTIFY_ON_EVENT; 3250 cnc->timeout = 0; /* no timeout, we hope */ 3251 cnc->synchronous = 0; 3252 cnc->ordered = 0; 3253 cnc->seek_to_oldest = 0; 3254 if ((sc->ciss_flags & CISS_FLAG_RUNNING) == 0) 3255 cnc->new_only = 1; 3256 else 3257 cnc->new_only = 0; 3258 cnc->length = htonl(CISS_NOTIFY_DATA_SIZE); 3259 3260 /* submit the request */ 3261 error = ciss_start(cr); 3262 3263 out: 3264 if (error) { 3265 if (cr != NULL) { 3266 if (cr->cr_data != NULL) 3267 free(cr->cr_data, CISS_MALLOC_CLASS); 3268 ciss_release_request(cr); 3269 } 3270 sc->ciss_periodic_notify = NULL; 3271 debug(0, "can't submit notify event request"); 3272 sc->ciss_flags &= ~CISS_FLAG_NOTIFY_OK; 3273 } else { 3274 debug(1, "notify event submitted"); 3275 sc->ciss_flags |= CISS_FLAG_NOTIFY_OK; 3276 } 3277} 3278 3279static void 3280ciss_notify_complete(struct ciss_request *cr) 3281{ 3282 struct ciss_command *cc; 3283 struct ciss_notify *cn; 3284 struct ciss_softc *sc; 3285 int scsi_status; 3286 int command_status; 3287 debug_called(1); 3288 3289 cc = CISS_FIND_COMMAND(cr); 3290 cn = (struct ciss_notify *)cr->cr_data; 3291 sc = cr->cr_sc; 3292 3293 /* 3294 * Report request results, decode status. 3295 */ 3296 ciss_report_request(cr, &command_status, &scsi_status); 3297 3298 /* 3299 * Abort the chain on a fatal error. 3300 * 3301 * XXX which of these are actually errors? 3302 */ 3303 if ((command_status != CISS_CMD_STATUS_SUCCESS) && 3304 (command_status != CISS_CMD_STATUS_TARGET_STATUS) && 3305 (command_status != CISS_CMD_STATUS_TIMEOUT)) { /* XXX timeout? */ 3306 ciss_printf(sc, "fatal error in Notify Event request (%s)\n", 3307 ciss_name_command_status(command_status)); 3308 ciss_release_request(cr); 3309 sc->ciss_flags &= ~CISS_FLAG_NOTIFY_OK; 3310 return; 3311 } 3312 3313 /* 3314 * If the adapter gave us a text message, print it. 3315 */ 3316 if (cn->message[0] != 0) 3317 ciss_printf(sc, "*** %.80s\n", cn->message); 3318 3319 debug(0, "notify event class %d subclass %d detail %d", 3320 cn->class, cn->subclass, cn->detail); 3321 3322 /* 3323 * If the response indicates that the notifier has been aborted, 3324 * release the notifier command. 3325 */ 3326 if ((cn->class == CISS_NOTIFY_NOTIFIER) && 3327 (cn->subclass == CISS_NOTIFY_NOTIFIER_STATUS) && 3328 (cn->detail == 1)) { 3329 debug(0, "notifier exiting"); 3330 sc->ciss_flags &= ~CISS_FLAG_NOTIFY_OK; 3331 ciss_release_request(cr); 3332 sc->ciss_periodic_notify = NULL; 3333 wakeup(&sc->ciss_periodic_notify); 3334 } else { 3335 /* Handle notify events in a kernel thread */ 3336 ciss_enqueue_notify(cr); 3337 sc->ciss_periodic_notify = NULL; 3338 wakeup(&sc->ciss_periodic_notify); 3339 wakeup(&sc->ciss_notify); 3340 } 3341 /* 3342 * Send a new notify event command, if we're not aborting. 3343 */ 3344 if (!(sc->ciss_flags & CISS_FLAG_ABORTING)) { 3345 ciss_notify_event(sc); 3346 } 3347} 3348 3349/************************************************************************ 3350 * Abort the Notify Event chain. 3351 * 3352 * Note that we can't just abort the command in progress; we have to 3353 * explicitly issue an Abort Notify Event command in order for the 3354 * adapter to clean up correctly. 3355 * 3356 * If we are called with CISS_FLAG_ABORTING set in the adapter softc, 3357 * the chain will not restart itself. 3358 */ 3359static int 3360ciss_notify_abort(struct ciss_softc *sc) 3361{ 3362 struct ciss_request *cr; 3363 struct ciss_command *cc; 3364 struct ciss_notify_cdb *cnc; 3365 int error, s, command_status, scsi_status; 3366 3367 debug_called(1); 3368 3369 cr = NULL; 3370 error = 0; 3371 3372 /* verify that there's an outstanding command */ 3373 if (!(sc->ciss_flags & CISS_FLAG_NOTIFY_OK)) 3374 goto out; 3375 3376 /* get a command to issue the abort with */ 3377 if ((error = ciss_get_request(sc, &cr))) 3378 goto out; 3379 3380 /* get a buffer for the result */ 3381 if ((cr->cr_data = malloc(CISS_NOTIFY_DATA_SIZE, CISS_MALLOC_CLASS, M_NOWAIT)) == NULL) { 3382 debug(0, "can't get notify event request buffer"); 3383 error = ENOMEM; 3384 goto out; 3385 } 3386 cr->cr_length = CISS_NOTIFY_DATA_SIZE; 3387 3388 /* build the CDB */ 3389 cc = CISS_FIND_COMMAND(cr); 3390 cc->header.address.physical.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL; 3391 cc->header.address.physical.bus = 0; 3392 cc->header.address.physical.target = 0; 3393 cc->cdb.cdb_length = sizeof(*cnc); 3394 cc->cdb.type = CISS_CDB_TYPE_COMMAND; 3395 cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE; 3396 cc->cdb.direction = CISS_CDB_DIRECTION_READ; 3397 cc->cdb.timeout = 0; /* no timeout, we hope */ 3398 3399 cnc = (struct ciss_notify_cdb *)&(cc->cdb.cdb[0]); 3400 bzero(cnc, sizeof(*cnc)); 3401 cnc->opcode = CISS_OPCODE_WRITE; 3402 cnc->command = CISS_COMMAND_ABORT_NOTIFY; 3403 cnc->length = htonl(CISS_NOTIFY_DATA_SIZE); 3404 3405 ciss_print_request(cr); 3406 3407 /* 3408 * Submit the request and wait for it to complete. 3409 */ 3410 if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) { 3411 ciss_printf(sc, "Abort Notify Event command failed (%d)\n", error); 3412 goto out; 3413 } 3414 3415 /* 3416 * Check response. 3417 */ 3418 ciss_report_request(cr, &command_status, &scsi_status); 3419 switch(command_status) { 3420 case CISS_CMD_STATUS_SUCCESS: 3421 break; 3422 case CISS_CMD_STATUS_INVALID_COMMAND: 3423 /* 3424 * Some older adapters don't support the CISS version of this 3425 * command. Fall back to using the BMIC version. 3426 */ 3427 error = ciss_notify_abort_bmic(sc); 3428 if (error != 0) 3429 goto out; 3430 break; 3431 3432 case CISS_CMD_STATUS_TARGET_STATUS: 3433 /* 3434 * This can happen if the adapter thinks there wasn't an outstanding 3435 * Notify Event command but we did. We clean up here. 3436 */ 3437 if (scsi_status == CISS_SCSI_STATUS_CHECK_CONDITION) { 3438 if (sc->ciss_periodic_notify != NULL) 3439 ciss_release_request(sc->ciss_periodic_notify); 3440 error = 0; 3441 goto out; 3442 } 3443 /* FALLTHROUGH */ 3444 3445 default: 3446 ciss_printf(sc, "Abort Notify Event command failed (%s)\n", 3447 ciss_name_command_status(command_status)); 3448 error = EIO; 3449 goto out; 3450 } 3451 3452 /* 3453 * Sleep waiting for the notifier command to complete. Note 3454 * that if it doesn't, we may end up in a bad situation, since 3455 * the adapter may deliver it later. Also note that the adapter 3456 * requires the Notify Event command to be cancelled in order to 3457 * maintain internal bookkeeping. 3458 */ 3459 s = splcam(); 3460 while (sc->ciss_periodic_notify != NULL) { 3461 error = msleep(&sc->ciss_periodic_notify, &sc->ciss_mtx, PRIBIO, "cissNEA", hz * 5); 3462 if (error == EWOULDBLOCK) { 3463 ciss_printf(sc, "Notify Event command failed to abort, adapter may wedge.\n"); 3464 break; 3465 } 3466 } 3467 splx(s); 3468 3469 out: 3470 /* release the cancel request */ 3471 if (cr != NULL) { 3472 if (cr->cr_data != NULL) 3473 free(cr->cr_data, CISS_MALLOC_CLASS); 3474 ciss_release_request(cr); 3475 } 3476 if (error == 0) 3477 sc->ciss_flags &= ~CISS_FLAG_NOTIFY_OK; 3478 return(error); 3479} 3480 3481/************************************************************************ 3482 * Abort the Notify Event chain using a BMIC command. 3483 */ 3484static int 3485ciss_notify_abort_bmic(struct ciss_softc *sc) 3486{ 3487 struct ciss_request *cr; 3488 int error, command_status; 3489 3490 debug_called(1); 3491 3492 cr = NULL; 3493 error = 0; 3494 3495 /* verify that there's an outstanding command */ 3496 if (!(sc->ciss_flags & CISS_FLAG_NOTIFY_OK)) 3497 goto out; 3498 3499 /* 3500 * Build a BMIC command to cancel the Notify on Event command. 3501 * 3502 * Note that we are sending a CISS opcode here. Odd. 3503 */ 3504 if ((error = ciss_get_bmic_request(sc, &cr, CISS_COMMAND_ABORT_NOTIFY, 3505 NULL, 0)) != 0) 3506 goto out; 3507 3508 /* 3509 * Submit the request and wait for it to complete. 3510 */ 3511 if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) { 3512 ciss_printf(sc, "error sending BMIC Cancel Notify on Event command (%d)\n", error); 3513 goto out; 3514 } 3515 3516 /* 3517 * Check response. 3518 */ 3519 ciss_report_request(cr, &command_status, NULL); 3520 switch(command_status) { 3521 case CISS_CMD_STATUS_SUCCESS: 3522 break; 3523 default: 3524 ciss_printf(sc, "error cancelling Notify on Event (%s)\n", 3525 ciss_name_command_status(command_status)); 3526 error = EIO; 3527 goto out; 3528 } 3529 3530out: 3531 if (cr != NULL) 3532 ciss_release_request(cr); 3533 return(error); 3534} 3535 3536/************************************************************************ 3537 * Handle rescanning all the logical volumes when a notify event 3538 * causes the drives to come online or offline. 3539 */ 3540static void 3541ciss_notify_rescan_logical(struct ciss_softc *sc) 3542{ 3543 struct ciss_lun_report *cll; 3544 struct ciss_ldrive *ld; 3545 int i, j, ndrives; 3546 3547 /* 3548 * We must rescan all logical volumes to get the right logical 3549 * drive address. 3550 */ 3551 cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_LOGICAL_LUNS, 3552 CISS_MAX_LOGICAL); 3553 if (cll == NULL) 3554 return; 3555 3556 ndrives = (ntohl(cll->list_size) / sizeof(union ciss_device_address)); 3557 3558 /* 3559 * Delete any of the drives which were destroyed by the 3560 * firmware. 3561 */ 3562 for (i = 0; i < sc->ciss_max_logical_bus; i++) { 3563 for (j = 0; j < CISS_MAX_LOGICAL; j++) { 3564 ld = &sc->ciss_logical[i][j]; 3565 3566 if (ld->cl_update == 0) 3567 continue; 3568 3569 if (ld->cl_status != CISS_LD_ONLINE) { 3570 ciss_cam_rescan_target(sc, i, j); 3571 ld->cl_update = 0; 3572 if (ld->cl_ldrive) 3573 free(ld->cl_ldrive, CISS_MALLOC_CLASS); 3574 if (ld->cl_lstatus) 3575 free(ld->cl_lstatus, CISS_MALLOC_CLASS); 3576 3577 ld->cl_ldrive = NULL; 3578 ld->cl_lstatus = NULL; 3579 } 3580 } 3581 } 3582 3583 /* 3584 * Scan for new drives. 3585 */ 3586 for (i = 0; i < ndrives; i++) { 3587 int bus, target; 3588 3589 bus = CISS_LUN_TO_BUS(cll->lun[i].logical.lun); 3590 target = CISS_LUN_TO_TARGET(cll->lun[i].logical.lun); 3591 ld = &sc->ciss_logical[bus][target]; 3592 3593 if (ld->cl_update == 0) 3594 continue; 3595 3596 ld->cl_update = 0; 3597 ld->cl_address = cll->lun[i]; 3598 ld->cl_controller = &sc->ciss_controllers[bus]; 3599 if (ciss_identify_logical(sc, ld) == 0) { 3600 ciss_cam_rescan_target(sc, bus, target); 3601 } 3602 } 3603 free(cll, CISS_MALLOC_CLASS); 3604} 3605 3606/************************************************************************ 3607 * Handle a notify event relating to the status of a logical drive. 3608 * 3609 * XXX need to be able to defer some of these to properly handle 3610 * calling the "ID Physical drive" command, unless the 'extended' 3611 * drive IDs are always in BIG_MAP format. 3612 */ 3613static void 3614ciss_notify_logical(struct ciss_softc *sc, struct ciss_notify *cn) 3615{ 3616 struct ciss_ldrive *ld; 3617 int ostatus, bus, target; 3618 3619 debug_called(2); 3620 3621 bus = cn->device.physical.bus; 3622 target = cn->data.logical_status.logical_drive; 3623 ld = &sc->ciss_logical[bus][target]; 3624 3625 switch (cn->subclass) { 3626 case CISS_NOTIFY_LOGICAL_STATUS: 3627 switch (cn->detail) { 3628 case 0: 3629 ciss_name_device(sc, bus, target); 3630 ciss_printf(sc, "logical drive %d (%s) changed status %s->%s, spare status 0x%b\n", 3631 cn->data.logical_status.logical_drive, ld->cl_name, 3632 ciss_name_ldrive_status(cn->data.logical_status.previous_state), 3633 ciss_name_ldrive_status(cn->data.logical_status.new_state), 3634 cn->data.logical_status.spare_state, 3635 "\20\1configured\2rebuilding\3failed\4in use\5available\n"); 3636 3637 /* 3638 * Update our idea of the drive's status. 3639 */ 3640 ostatus = ciss_decode_ldrive_status(cn->data.logical_status.previous_state); 3641 ld->cl_status = ciss_decode_ldrive_status(cn->data.logical_status.new_state); 3642 if (ld->cl_lstatus != NULL) 3643 ld->cl_lstatus->status = cn->data.logical_status.new_state; 3644 3645 /* 3646 * Have CAM rescan the drive if its status has changed. 3647 */ 3648 if (ostatus != ld->cl_status) { 3649 ld->cl_update = 1; 3650 ciss_notify_rescan_logical(sc); 3651 } 3652 3653 break; 3654 3655 case 1: /* logical drive has recognised new media, needs Accept Media Exchange */ 3656 ciss_name_device(sc, bus, target); 3657 ciss_printf(sc, "logical drive %d (%s) media exchanged, ready to go online\n", 3658 cn->data.logical_status.logical_drive, ld->cl_name); 3659 ciss_accept_media(sc, ld); 3660 3661 ld->cl_update = 1; 3662 ld->cl_status = ciss_decode_ldrive_status(cn->data.logical_status.new_state); 3663 ciss_notify_rescan_logical(sc); 3664 break; 3665 3666 case 2: 3667 case 3: 3668 ciss_printf(sc, "rebuild of logical drive %d (%s) failed due to %s error\n", 3669 cn->data.rebuild_aborted.logical_drive, 3670 ld->cl_name, 3671 (cn->detail == 2) ? "read" : "write"); 3672 break; 3673 } 3674 break; 3675 3676 case CISS_NOTIFY_LOGICAL_ERROR: 3677 if (cn->detail == 0) { 3678 ciss_printf(sc, "FATAL I/O ERROR on logical drive %d (%s), SCSI port %d ID %d\n", 3679 cn->data.io_error.logical_drive, 3680 ld->cl_name, 3681 cn->data.io_error.failure_bus, 3682 cn->data.io_error.failure_drive); 3683 /* XXX should we take the drive down at this point, or will we be told? */ 3684 } 3685 break; 3686 3687 case CISS_NOTIFY_LOGICAL_SURFACE: 3688 if (cn->detail == 0) 3689 ciss_printf(sc, "logical drive %d (%s) completed consistency initialisation\n", 3690 cn->data.consistency_completed.logical_drive, 3691 ld->cl_name); 3692 break; 3693 } 3694} 3695 3696/************************************************************************ 3697 * Handle a notify event relating to the status of a physical drive. 3698 */ 3699static void 3700ciss_notify_physical(struct ciss_softc *sc, struct ciss_notify *cn) 3701{ 3702} 3703 3704/************************************************************************ 3705 * Handle a notify event relating to the status of a physical drive. 3706 */ 3707static void 3708ciss_notify_hotplug(struct ciss_softc *sc, struct ciss_notify *cn) 3709{ 3710 struct ciss_lun_report *cll = NULL; 3711 int bus, target; 3712 int s; 3713 3714 switch (cn->subclass) { 3715 case CISS_NOTIFY_HOTPLUG_PHYSICAL: 3716 case CISS_NOTIFY_HOTPLUG_NONDISK: 3717 bus = CISS_BIG_MAP_BUS(sc, cn->data.drive.big_physical_drive_number); 3718 target = 3719 CISS_BIG_MAP_TARGET(sc, cn->data.drive.big_physical_drive_number); 3720 3721 s = splcam(); 3722 if (cn->detail == 0) { 3723 /* 3724 * Mark the device offline so that it'll start producing selection 3725 * timeouts to the upper layer. 3726 */ 3727 if ((bus >= 0) && (target >= 0)) 3728 sc->ciss_physical[bus][target].cp_online = 0; 3729 } else { 3730 /* 3731 * Rescan the physical lun list for new items 3732 */ 3733 cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_PHYSICAL_LUNS, 3734 CISS_MAX_PHYSICAL); 3735 if (cll == NULL) { 3736 ciss_printf(sc, "Warning, cannot get physical lun list\n"); 3737 break; 3738 } 3739 ciss_filter_physical(sc, cll); 3740 } 3741 splx(s); 3742 break; 3743 3744 default: 3745 ciss_printf(sc, "Unknown hotplug event %d\n", cn->subclass); 3746 return; 3747 } 3748 3749 if (cll != NULL) 3750 free(cll, CISS_MALLOC_CLASS); 3751} 3752 3753/************************************************************************ 3754 * Handle deferred processing of notify events. Notify events may need 3755 * sleep which is unsafe during an interrupt. 3756 */ 3757static void 3758ciss_notify_thread(void *arg) 3759{ 3760 struct ciss_softc *sc; 3761 struct ciss_request *cr; 3762 struct ciss_notify *cn; 3763 int s; 3764 3765 sc = (struct ciss_softc *)arg; 3766#if __FreeBSD_version >= 500000 3767 mtx_lock(&sc->ciss_mtx); 3768#endif 3769 3770 s = splcam(); 3771 for (;;) { 3772 if (TAILQ_EMPTY(&sc->ciss_notify) != 0 && 3773 (sc->ciss_flags & CISS_FLAG_THREAD_SHUT) == 0) { 3774 msleep(&sc->ciss_notify, &sc->ciss_mtx, PUSER, "idle", 0); 3775 } 3776 3777 if (sc->ciss_flags & CISS_FLAG_THREAD_SHUT) 3778 break; 3779 3780 cr = ciss_dequeue_notify(sc); 3781 splx(s); 3782 3783 if (cr == NULL) 3784 panic("cr null"); 3785 cn = (struct ciss_notify *)cr->cr_data; 3786 3787 switch (cn->class) { 3788 case CISS_NOTIFY_HOTPLUG: 3789 ciss_notify_hotplug(sc, cn); 3790 break; 3791 case CISS_NOTIFY_LOGICAL: 3792 ciss_notify_logical(sc, cn); 3793 break; 3794 case CISS_NOTIFY_PHYSICAL: 3795 ciss_notify_physical(sc, cn); 3796 break; 3797 } 3798 3799 ciss_release_request(cr); 3800 3801 s = splcam(); 3802 } 3803 sc->ciss_notify_thread = NULL; 3804 wakeup(&sc->ciss_notify_thread); 3805 splx(s); 3806 3807#if __FreeBSD_version >= 500000 3808 mtx_unlock(&sc->ciss_mtx); 3809#endif 3810 kthread_exit(0); 3811} 3812 3813/************************************************************************ 3814 * Start the notification kernel thread. 3815 */ 3816static void 3817ciss_spawn_notify_thread(struct ciss_softc *sc) 3818{ 3819 3820#if __FreeBSD_version > 500005 3821 if (kthread_create((void(*)(void *))ciss_notify_thread, sc, 3822 &sc->ciss_notify_thread, 0, 0, "ciss_notify%d", 3823 device_get_unit(sc->ciss_dev))) 3824#else 3825 if (kthread_create((void(*)(void *))ciss_notify_thread, sc, 3826 &sc->ciss_notify_thread, "ciss_notify%d", 3827 device_get_unit(sc->ciss_dev))) 3828#endif 3829 panic("Could not create notify thread\n"); 3830} 3831 3832/************************************************************************ 3833 * Kill the notification kernel thread. 3834 */ 3835static void 3836ciss_kill_notify_thread(struct ciss_softc *sc) 3837{ 3838 3839 if (sc->ciss_notify_thread == NULL) 3840 return; 3841 3842 sc->ciss_flags |= CISS_FLAG_THREAD_SHUT; 3843 wakeup(&sc->ciss_notify); 3844 msleep(&sc->ciss_notify_thread, &sc->ciss_mtx, PUSER, "thtrm", 0); 3845} 3846 3847/************************************************************************ 3848 * Print a request. 3849 */ 3850static void 3851ciss_print_request(struct ciss_request *cr) 3852{ 3853 struct ciss_softc *sc; 3854 struct ciss_command *cc; 3855 int i; 3856 3857 sc = cr->cr_sc; 3858 cc = CISS_FIND_COMMAND(cr); 3859 3860 ciss_printf(sc, "REQUEST @ %p\n", cr); 3861 ciss_printf(sc, " data %p/%d tag %d flags %b\n", 3862 cr->cr_data, cr->cr_length, cr->cr_tag, cr->cr_flags, 3863 "\20\1mapped\2sleep\3poll\4dataout\5datain\n"); 3864 ciss_printf(sc, " sg list/total %d/%d host tag 0x%x\n", 3865 cc->header.sg_in_list, cc->header.sg_total, cc->header.host_tag); 3866 switch(cc->header.address.mode.mode) { 3867 case CISS_HDR_ADDRESS_MODE_PERIPHERAL: 3868 case CISS_HDR_ADDRESS_MODE_MASK_PERIPHERAL: 3869 ciss_printf(sc, " physical bus %d target %d\n", 3870 cc->header.address.physical.bus, cc->header.address.physical.target); 3871 break; 3872 case CISS_HDR_ADDRESS_MODE_LOGICAL: 3873 ciss_printf(sc, " logical unit %d\n", cc->header.address.logical.lun); 3874 break; 3875 } 3876 ciss_printf(sc, " %s cdb length %d type %s attribute %s\n", 3877 (cc->cdb.direction == CISS_CDB_DIRECTION_NONE) ? "no-I/O" : 3878 (cc->cdb.direction == CISS_CDB_DIRECTION_READ) ? "READ" : 3879 (cc->cdb.direction == CISS_CDB_DIRECTION_WRITE) ? "WRITE" : "??", 3880 cc->cdb.cdb_length, 3881 (cc->cdb.type == CISS_CDB_TYPE_COMMAND) ? "command" : 3882 (cc->cdb.type == CISS_CDB_TYPE_MESSAGE) ? "message" : "??", 3883 (cc->cdb.attribute == CISS_CDB_ATTRIBUTE_UNTAGGED) ? "untagged" : 3884 (cc->cdb.attribute == CISS_CDB_ATTRIBUTE_SIMPLE) ? "simple" : 3885 (cc->cdb.attribute == CISS_CDB_ATTRIBUTE_HEAD_OF_QUEUE) ? "head-of-queue" : 3886 (cc->cdb.attribute == CISS_CDB_ATTRIBUTE_ORDERED) ? "ordered" : 3887 (cc->cdb.attribute == CISS_CDB_ATTRIBUTE_AUTO_CONTINGENT) ? "auto-contingent" : "??"); 3888 ciss_printf(sc, " %*D\n", cc->cdb.cdb_length, &cc->cdb.cdb[0], " "); 3889 3890 if (cc->header.host_tag & CISS_HDR_HOST_TAG_ERROR) { 3891 /* XXX print error info */ 3892 } else { 3893 /* since we don't use chained s/g, don't support it here */ 3894 for (i = 0; i < cc->header.sg_in_list; i++) { 3895 if ((i % 4) == 0) 3896 ciss_printf(sc, " "); 3897 printf("0x%08x/%d ", (u_int32_t)cc->sg[i].address, cc->sg[i].length); 3898 if ((((i + 1) % 4) == 0) || (i == (cc->header.sg_in_list - 1))) 3899 printf("\n"); 3900 } 3901 } 3902} 3903 3904/************************************************************************ 3905 * Print information about the status of a logical drive. 3906 */ 3907static void 3908ciss_print_ldrive(struct ciss_softc *sc, struct ciss_ldrive *ld) 3909{ 3910 int bus, target, i; 3911 3912 if (ld->cl_lstatus == NULL) { 3913 printf("does not exist\n"); 3914 return; 3915 } 3916 3917 /* print drive status */ 3918 switch(ld->cl_lstatus->status) { 3919 case CISS_LSTATUS_OK: 3920 printf("online\n"); 3921 break; 3922 case CISS_LSTATUS_INTERIM_RECOVERY: 3923 printf("in interim recovery mode\n"); 3924 break; 3925 case CISS_LSTATUS_READY_RECOVERY: 3926 printf("ready to begin recovery\n"); 3927 break; 3928 case CISS_LSTATUS_RECOVERING: 3929 bus = CISS_BIG_MAP_BUS(sc, ld->cl_lstatus->drive_rebuilding); 3930 target = CISS_BIG_MAP_BUS(sc, ld->cl_lstatus->drive_rebuilding); 3931 printf("being recovered, working on physical drive %d.%d, %u blocks remaining\n", 3932 bus, target, ld->cl_lstatus->blocks_to_recover); 3933 break; 3934 case CISS_LSTATUS_EXPANDING: 3935 printf("being expanded, %u blocks remaining\n", 3936 ld->cl_lstatus->blocks_to_recover); 3937 break; 3938 case CISS_LSTATUS_QUEUED_FOR_EXPANSION: 3939 printf("queued for expansion\n"); 3940 break; 3941 case CISS_LSTATUS_FAILED: 3942 printf("queued for expansion\n"); 3943 break; 3944 case CISS_LSTATUS_WRONG_PDRIVE: 3945 printf("wrong physical drive inserted\n"); 3946 break; 3947 case CISS_LSTATUS_MISSING_PDRIVE: 3948 printf("missing a needed physical drive\n"); 3949 break; 3950 case CISS_LSTATUS_BECOMING_READY: 3951 printf("becoming ready\n"); 3952 break; 3953 } 3954 3955 /* print failed physical drives */ 3956 for (i = 0; i < CISS_BIG_MAP_ENTRIES / 8; i++) { 3957 bus = CISS_BIG_MAP_BUS(sc, ld->cl_lstatus->drive_failure_map[i]); 3958 target = CISS_BIG_MAP_TARGET(sc, ld->cl_lstatus->drive_failure_map[i]); 3959 if (bus == -1) 3960 continue; 3961 ciss_printf(sc, "physical drive %d:%d (%x) failed\n", bus, target, 3962 ld->cl_lstatus->drive_failure_map[i]); 3963 } 3964} 3965 3966#ifdef CISS_DEBUG 3967/************************************************************************ 3968 * Print information about the controller/driver. 3969 */ 3970static void 3971ciss_print_adapter(struct ciss_softc *sc) 3972{ 3973 int i, j; 3974 3975 ciss_printf(sc, "ADAPTER:\n"); 3976 for (i = 0; i < CISSQ_COUNT; i++) { 3977 ciss_printf(sc, "%s %d/%d\n", 3978 i == 0 ? "free" : 3979 i == 1 ? "busy" : "complete", 3980 sc->ciss_qstat[i].q_length, 3981 sc->ciss_qstat[i].q_max); 3982 } 3983 ciss_printf(sc, "max_requests %d\n", sc->ciss_max_requests); 3984 ciss_printf(sc, "flags %b\n", sc->ciss_flags, 3985 "\20\1notify_ok\2control_open\3aborting\4running\21fake_synch\22bmic_abort\n"); 3986 3987 for (i = 0; i < sc->ciss_max_logical_bus; i++) { 3988 for (j = 0; j < CISS_MAX_LOGICAL; j++) { 3989 ciss_printf(sc, "LOGICAL DRIVE %d: ", i); 3990 ciss_print_ldrive(sc, &sc->ciss_logical[i][j]); 3991 } 3992 } 3993 3994 /* XXX Should physical drives be printed out here? */ 3995 3996 for (i = 1; i < sc->ciss_max_requests; i++) 3997 ciss_print_request(sc->ciss_request + i); 3998} 3999 4000/* DDB hook */ 4001static void 4002ciss_print0(void) 4003{ 4004 struct ciss_softc *sc; 4005 4006 sc = devclass_get_softc(devclass_find("ciss"), 0); 4007 if (sc == NULL) { 4008 printf("no ciss controllers\n"); 4009 } else { 4010 ciss_print_adapter(sc); 4011 } 4012} 4013#endif 4014 4015/************************************************************************ 4016 * Return a name for a logical drive status value. 4017 */ 4018static const char * 4019ciss_name_ldrive_status(int status) 4020{ 4021 switch (status) { 4022 case CISS_LSTATUS_OK: 4023 return("OK"); 4024 case CISS_LSTATUS_FAILED: 4025 return("failed"); 4026 case CISS_LSTATUS_NOT_CONFIGURED: 4027 return("not configured"); 4028 case CISS_LSTATUS_INTERIM_RECOVERY: 4029 return("interim recovery"); 4030 case CISS_LSTATUS_READY_RECOVERY: 4031 return("ready for recovery"); 4032 case CISS_LSTATUS_RECOVERING: 4033 return("recovering"); 4034 case CISS_LSTATUS_WRONG_PDRIVE: 4035 return("wrong physical drive inserted"); 4036 case CISS_LSTATUS_MISSING_PDRIVE: 4037 return("missing physical drive"); 4038 case CISS_LSTATUS_EXPANDING: 4039 return("expanding"); 4040 case CISS_LSTATUS_BECOMING_READY: 4041 return("becoming ready"); 4042 case CISS_LSTATUS_QUEUED_FOR_EXPANSION: 4043 return("queued for expansion"); 4044 } 4045 return("unknown status"); 4046} 4047 4048/************************************************************************ 4049 * Return an online/offline/nonexistent value for a logical drive 4050 * status value. 4051 */ 4052static int 4053ciss_decode_ldrive_status(int status) 4054{ 4055 switch(status) { 4056 case CISS_LSTATUS_NOT_CONFIGURED: 4057 return(CISS_LD_NONEXISTENT); 4058 4059 case CISS_LSTATUS_OK: 4060 case CISS_LSTATUS_INTERIM_RECOVERY: 4061 case CISS_LSTATUS_READY_RECOVERY: 4062 case CISS_LSTATUS_RECOVERING: 4063 case CISS_LSTATUS_EXPANDING: 4064 case CISS_LSTATUS_QUEUED_FOR_EXPANSION: 4065 return(CISS_LD_ONLINE); 4066 4067 case CISS_LSTATUS_FAILED: 4068 case CISS_LSTATUS_WRONG_PDRIVE: 4069 case CISS_LSTATUS_MISSING_PDRIVE: 4070 case CISS_LSTATUS_BECOMING_READY: 4071 default: 4072 return(CISS_LD_OFFLINE); 4073 } 4074} 4075 4076 4077/************************************************************************ 4078 * Return a name for a logical drive's organisation. 4079 */ 4080static const char * 4081ciss_name_ldrive_org(int org) 4082{ 4083 switch(org) { 4084 case CISS_LDRIVE_RAID0: 4085 return("RAID 0"); 4086 case CISS_LDRIVE_RAID1: 4087 return("RAID 1"); 4088 case CISS_LDRIVE_RAID4: 4089 return("RAID 4"); 4090 case CISS_LDRIVE_RAID5: 4091 return("RAID 5"); 4092 case CISS_LDRIVE_RAID51: 4093 return("RAID 5+1"); 4094 case CISS_LDRIVE_RAIDADG: 4095 return("RAID ADG"); 4096 } 4097 return("unkown"); 4098} 4099 4100/************************************************************************ 4101 * Return a name for a command status value. 4102 */ 4103static const char * 4104ciss_name_command_status(int status) 4105{ 4106 switch(status) { 4107 case CISS_CMD_STATUS_SUCCESS: 4108 return("success"); 4109 case CISS_CMD_STATUS_TARGET_STATUS: 4110 return("target status"); 4111 case CISS_CMD_STATUS_DATA_UNDERRUN: 4112 return("data underrun"); 4113 case CISS_CMD_STATUS_DATA_OVERRUN: 4114 return("data overrun"); 4115 case CISS_CMD_STATUS_INVALID_COMMAND: 4116 return("invalid command"); 4117 case CISS_CMD_STATUS_PROTOCOL_ERROR: 4118 return("protocol error"); 4119 case CISS_CMD_STATUS_HARDWARE_ERROR: 4120 return("hardware error"); 4121 case CISS_CMD_STATUS_CONNECTION_LOST: 4122 return("connection lost"); 4123 case CISS_CMD_STATUS_ABORTED: 4124 return("aborted"); 4125 case CISS_CMD_STATUS_ABORT_FAILED: 4126 return("abort failed"); 4127 case CISS_CMD_STATUS_UNSOLICITED_ABORT: 4128 return("unsolicited abort"); 4129 case CISS_CMD_STATUS_TIMEOUT: 4130 return("timeout"); 4131 case CISS_CMD_STATUS_UNABORTABLE: 4132 return("unabortable"); 4133 } 4134 return("unknown status"); 4135} 4136 4137/************************************************************************ 4138 * Handle an open on the control device. 4139 */ 4140static int 4141ciss_open(struct cdev *dev, int flags, int fmt, d_thread_t *p) 4142{ 4143 struct ciss_softc *sc; 4144 4145 debug_called(1); 4146 4147 sc = (struct ciss_softc *)dev->si_drv1; 4148 4149 /* we might want to veto if someone already has us open */ 4150 4151 mtx_lock(&sc->ciss_mtx); 4152 sc->ciss_flags |= CISS_FLAG_CONTROL_OPEN; 4153 mtx_unlock(&sc->ciss_mtx); 4154 return(0); 4155} 4156 4157/************************************************************************ 4158 * Handle the last close on the control device. 4159 */ 4160static int 4161ciss_close(struct cdev *dev, int flags, int fmt, d_thread_t *p) 4162{ 4163 struct ciss_softc *sc; 4164 4165 debug_called(1); 4166 4167 sc = (struct ciss_softc *)dev->si_drv1; 4168 4169 mtx_lock(&sc->ciss_mtx); 4170 sc->ciss_flags &= ~CISS_FLAG_CONTROL_OPEN; 4171 mtx_unlock(&sc->ciss_mtx); 4172 return (0); 4173} 4174 4175/******************************************************************************** 4176 * Handle adapter-specific control operations. 4177 * 4178 * Note that the API here is compatible with the Linux driver, in order to 4179 * simplify the porting of Compaq's userland tools. 4180 */ 4181static int 4182ciss_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *p) 4183{ 4184 struct ciss_softc *sc; 4185 IOCTL_Command_struct *ioc = (IOCTL_Command_struct *)addr; 4186#ifdef __amd64__ 4187 IOCTL_Command_struct32 *ioc32 = (IOCTL_Command_struct32 *)addr; 4188 IOCTL_Command_struct ioc_swab; 4189#endif 4190 int error; 4191 4192 debug_called(1); 4193 4194 sc = (struct ciss_softc *)dev->si_drv1; 4195 error = 0; 4196 mtx_lock(&sc->ciss_mtx); 4197 4198 switch(cmd) { 4199 case CCISS_GETPCIINFO: 4200 { 4201 cciss_pci_info_struct *pis = (cciss_pci_info_struct *)addr; 4202 4203 pis->bus = pci_get_bus(sc->ciss_dev); 4204 pis->dev_fn = pci_get_slot(sc->ciss_dev); 4205 pis->board_id = pci_get_devid(sc->ciss_dev); 4206 4207 break; 4208 } 4209 4210 case CCISS_GETINTINFO: 4211 { 4212 cciss_coalint_struct *cis = (cciss_coalint_struct *)addr; 4213 4214 cis->delay = sc->ciss_cfg->interrupt_coalesce_delay; 4215 cis->count = sc->ciss_cfg->interrupt_coalesce_count; 4216 4217 break; 4218 } 4219 4220 case CCISS_SETINTINFO: 4221 { 4222 cciss_coalint_struct *cis = (cciss_coalint_struct *)addr; 4223 4224 if ((cis->delay == 0) && (cis->count == 0)) { 4225 error = EINVAL; 4226 break; 4227 } 4228 4229 /* 4230 * XXX apparently this is only safe if the controller is idle, 4231 * we should suspend it before doing this. 4232 */ 4233 sc->ciss_cfg->interrupt_coalesce_delay = cis->delay; 4234 sc->ciss_cfg->interrupt_coalesce_count = cis->count; 4235 4236 if (ciss_update_config(sc)) 4237 error = EIO; 4238 4239 /* XXX resume the controller here */ 4240 break; 4241 } 4242 4243 case CCISS_GETNODENAME: 4244 bcopy(sc->ciss_cfg->server_name, (NodeName_type *)addr, 4245 sizeof(NodeName_type)); 4246 break; 4247 4248 case CCISS_SETNODENAME: 4249 bcopy((NodeName_type *)addr, sc->ciss_cfg->server_name, 4250 sizeof(NodeName_type)); 4251 if (ciss_update_config(sc)) 4252 error = EIO; 4253 break; 4254 4255 case CCISS_GETHEARTBEAT: 4256 *(Heartbeat_type *)addr = sc->ciss_cfg->heartbeat; 4257 break; 4258 4259 case CCISS_GETBUSTYPES: 4260 *(BusTypes_type *)addr = sc->ciss_cfg->bus_types; 4261 break; 4262 4263 case CCISS_GETFIRMVER: 4264 bcopy(sc->ciss_id->running_firmware_revision, (FirmwareVer_type *)addr, 4265 sizeof(FirmwareVer_type)); 4266 break; 4267 4268 case CCISS_GETDRIVERVER: 4269 *(DriverVer_type *)addr = CISS_DRIVER_VERSION; 4270 break; 4271 4272 case CCISS_REVALIDVOLS: 4273 /* 4274 * This is a bit ugly; to do it "right" we really need 4275 * to find any disks that have changed, kick CAM off them, 4276 * then rescan only these disks. It'd be nice if they 4277 * a) told us which disk(s) they were going to play with, 4278 * and b) which ones had arrived. 8( 4279 */ 4280 break; 4281 4282#ifdef __amd64__ 4283 case CCISS_PASSTHRU32: 4284 ioc_swab.LUN_info = ioc32->LUN_info; 4285 ioc_swab.Request = ioc32->Request; 4286 ioc_swab.error_info = ioc32->error_info; 4287 ioc_swab.buf_size = ioc32->buf_size; 4288 ioc_swab.buf = (u_int8_t *)(uintptr_t)ioc32->buf; 4289 ioc = &ioc_swab; 4290 /* FALLTHROUGH */ 4291#endif 4292 4293 case CCISS_PASSTHRU: 4294 error = ciss_user_command(sc, ioc); 4295 break; 4296 4297 default: 4298 debug(0, "unknown ioctl 0x%lx", cmd); 4299 4300 debug(1, "CCISS_GETPCIINFO: 0x%lx", CCISS_GETPCIINFO); 4301 debug(1, "CCISS_GETINTINFO: 0x%lx", CCISS_GETINTINFO); 4302 debug(1, "CCISS_SETINTINFO: 0x%lx", CCISS_SETINTINFO); 4303 debug(1, "CCISS_GETNODENAME: 0x%lx", CCISS_GETNODENAME); 4304 debug(1, "CCISS_SETNODENAME: 0x%lx", CCISS_SETNODENAME); 4305 debug(1, "CCISS_GETHEARTBEAT: 0x%lx", CCISS_GETHEARTBEAT); 4306 debug(1, "CCISS_GETBUSTYPES: 0x%lx", CCISS_GETBUSTYPES); 4307 debug(1, "CCISS_GETFIRMVER: 0x%lx", CCISS_GETFIRMVER); 4308 debug(1, "CCISS_GETDRIVERVER: 0x%lx", CCISS_GETDRIVERVER); 4309 debug(1, "CCISS_REVALIDVOLS: 0x%lx", CCISS_REVALIDVOLS); 4310 debug(1, "CCISS_PASSTHRU: 0x%lx", CCISS_PASSTHRU); 4311 4312 error = ENOIOCTL; 4313 break; 4314 } 4315 4316 mtx_unlock(&sc->ciss_mtx); 4317 return(error); 4318} 4319