10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51984Scg149915 * Common Development and Distribution License (the "License"). 61984Scg149915 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 225789Ssl147100 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate 270Sstevel@tonic-gate /* 280Sstevel@tonic-gate * scsa2usb bridge nexus driver: 290Sstevel@tonic-gate * 300Sstevel@tonic-gate * This driver supports the following wire transports: 310Sstevel@tonic-gate * a. Bulk Only transport (see usb_ms_bulkonly.c) 320Sstevel@tonic-gate * b. CB transport (see usb_ms_cbi.c) 330Sstevel@tonic-gate * c. CBI transport with interrupt status completion (see usb_ms_cbi.c) 340Sstevel@tonic-gate * 350Sstevel@tonic-gate * It handles the following command sets: 360Sstevel@tonic-gate * a. SCSI 370Sstevel@tonic-gate * b. ATAPI command set (subset of SCSI command set) 380Sstevel@tonic-gate * c. UFI command set ( 390Sstevel@tonic-gate * http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf) 400Sstevel@tonic-gate * 410Sstevel@tonic-gate * For details on USB Mass Storage Class overview: 420Sstevel@tonic-gate * http://www.usb.org/developers/devclass_docs/usbmassover_11.pdf 430Sstevel@tonic-gate */ 440Sstevel@tonic-gate #if defined(lint) && !defined(DEBUG) 450Sstevel@tonic-gate #define DEBUG 1 460Sstevel@tonic-gate #endif 470Sstevel@tonic-gate 480Sstevel@tonic-gate #include <sys/usb/usba/usbai_version.h> 490Sstevel@tonic-gate #include <sys/scsi/scsi.h> 500Sstevel@tonic-gate #include <sys/cdio.h> 510Sstevel@tonic-gate #include <sys/sunndi.h> 520Sstevel@tonic-gate #include <sys/esunddi.h> 530Sstevel@tonic-gate #include <sys/callb.h> 540Sstevel@tonic-gate #include <sys/kobj.h> 550Sstevel@tonic-gate #include <sys/kobj_lex.h> 560Sstevel@tonic-gate #include <sys/strsubr.h> 57*7492SZhigang.Lu@Sun.COM #include <sys/strsun.h> 580Sstevel@tonic-gate #include <sys/sysmacros.h> 590Sstevel@tonic-gate 600Sstevel@tonic-gate #include <sys/usb/usba.h> 610Sstevel@tonic-gate #include <sys/usb/usba/usba_ugen.h> 620Sstevel@tonic-gate 630Sstevel@tonic-gate #include <sys/usb/usba/usba_private.h> 640Sstevel@tonic-gate #include <sys/usb/clients/mass_storage/usb_bulkonly.h> 650Sstevel@tonic-gate #include <sys/usb/scsa2usb/scsa2usb.h> 660Sstevel@tonic-gate 670Sstevel@tonic-gate /* 680Sstevel@tonic-gate * Function Prototypes 690Sstevel@tonic-gate */ 700Sstevel@tonic-gate static int scsa2usb_attach(dev_info_t *, ddi_attach_cmd_t); 710Sstevel@tonic-gate static int scsa2usb_info(dev_info_t *, ddi_info_cmd_t, void *, 720Sstevel@tonic-gate void **); 730Sstevel@tonic-gate static int scsa2usb_detach(dev_info_t *, ddi_detach_cmd_t); 740Sstevel@tonic-gate static int scsa2usb_cleanup(dev_info_t *, scsa2usb_state_t *); 750Sstevel@tonic-gate static void scsa2usb_validate_attrs(scsa2usb_state_t *); 760Sstevel@tonic-gate static void scsa2usb_create_luns(scsa2usb_state_t *); 770Sstevel@tonic-gate static int scsa2usb_is_usb(dev_info_t *); 780Sstevel@tonic-gate static int scsa2usb_fake_inquiry(scsa2usb_state_t *, 790Sstevel@tonic-gate scsa2usb_cmd_t *, uint_t); 800Sstevel@tonic-gate static void scsa2usb_do_inquiry(scsa2usb_state_t *, 810Sstevel@tonic-gate uint_t, uint_t); 822506Ssl147100 static int scsa2usb_do_tur(scsa2usb_state_t *, struct scsi_address *); 830Sstevel@tonic-gate 840Sstevel@tonic-gate /* override property handling */ 850Sstevel@tonic-gate static void scsa2usb_override(scsa2usb_state_t *); 860Sstevel@tonic-gate static int scsa2usb_parse_input_str(char *, scsa2usb_ov_t *, 870Sstevel@tonic-gate scsa2usb_state_t *); 880Sstevel@tonic-gate static void scsa2usb_override_error(char *, scsa2usb_state_t *); 890Sstevel@tonic-gate static char *scsa2usb_strtok_r(char *, char *, char **); 900Sstevel@tonic-gate 910Sstevel@tonic-gate 920Sstevel@tonic-gate /* PANIC callback handling */ 930Sstevel@tonic-gate static void scsa2usb_panic_callb_init(scsa2usb_state_t *); 940Sstevel@tonic-gate static void scsa2usb_panic_callb_fini(scsa2usb_state_t *); 950Sstevel@tonic-gate static boolean_t scsa2usb_panic_callb(void *, int); 960Sstevel@tonic-gate 970Sstevel@tonic-gate /* SCSA support */ 980Sstevel@tonic-gate static int scsa2usb_scsi_tgt_probe(struct scsi_device *, int (*)(void)); 990Sstevel@tonic-gate static int scsa2usb_scsi_tgt_init(dev_info_t *, dev_info_t *, 1000Sstevel@tonic-gate scsi_hba_tran_t *, struct scsi_device *); 1010Sstevel@tonic-gate static void scsa2usb_scsi_tgt_free(dev_info_t *, dev_info_t *, 1020Sstevel@tonic-gate scsi_hba_tran_t *, struct scsi_device *); 1030Sstevel@tonic-gate static struct scsi_pkt *scsa2usb_scsi_init_pkt(struct scsi_address *, 1040Sstevel@tonic-gate struct scsi_pkt *, struct buf *, int, int, 1050Sstevel@tonic-gate int, int, int (*)(), caddr_t); 1060Sstevel@tonic-gate static void scsa2usb_scsi_destroy_pkt(struct scsi_address *, 1070Sstevel@tonic-gate struct scsi_pkt *); 1080Sstevel@tonic-gate static int scsa2usb_scsi_start(struct scsi_address *, struct scsi_pkt *); 1090Sstevel@tonic-gate static int scsa2usb_scsi_abort(struct scsi_address *, struct scsi_pkt *); 1100Sstevel@tonic-gate static int scsa2usb_scsi_reset(struct scsi_address *, int); 1110Sstevel@tonic-gate static int scsa2usb_scsi_getcap(struct scsi_address *, char *, int); 1120Sstevel@tonic-gate static int scsa2usb_scsi_setcap(struct scsi_address *, char *, int, int); 1130Sstevel@tonic-gate static int scsa2usb_scsi_bus_config(dev_info_t *, uint_t, 1140Sstevel@tonic-gate ddi_bus_config_op_t, void *, dev_info_t **); 1150Sstevel@tonic-gate static int scsa2usb_scsi_bus_unconfig(dev_info_t *, uint_t, 1160Sstevel@tonic-gate ddi_bus_config_op_t, void *); 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate /* functions for command and transport support */ 1190Sstevel@tonic-gate static void scsa2usb_prepare_pkt(scsa2usb_state_t *, struct scsi_pkt *); 1200Sstevel@tonic-gate static int scsa2usb_cmd_transport(scsa2usb_state_t *, scsa2usb_cmd_t *); 1210Sstevel@tonic-gate static int scsa2usb_check_bulkonly_blacklist_attrs(scsa2usb_state_t *, 1220Sstevel@tonic-gate scsa2usb_cmd_t *, uchar_t); 1230Sstevel@tonic-gate static int scsa2usb_check_ufi_blacklist_attrs(scsa2usb_state_t *, uchar_t, 1240Sstevel@tonic-gate scsa2usb_cmd_t *); 1250Sstevel@tonic-gate static int scsa2usb_handle_scsi_cmd_sub_class(scsa2usb_state_t *, 1260Sstevel@tonic-gate scsa2usb_cmd_t *, struct scsi_pkt *); 1270Sstevel@tonic-gate static int scsa2usb_handle_ufi_subclass_cmd(scsa2usb_state_t *, 1280Sstevel@tonic-gate scsa2usb_cmd_t *, struct scsi_pkt *); 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate /* waitQ handling */ 1310Sstevel@tonic-gate static void scsa2usb_work_thread(void *); 1320Sstevel@tonic-gate static void scsa2usb_transport_request(scsa2usb_state_t *, uint_t); 1330Sstevel@tonic-gate static void scsa2usb_flush_waitQ(scsa2usb_state_t *, uint_t, uchar_t); 1340Sstevel@tonic-gate static int scsa2usb_all_waitQs_empty(scsa2usb_state_t *); 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate /* auto request sense handling */ 1370Sstevel@tonic-gate static int scsa2usb_create_arq_pkt(scsa2usb_state_t *, 1380Sstevel@tonic-gate struct scsi_address *); 1390Sstevel@tonic-gate static void scsa2usb_delete_arq_pkt(scsa2usb_state_t *); 1400Sstevel@tonic-gate static void scsa2usb_complete_arq_pkt(scsa2usb_state_t *, struct scsi_pkt *, 1410Sstevel@tonic-gate scsa2usb_cmd_t *, struct buf *); 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate /* utility functions for any transport */ 1440Sstevel@tonic-gate static int scsa2usb_open_usb_pipes(scsa2usb_state_t *); 1450Sstevel@tonic-gate void scsa2usb_close_usb_pipes(scsa2usb_state_t *); 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate static void scsa2usb_fill_up_cdb_len(scsa2usb_cmd_t *, int); 1480Sstevel@tonic-gate static void scsa2usb_fill_up_cdb_lba(scsa2usb_cmd_t *, int); 1490Sstevel@tonic-gate static void scsa2usb_fill_up_ReadCD_cdb_len(scsa2usb_cmd_t *, int, int); 1500Sstevel@tonic-gate static void scsa2usb_fill_up_12byte_cdb_len(scsa2usb_cmd_t *, int, int); 1510Sstevel@tonic-gate static int scsa2usb_read_cd_blk_size(uchar_t); 1520Sstevel@tonic-gate int scsa2usb_rw_transport(scsa2usb_state_t *, struct scsi_pkt *); 1530Sstevel@tonic-gate void scsa2usb_setup_next_xfer(scsa2usb_state_t *, scsa2usb_cmd_t *); 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate static mblk_t *scsa2usb_bp_to_mblk(scsa2usb_state_t *); 1560Sstevel@tonic-gate int scsa2usb_handle_data_start(scsa2usb_state_t *, 1570Sstevel@tonic-gate scsa2usb_cmd_t *, usb_bulk_req_t *); 1580Sstevel@tonic-gate void scsa2usb_handle_data_done(scsa2usb_state_t *, 1590Sstevel@tonic-gate scsa2usb_cmd_t *cmd, usb_bulk_req_t *); 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate usb_bulk_req_t *scsa2usb_init_bulk_req(scsa2usb_state_t *, 1620Sstevel@tonic-gate size_t, uint_t, usb_req_attrs_t, usb_flags_t); 1630Sstevel@tonic-gate int scsa2usb_bulk_timeout(int); 1640Sstevel@tonic-gate int scsa2usb_clear_ept_stall(scsa2usb_state_t *, uint_t, 1650Sstevel@tonic-gate usb_pipe_handle_t, char *); 1660Sstevel@tonic-gate static void scsa2usb_pkt_completion(scsa2usb_state_t *, struct scsi_pkt *); 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate /* event handling */ 1690Sstevel@tonic-gate static int scsa2usb_reconnect_event_cb(dev_info_t *); 1700Sstevel@tonic-gate static int scsa2usb_disconnect_event_cb(dev_info_t *); 1710Sstevel@tonic-gate static int scsa2usb_cpr_suspend(dev_info_t *); 1720Sstevel@tonic-gate static void scsa2usb_cpr_resume(dev_info_t *); 1730Sstevel@tonic-gate static void scsa2usb_restore_device_state(dev_info_t *, scsa2usb_state_t *); 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate /* PM handling */ 1760Sstevel@tonic-gate static void scsa2usb_create_pm_components(dev_info_t *, scsa2usb_state_t *); 1770Sstevel@tonic-gate static void scsa2usb_raise_power(scsa2usb_state_t *); 1780Sstevel@tonic-gate static int scsa2usb_pwrlvl0(scsa2usb_state_t *); 1790Sstevel@tonic-gate static int scsa2usb_pwrlvl1(scsa2usb_state_t *); 1800Sstevel@tonic-gate static int scsa2usb_pwrlvl2(scsa2usb_state_t *); 1810Sstevel@tonic-gate static int scsa2usb_pwrlvl3(scsa2usb_state_t *); 1820Sstevel@tonic-gate static int scsa2usb_power(dev_info_t *, int comp, int level); 1830Sstevel@tonic-gate static void scsa2usb_pm_busy_component(scsa2usb_state_t *); 1840Sstevel@tonic-gate static void scsa2usb_pm_idle_component(scsa2usb_state_t *); 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* external functions for Bulk only (BO) support */ 1870Sstevel@tonic-gate extern int scsa2usb_bulk_only_transport(scsa2usb_state_t *, 1880Sstevel@tonic-gate scsa2usb_cmd_t *); 1890Sstevel@tonic-gate extern int scsa2usb_bulk_only_get_max_lun(scsa2usb_state_t *); 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate /* external functions for CB/CBI support */ 1920Sstevel@tonic-gate extern int scsa2usb_cbi_transport(scsa2usb_state_t *, scsa2usb_cmd_t *); 1930Sstevel@tonic-gate extern void scsa2usb_cbi_stop_intr_polling(scsa2usb_state_t *); 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate /* cmd decoding */ 1970Sstevel@tonic-gate static char *scsa2usb_cmds[] = { 1980Sstevel@tonic-gate "\000tur", 1990Sstevel@tonic-gate "\001rezero", 2000Sstevel@tonic-gate "\003rqsense", 2010Sstevel@tonic-gate "\004format", 2020Sstevel@tonic-gate "\014cartprot", 2030Sstevel@tonic-gate "\022inquiry", 2040Sstevel@tonic-gate "\026tranlba", 2050Sstevel@tonic-gate "\030fmtverify", 2060Sstevel@tonic-gate "\032modesense", 2070Sstevel@tonic-gate "\033start", 2080Sstevel@tonic-gate "\035snddiag", 2090Sstevel@tonic-gate "\036doorlock", 2100Sstevel@tonic-gate "\043formatcap", 2110Sstevel@tonic-gate "\045readcap", 2120Sstevel@tonic-gate "\050read10", 2130Sstevel@tonic-gate "\052write10", 2140Sstevel@tonic-gate "\053seek10", 2150Sstevel@tonic-gate "\056writeverify", 2160Sstevel@tonic-gate "\057verify", 2170Sstevel@tonic-gate "\065synchcache", 2180Sstevel@tonic-gate "\076readlong", 2190Sstevel@tonic-gate "\077writelong", 2200Sstevel@tonic-gate "\102readsubchan", 2210Sstevel@tonic-gate "\103readtoc", 2220Sstevel@tonic-gate "\104readhdr", 2230Sstevel@tonic-gate "\105playaudio10", 2240Sstevel@tonic-gate "\107playaudio_msf", 2250Sstevel@tonic-gate "\110playaudio_ti", 2260Sstevel@tonic-gate "\111playtrk_r10", 2270Sstevel@tonic-gate "\112geteventnotify", 2280Sstevel@tonic-gate "\113pause_resume", 2290Sstevel@tonic-gate "\116stop/play_scan", 2300Sstevel@tonic-gate "\121readdiscinfo", 2310Sstevel@tonic-gate "\122readtrkinfo", 2320Sstevel@tonic-gate "\123reservedtrk", 2330Sstevel@tonic-gate "\124sendopcinfo", 2340Sstevel@tonic-gate "\125modeselect", 2350Sstevel@tonic-gate "\132modesense", 2360Sstevel@tonic-gate "\133closetrksession", 2370Sstevel@tonic-gate "\135sendcuesheet", 2380Sstevel@tonic-gate "\136prin", 2390Sstevel@tonic-gate "\137prout", 2400Sstevel@tonic-gate "\241blankcd", 2410Sstevel@tonic-gate "\245playaudio12", 2420Sstevel@tonic-gate "\250read12", 2430Sstevel@tonic-gate "\251playtrk12", 2440Sstevel@tonic-gate "\252write12", 2450Sstevel@tonic-gate "\254getperf", 2460Sstevel@tonic-gate "\271readcdmsf", 2470Sstevel@tonic-gate "\273setcdspeed", 2480Sstevel@tonic-gate "\275mechanism_sts", 2490Sstevel@tonic-gate "\276readcd", 2500Sstevel@tonic-gate NULL 2510Sstevel@tonic-gate }; 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate /* 2550Sstevel@tonic-gate * Mass-Storage devices masquerade as "sd" disks. 2560Sstevel@tonic-gate * 2570Sstevel@tonic-gate * These devices may not support all SCSI CDBs in their 2580Sstevel@tonic-gate * entirety due to their hardware implementation limitations. 2590Sstevel@tonic-gate * 2600Sstevel@tonic-gate * As such, following is a list of some of the black-listed 2610Sstevel@tonic-gate * devices w/ the attributes that they do not support. 2620Sstevel@tonic-gate * (See scsa2usb.h for description on each attribute) 2630Sstevel@tonic-gate */ 2640Sstevel@tonic-gate #define X ((uint16_t)(-1)) 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate static struct blacklist { 2670Sstevel@tonic-gate uint16_t idVendor; /* vendor ID */ 2680Sstevel@tonic-gate uint16_t idProduct; /* product ID */ 2690Sstevel@tonic-gate uint16_t bcdDevice; /* device release number in bcd */ 2700Sstevel@tonic-gate uint16_t attributes; /* attributes to blacklist */ 2710Sstevel@tonic-gate } scsa2usb_blacklist[] = { 2720Sstevel@tonic-gate /* Iomega Zip100 drive (prototype) with flaky bridge */ 2730Sstevel@tonic-gate {MS_IOMEGA_VID, MS_IOMEGA_PID1_ZIP100, 0, 2740Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM}, 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate /* Iomega Zip100 drive (newer model) with flaky bridge */ 2770Sstevel@tonic-gate {MS_IOMEGA_VID, MS_IOMEGA_PID2_ZIP100, 0, 2780Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM}, 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate /* Iomega Zip100 drive (newer model) with flaky bridge */ 2810Sstevel@tonic-gate {MS_IOMEGA_VID, MS_IOMEGA_PID3_ZIP100, 0, 2820Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM}, 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate /* Iomega Zip250 drive */ 2850Sstevel@tonic-gate {MS_IOMEGA_VID, MS_IOMEGA_PID_ZIP250, 0, SCSA2USB_ATTRS_GET_LUN}, 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate /* Iomega Clik! drive */ 2880Sstevel@tonic-gate {MS_IOMEGA_VID, MS_IOMEGA_PID_CLIK, 0, 2890Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate /* SMSC floppy Device - and its clones */ 2920Sstevel@tonic-gate {MS_SMSC_VID, X, 0, SCSA2USB_ATTRS_START_STOP}, 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate /* Hagiwara SmartMedia Device */ 2950Sstevel@tonic-gate {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID1, 0, 2960Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate /* Hagiwara CompactFlash Device */ 2990Sstevel@tonic-gate {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID2, 0, 3000Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate /* Hagiwara SmartMedia/CompactFlash Combo Device */ 3030Sstevel@tonic-gate {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID3, 0, 3040Sstevel@tonic-gate SCSA2USB_ATTRS_START_STOP}, 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate /* Hagiwara new SM Device */ 3070Sstevel@tonic-gate {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID4, 0, 3080Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate /* Hagiwara new CF Device */ 3110Sstevel@tonic-gate {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID5, 0, 3120Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate /* Mitsumi CD-RW Device(s) */ 3150Sstevel@tonic-gate {MS_MITSUMI_VID, X, X, SCSA2USB_ATTRS_BIG_TIMEOUT | 3160Sstevel@tonic-gate SCSA2USB_ATTRS_GET_CONF | SCSA2USB_ATTRS_GET_PERF}, 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate /* Neodio Technologies Corporation SM/CF/MS/SD Combo Device */ 3190Sstevel@tonic-gate {MS_NEODIO_VID, MS_NEODIO_DEVICE_3050, 0, 3200Sstevel@tonic-gate SCSA2USB_ATTRS_MODE_SENSE }, 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate /* dumb flash devices */ 3230Sstevel@tonic-gate {MS_SONY_FLASH_VID, MS_SONY_FLASH_PID, 0, 3240Sstevel@tonic-gate SCSA2USB_ATTRS_REDUCED_CMD}, 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate {MS_TREK_FLASH_VID, MS_TREK_FLASH_PID, 0, 3270Sstevel@tonic-gate SCSA2USB_ATTRS_REDUCED_CMD}, 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate {MS_PENN_FLASH_VID, MS_PENN_FLASH_PID, 0, 3300Sstevel@tonic-gate SCSA2USB_ATTRS_REDUCED_CMD}, 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate /* SimpleTech UCF-100 CF Device */ 3330Sstevel@tonic-gate {MS_SIMPLETECH_VID, MS_SIMPLETECH_PID1, 0, 3340Sstevel@tonic-gate SCSA2USB_ATTRS_REDUCED_CMD}, 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate {MS_ADDONICS_CARD_READER_VID, MS_ADDONICS_CARD_READER_PID, 3370Sstevel@tonic-gate 0, SCSA2USB_ATTRS_REDUCED_CMD}, 3381101Ssl147100 3391101Ssl147100 /* Acomdata 80GB USB/1394 Hard Disk */ 3401101Ssl147100 {MS_ACOMDATA_VID, MS_ACOMDATA_PID1, 0, 3411101Ssl147100 SCSA2USB_ATTRS_USE_CSW_RESIDUE}, 3421101Ssl147100 3431101Ssl147100 /* OTi6828 Flash Disk */ 3441101Ssl147100 {MS_OTI_VID, MS_OTI_DEVICE_6828, 0, 3451101Ssl147100 SCSA2USB_ATTRS_USE_CSW_RESIDUE}, 3462506Ssl147100 3472506Ssl147100 /* AMI Virtual Floppy */ 3482506Ssl147100 {MS_AMI_VID, MS_AMI_VIRTUAL_FLOPPY, 0, 3492506Ssl147100 SCSA2USB_ATTRS_NO_MEDIA_CHECK}, 3504834Sfb209375 3514834Sfb209375 /* ScanLogic USB Storage Device */ 3524834Sfb209375 {MS_SCANLOGIC_VID, MS_SCANLOGIC_PID1, 0, 3535789Ssl147100 SCSA2USB_ATTRS_NO_CAP_ADJUST}, 3545789Ssl147100 3555789Ssl147100 /* Super Top USB 2.0 IDE Device */ 3565789Ssl147100 {MS_SUPERTOP_VID, MS_SUPERTOP_DEVICE_6600, 0, 3577231Slg150142 SCSA2USB_ATTRS_USE_CSW_RESIDUE}, 3587231Slg150142 3597231Slg150142 /* Aigo Miniking Device NEHFSP14 */ 3607231Slg150142 {MS_AIGO_VID, MS_AIGO_DEVICE_6981, 0, 3615789Ssl147100 SCSA2USB_ATTRS_USE_CSW_RESIDUE} 3620Sstevel@tonic-gate }; 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate #define N_SCSA2USB_BLACKLIST (sizeof (scsa2usb_blacklist))/ \ 3660Sstevel@tonic-gate sizeof (struct blacklist) 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate /* 3690Sstevel@tonic-gate * Attribute values can be overridden by values 3700Sstevel@tonic-gate * contained in the scsa2usb.conf file. 3710Sstevel@tonic-gate * These arrays define possible user input values. 3720Sstevel@tonic-gate */ 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate struct scsa2usb_subclass_protocol_override { 3750Sstevel@tonic-gate char *name; 3760Sstevel@tonic-gate int value; 3770Sstevel@tonic-gate }; 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate static struct scsa2usb_subclass_protocol_override scsa2usb_protocol[] = { 3800Sstevel@tonic-gate {"CB", SCSA2USB_CB_PROTOCOL}, 3810Sstevel@tonic-gate {"CBI", SCSA2USB_CBI_PROTOCOL}, 3820Sstevel@tonic-gate {"BO", SCSA2USB_BULK_ONLY_PROTOCOL} 3830Sstevel@tonic-gate }; 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate static struct scsa2usb_subclass_protocol_override scsa2usb_subclass[] = { 3860Sstevel@tonic-gate {"SCSI", SCSA2USB_SCSI_CMDSET}, 3870Sstevel@tonic-gate {"ATAPI", SCSA2USB_ATAPI_CMDSET}, 3880Sstevel@tonic-gate {"UFI", SCSA2USB_UFI_CMDSET} 3890Sstevel@tonic-gate }; 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate #define N_SCSA2USB_SUBC_OVERRIDE (sizeof (scsa2usb_subclass))/ \ 3930Sstevel@tonic-gate sizeof (struct scsa2usb_subclass_protocol_override) 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate #define N_SCSA2USB_PROT_OVERRIDE (sizeof (scsa2usb_protocol))/ \ 3960Sstevel@tonic-gate sizeof (struct scsa2usb_subclass_protocol_override) 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate /* global variables */ 3990Sstevel@tonic-gate static void *scsa2usb_statep; /* for soft state */ 4000Sstevel@tonic-gate static boolean_t scsa2usb_sync_message = B_TRUE; /* for syncing */ 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate /* for debug messages */ 403880Sfrits uint_t scsa2usb_errmask = (uint_t)DPRINT_MASK_ALL; 404880Sfrits uint_t scsa2usb_errlevel = USB_LOG_L4; 405880Sfrits uint_t scsa2usb_instance_debug = (uint_t)-1; 406880Sfrits uint_t scsa2usb_scsi_bus_config_debug = 0; 407880Sfrits uint_t scsa2usb_long_timeout = 50 * SCSA2USB_BULK_PIPE_TIMEOUT; 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate /* 4110Sstevel@tonic-gate * Some devices have problems with big bulk transfers, 4120Sstevel@tonic-gate * transfers >= 128kbytes hang the device. This tunable allows to 4130Sstevel@tonic-gate * limit the maximum bulk transfers rate. 4140Sstevel@tonic-gate */ 415880Sfrits uint_t scsa2usb_max_bulk_xfer_size = SCSA2USB_MAX_BULK_XFER_SIZE; 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 4190Sstevel@tonic-gate /* 4200Sstevel@tonic-gate * Test BO 13 cases. (See USB Mass Storage Class - Bulk Only Transport). 4210Sstevel@tonic-gate * We are not covering test cases 1, 6, and 12 as these are the "good" 4220Sstevel@tonic-gate * test cases and are tested as part of the normal drive access operations. 4230Sstevel@tonic-gate * 4240Sstevel@tonic-gate * NOTE: This is for testing only. It will be replaced by a uscsi test. 4250Sstevel@tonic-gate * Some are listed here while; other test cases are moved to usb_bulkonly.c 4260Sstevel@tonic-gate */ 4270Sstevel@tonic-gate static int scsa2usb_test_case_5 = 0; 4280Sstevel@tonic-gate int scsa2usb_test_case_8 = 0; 4290Sstevel@tonic-gate int scsa2usb_test_case_10 = 0; 4300Sstevel@tonic-gate static int scsa2usb_test_case_11 = 0; 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate static void scsa2usb_test_mblk(scsa2usb_state_t *, boolean_t); 4330Sstevel@tonic-gate #endif /* SCSA2USB_BULK_ONLY_TEST */ 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate static int scsa2usb_ugen_open(dev_t *, int, int, cred_t *); 4360Sstevel@tonic-gate static int scsa2usb_ugen_close(dev_t, int, int, cred_t *); 4370Sstevel@tonic-gate static int scsa2usb_ugen_read(dev_t, struct uio *, cred_t *); 4380Sstevel@tonic-gate static int scsa2usb_ugen_write(dev_t, struct uio *, cred_t *); 4390Sstevel@tonic-gate static int scsa2usb_ugen_poll(dev_t, short, int, short *, 4400Sstevel@tonic-gate struct pollhead **); 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate /* scsa2usb cb_ops */ 4430Sstevel@tonic-gate static struct cb_ops scsa2usb_cbops = { 4440Sstevel@tonic-gate scsa2usb_ugen_open, /* open */ 4450Sstevel@tonic-gate scsa2usb_ugen_close, /* close */ 4460Sstevel@tonic-gate nodev, /* strategy */ 4470Sstevel@tonic-gate nodev, /* print */ 4480Sstevel@tonic-gate nodev, /* dump */ 4490Sstevel@tonic-gate scsa2usb_ugen_read, /* read */ 4500Sstevel@tonic-gate scsa2usb_ugen_write, /* write */ 4516910Svb160487 nodev, /* ioctl */ 4520Sstevel@tonic-gate nodev, /* devmap */ 4530Sstevel@tonic-gate nodev, /* mmap */ 4540Sstevel@tonic-gate nodev, /* segmap */ 4550Sstevel@tonic-gate scsa2usb_ugen_poll, /* poll */ 4560Sstevel@tonic-gate ddi_prop_op, /* prop_op */ 4570Sstevel@tonic-gate NULL, /* stream */ 4580Sstevel@tonic-gate D_MP, /* cb_flag */ 4590Sstevel@tonic-gate CB_REV, /* rev */ 4600Sstevel@tonic-gate nodev, /* int (*cb_aread)() */ 4610Sstevel@tonic-gate nodev /* int (*cb_awrite)() */ 4620Sstevel@tonic-gate }; 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate /* modloading support */ 4650Sstevel@tonic-gate static struct dev_ops scsa2usb_ops = { 4660Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 4670Sstevel@tonic-gate 0, /* refcnt */ 4680Sstevel@tonic-gate scsa2usb_info, /* info */ 4690Sstevel@tonic-gate nulldev, /* identify */ 4700Sstevel@tonic-gate nulldev, /* probe */ 4710Sstevel@tonic-gate scsa2usb_attach, /* attach */ 4720Sstevel@tonic-gate scsa2usb_detach, /* detach */ 4730Sstevel@tonic-gate nodev, /* reset */ 4740Sstevel@tonic-gate &scsa2usb_cbops, /* driver operations */ 4750Sstevel@tonic-gate NULL, /* bus operations */ 4760Sstevel@tonic-gate scsa2usb_power /* power */ 4770Sstevel@tonic-gate }; 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate static struct modldrv modldrv = { 4800Sstevel@tonic-gate &mod_driverops, /* Module type. This one is a driver */ 4817015Sbc224572 "SCSA to USB Driver", /* Name of the module. */ 4820Sstevel@tonic-gate &scsa2usb_ops, /* driver ops */ 4830Sstevel@tonic-gate }; 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate static struct modlinkage modlinkage = { 4860Sstevel@tonic-gate MODREV_1, (void *)&modldrv, NULL 4870Sstevel@tonic-gate }; 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate /* event support */ 4900Sstevel@tonic-gate static usb_event_t scsa2usb_events = { 4910Sstevel@tonic-gate scsa2usb_disconnect_event_cb, 4920Sstevel@tonic-gate scsa2usb_reconnect_event_cb, 4930Sstevel@tonic-gate NULL, NULL 4940Sstevel@tonic-gate }; 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate int 4970Sstevel@tonic-gate _init(void) 4980Sstevel@tonic-gate { 4990Sstevel@tonic-gate int rval; 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate if (((rval = ddi_soft_state_init(&scsa2usb_statep, 5020Sstevel@tonic-gate sizeof (scsa2usb_state_t), SCSA2USB_INITIAL_ALLOC)) != 0)) { 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate return (rval); 5050Sstevel@tonic-gate } 5060Sstevel@tonic-gate 5070Sstevel@tonic-gate if ((rval = scsi_hba_init(&modlinkage)) != 0) { 5080Sstevel@tonic-gate ddi_soft_state_fini(&scsa2usb_statep); 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate return (rval); 5110Sstevel@tonic-gate } 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate if ((rval = mod_install(&modlinkage)) != 0) { 5140Sstevel@tonic-gate scsi_hba_fini(&modlinkage); 5150Sstevel@tonic-gate ddi_soft_state_fini(&scsa2usb_statep); 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate return (rval); 5180Sstevel@tonic-gate } 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate return (rval); 5210Sstevel@tonic-gate } 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate int 5250Sstevel@tonic-gate _fini(void) 5260Sstevel@tonic-gate { 5270Sstevel@tonic-gate int rval; 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate if ((rval = mod_remove(&modlinkage)) == 0) { 5300Sstevel@tonic-gate scsi_hba_fini(&modlinkage); 5310Sstevel@tonic-gate ddi_soft_state_fini(&scsa2usb_statep); 5320Sstevel@tonic-gate } 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate return (rval); 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate int 5390Sstevel@tonic-gate _info(struct modinfo *modinfop) 5400Sstevel@tonic-gate { 5410Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 5420Sstevel@tonic-gate } 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate /* 5460Sstevel@tonic-gate * scsa2usb_info : 5470Sstevel@tonic-gate * Get minor number, soft state structure etc. 5480Sstevel@tonic-gate */ 5490Sstevel@tonic-gate /*ARGSUSED*/ 5500Sstevel@tonic-gate static int 5510Sstevel@tonic-gate scsa2usb_info(dev_info_t *dip, ddi_info_cmd_t infocmd, 5520Sstevel@tonic-gate void *arg, void **result) 5530Sstevel@tonic-gate { 5540Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = NULL; 5550Sstevel@tonic-gate int error = DDI_FAILURE; 5560Sstevel@tonic-gate int instance = SCSA2USB_MINOR_TO_INSTANCE(getminor((dev_t)arg)); 5570Sstevel@tonic-gate 5580Sstevel@tonic-gate switch (infocmd) { 5590Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 5600Sstevel@tonic-gate if (((scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 5610Sstevel@tonic-gate instance)) != NULL) && 5620Sstevel@tonic-gate scsa2usbp->scsa2usb_dip) { 5630Sstevel@tonic-gate *result = scsa2usbp->scsa2usb_dip; 5640Sstevel@tonic-gate error = DDI_SUCCESS; 5650Sstevel@tonic-gate } else { 5660Sstevel@tonic-gate *result = NULL; 5670Sstevel@tonic-gate } 5680Sstevel@tonic-gate break; 5690Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 5700Sstevel@tonic-gate *result = (void *)(uintptr_t)instance; 5710Sstevel@tonic-gate error = DDI_SUCCESS; 5720Sstevel@tonic-gate break; 5730Sstevel@tonic-gate default: 5740Sstevel@tonic-gate break; 5750Sstevel@tonic-gate } 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate return (error); 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate /* 5820Sstevel@tonic-gate * scsa2usb_attach: 5830Sstevel@tonic-gate * Attach driver 5840Sstevel@tonic-gate * Allocate a "scsi_hba_tran" - call scsi_hba_tran_alloc() 5850Sstevel@tonic-gate * Invoke scsi_hba_attach_setup 5860Sstevel@tonic-gate * Get the serialno of the device 5870Sstevel@tonic-gate * Open bulk pipes 5880Sstevel@tonic-gate * Create disk child(ren) 5890Sstevel@tonic-gate * Register events 5900Sstevel@tonic-gate * Create and register panic callback 5910Sstevel@tonic-gate * 5920Sstevel@tonic-gate * NOTE: Replaced CBW_DIR_OUT with USB_EP_DIR_OUT and CBW_DIR_IN with 5930Sstevel@tonic-gate * USB_EP_DIR_IN as they are the same #defines. 5940Sstevel@tonic-gate */ 5950Sstevel@tonic-gate static int 5960Sstevel@tonic-gate scsa2usb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 5970Sstevel@tonic-gate { 5980Sstevel@tonic-gate int instance = ddi_get_instance(dip); 5990Sstevel@tonic-gate int interface; 6000Sstevel@tonic-gate uint_t lun; 6010Sstevel@tonic-gate boolean_t ept_check = B_TRUE; 6020Sstevel@tonic-gate scsi_hba_tran_t *tran; /* scsi transport */ 6030Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 6040Sstevel@tonic-gate usb_log_handle_t log_handle; 6050Sstevel@tonic-gate usb_ep_data_t *ep_data; 6060Sstevel@tonic-gate usb_client_dev_data_t *dev_data; 6070Sstevel@tonic-gate usb_alt_if_data_t *altif_data; 6080Sstevel@tonic-gate usb_ugen_info_t usb_ugen_info; 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, NULL, 6116898Sfb209375 "scsa2usb_attach: dip = 0x%p", (void *)dip); 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate switch (cmd) { 6140Sstevel@tonic-gate case DDI_ATTACH: 6150Sstevel@tonic-gate break; 6160Sstevel@tonic-gate case DDI_RESUME: 6170Sstevel@tonic-gate scsa2usb_cpr_resume(dip); 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate return (DDI_SUCCESS); 6200Sstevel@tonic-gate default: 6210Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, NULL, 6220Sstevel@tonic-gate "scsa2usb_attach: failed"); 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate return (DDI_FAILURE); 6250Sstevel@tonic-gate } 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate /* Allocate softc information */ 6280Sstevel@tonic-gate if (ddi_soft_state_zalloc(scsa2usb_statep, instance) != DDI_SUCCESS) { 6290Sstevel@tonic-gate ddi_prop_remove_all(dip); 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate return (DDI_FAILURE); 6320Sstevel@tonic-gate } 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate /* get soft state space and initialize */ 6350Sstevel@tonic-gate if ((scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 6360Sstevel@tonic-gate instance)) == NULL) { 6370Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, NULL, 6380Sstevel@tonic-gate "scsa2usb%d: bad soft state", instance); 6390Sstevel@tonic-gate ddi_prop_remove_all(dip); 6400Sstevel@tonic-gate 6410Sstevel@tonic-gate return (DDI_FAILURE); 6420Sstevel@tonic-gate } 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate scsa2usbp->scsa2usb_dip = dip; 6450Sstevel@tonic-gate scsa2usbp->scsa2usb_instance = instance; 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate /* allocate a log handle for debug/error messages */ 6480Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle = log_handle = 6490Sstevel@tonic-gate usb_alloc_log_hdl(dip, "s2u", 6504700Sfb209375 &scsa2usb_errlevel, 6514700Sfb209375 &scsa2usb_errmask, &scsa2usb_instance_debug, 6524700Sfb209375 0); 6530Sstevel@tonic-gate 6540Sstevel@tonic-gate /* attach to USBA */ 6550Sstevel@tonic-gate if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) { 6560Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 6570Sstevel@tonic-gate "usb_client_attach failed"); 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate goto fail; 6600Sstevel@tonic-gate } 6610Sstevel@tonic-gate if (usb_get_dev_data(dip, &dev_data, USB_PARSE_LVL_IF, 0) != 6620Sstevel@tonic-gate USB_SUCCESS) { 6630Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 6640Sstevel@tonic-gate "usb_get_dev_data failed"); 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate goto fail; 6670Sstevel@tonic-gate } 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate /* initialize the mutex with the right cookie */ 6700Sstevel@tonic-gate mutex_init(&scsa2usbp->scsa2usb_mutex, NULL, MUTEX_DRIVER, 6714700Sfb209375 dev_data->dev_iblock_cookie); 6720Sstevel@tonic-gate cv_init(&scsa2usbp->scsa2usb_transport_busy_cv, NULL, CV_DRIVER, NULL); 6730Sstevel@tonic-gate 6740Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 6750Sstevel@tonic-gate usba_init_list(&scsa2usbp->scsa2usb_waitQ[lun], NULL, 6764700Sfb209375 dev_data->dev_iblock_cookie); 6770Sstevel@tonic-gate } 6780Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 6790Sstevel@tonic-gate scsa2usbp->scsa2usb_dip = dip; 6800Sstevel@tonic-gate scsa2usbp->scsa2usb_instance = instance; 6810Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs = SCSA2USB_ALL_ATTRS; 6820Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_data = dev_data; 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate /* save the default pipe handle */ 6860Sstevel@tonic-gate scsa2usbp->scsa2usb_default_pipe = dev_data->dev_default_ph; 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate /* basic inits are done */ 6890Sstevel@tonic-gate scsa2usbp->scsa2usb_flags |= SCSA2USB_FLAGS_LOCKS_INIT; 6900Sstevel@tonic-gate 6910Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, log_handle, 6926898Sfb209375 "curr_cfg=%ld, curr_if=%d", 6936898Sfb209375 (long)(dev_data->dev_curr_cfg - &dev_data->dev_cfg[0]), 6940Sstevel@tonic-gate dev_data->dev_curr_if); 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate interface = dev_data->dev_curr_if; 6970Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_num = dev_data->dev_curr_if; 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate /* now find out relevant descriptors for alternate 0 */ 7000Sstevel@tonic-gate altif_data = &dev_data->dev_curr_cfg->cfg_if[interface].if_alt[0]; 7010Sstevel@tonic-gate 7020Sstevel@tonic-gate if (altif_data->altif_n_ep == 0) { 703978Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 7040Sstevel@tonic-gate "invalid alt 0 for interface %d", interface); 7050Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate goto fail; 7080Sstevel@tonic-gate } 7090Sstevel@tonic-gate 7100Sstevel@tonic-gate /* All CB/CBI, BO devices should have this value set */ 7110Sstevel@tonic-gate if (altif_data->altif_descr.bInterfaceClass != 7120Sstevel@tonic-gate USB_CLASS_MASS_STORAGE) { 713978Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 7140Sstevel@tonic-gate "invalid interface class (0x%x)", 7150Sstevel@tonic-gate altif_data->altif_descr.bInterfaceClass); 7160Sstevel@tonic-gate } 7170Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr = altif_data->altif_descr; 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate /* figure out the endpoints and copy the descr */ 7200Sstevel@tonic-gate if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, 0, 0, 7210Sstevel@tonic-gate USB_EP_ATTR_BULK, USB_EP_DIR_OUT)) != NULL) { 7220Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkout_ept = ep_data->ep_descr; 7230Sstevel@tonic-gate } 7240Sstevel@tonic-gate if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, 0, 0, 7250Sstevel@tonic-gate USB_EP_ATTR_BULK, USB_EP_DIR_IN)) != NULL) { 7260Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_ept = ep_data->ep_descr; 7270Sstevel@tonic-gate } 7280Sstevel@tonic-gate if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, 0, 0, 7290Sstevel@tonic-gate USB_EP_ATTR_INTR, USB_EP_DIR_IN)) != NULL) { 7300Sstevel@tonic-gate scsa2usbp->scsa2usb_intr_ept = ep_data->ep_descr; 7310Sstevel@tonic-gate } 7320Sstevel@tonic-gate 7330Sstevel@tonic-gate /* 7340Sstevel@tonic-gate * check here for protocol and subclass supported by this driver 7350Sstevel@tonic-gate * 7360Sstevel@tonic-gate * first check if conf file has override values 7370Sstevel@tonic-gate * Note: override values are not used if supplied values are legal 7380Sstevel@tonic-gate */ 7390Sstevel@tonic-gate scsa2usb_override(scsa2usbp); 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, log_handle, 7420Sstevel@tonic-gate "protocol=0x%x override=0x%x subclass=0x%x override=0x%x", 7430Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol, 7440Sstevel@tonic-gate scsa2usbp->scsa2usb_protocol_override, 7450Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass, 7460Sstevel@tonic-gate scsa2usbp->scsa2usb_subclass_override); 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate switch (scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol) { 7490Sstevel@tonic-gate case USB_PROTO_MS_CBI: 7500Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_CB_PROTOCOL; 7510Sstevel@tonic-gate break; 7520Sstevel@tonic-gate case USB_PROTO_MS_CBI_WC: 7530Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_CBI_PROTOCOL; 7540Sstevel@tonic-gate break; 7550Sstevel@tonic-gate case USB_PROTO_MS_ISD_1999_SILICN: 7560Sstevel@tonic-gate case USB_PROTO_MS_BULK_ONLY: 7570Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_BULK_ONLY_PROTOCOL; 7580Sstevel@tonic-gate break; 7590Sstevel@tonic-gate default: 7600Sstevel@tonic-gate if (scsa2usbp->scsa2usb_protocol_override) { 7610Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= 7620Sstevel@tonic-gate scsa2usbp->scsa2usb_protocol_override; 763978Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 7640Sstevel@tonic-gate "overriding protocol %x", 7650Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol); 7660Sstevel@tonic-gate break; 7670Sstevel@tonic-gate } 7680Sstevel@tonic-gate 7690Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 7700Sstevel@tonic-gate "unsupported protocol = %x", 7710Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol); 7720Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate goto fail; 7750Sstevel@tonic-gate } 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate switch (scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass) { 7780Sstevel@tonic-gate case USB_SUBCLS_MS_SCSI: /* transparent SCSI */ 7790Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_SCSI_CMDSET; 7800Sstevel@tonic-gate break; 7810Sstevel@tonic-gate case USB_SUBCLS_MS_SFF8020I: 7820Sstevel@tonic-gate case USB_SUBCLS_MS_SFF8070I: 7830Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_ATAPI_CMDSET; 7840Sstevel@tonic-gate break; 7850Sstevel@tonic-gate case USB_SUBCLS_MS_UFI: /* UFI */ 7860Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_UFI_CMDSET; 7870Sstevel@tonic-gate break; 7880Sstevel@tonic-gate default: 7890Sstevel@tonic-gate if (scsa2usbp->scsa2usb_subclass_override) { 7900Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= 7910Sstevel@tonic-gate scsa2usbp->scsa2usb_subclass_override; 792978Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 7930Sstevel@tonic-gate "overriding subclass %x", 7940Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass); 7950Sstevel@tonic-gate break; 7960Sstevel@tonic-gate } 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 7990Sstevel@tonic-gate "unsupported subclass = %x", 8000Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass); 8010Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate goto fail; 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate /* check that we have the right set of endpoint descriptors */ 8070Sstevel@tonic-gate if (SCSA2USB_IS_BULK_ONLY(scsa2usbp) || SCSA2USB_IS_CB(scsa2usbp)) { 8080Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_bulkout_ept.bLength == 0) || 8090Sstevel@tonic-gate (scsa2usbp->scsa2usb_bulkin_ept.bLength == 0)) { 8100Sstevel@tonic-gate ept_check = B_FALSE; 8110Sstevel@tonic-gate } 8120Sstevel@tonic-gate } else if (SCSA2USB_IS_CBI(scsa2usbp)) { 8130Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_bulkout_ept.bLength == 0) || 8140Sstevel@tonic-gate (scsa2usbp->scsa2usb_bulkin_ept.bLength == 0) || 8150Sstevel@tonic-gate (scsa2usbp->scsa2usb_intr_ept.bLength == 0)) { 8160Sstevel@tonic-gate ept_check = B_FALSE; 8170Sstevel@tonic-gate } 8180Sstevel@tonic-gate } 8190Sstevel@tonic-gate 8200Sstevel@tonic-gate if (ept_check == B_FALSE) { 821978Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 8220Sstevel@tonic-gate "scsa2usb%d doesn't support minimum required endpoints", 8230Sstevel@tonic-gate instance); 8240Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 8250Sstevel@tonic-gate 8260Sstevel@tonic-gate goto fail; 8270Sstevel@tonic-gate } 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate /* 8300Sstevel@tonic-gate * Validate the black-listed attributes 8310Sstevel@tonic-gate */ 8320Sstevel@tonic-gate scsa2usb_validate_attrs(scsa2usbp); 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate /* Print the serial number from the registration data */ 8350Sstevel@tonic-gate if (scsa2usbp->scsa2usb_dev_data->dev_serial) { 8360Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, 8370Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, "Serial Number = %s", 8380Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_data->dev_serial); 8390Sstevel@tonic-gate } 8400Sstevel@tonic-gate 8410Sstevel@tonic-gate /* 8420Sstevel@tonic-gate * Allocate a SCSA transport structure 8430Sstevel@tonic-gate */ 8440Sstevel@tonic-gate tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP); 8450Sstevel@tonic-gate scsa2usbp->scsa2usb_tran = tran; 8460Sstevel@tonic-gate 8470Sstevel@tonic-gate /* 8480Sstevel@tonic-gate * initialize transport structure 8490Sstevel@tonic-gate */ 8500Sstevel@tonic-gate tran->tran_hba_private = scsa2usbp; 8510Sstevel@tonic-gate tran->tran_tgt_private = NULL; 8520Sstevel@tonic-gate tran->tran_tgt_init = scsa2usb_scsi_tgt_init; 8530Sstevel@tonic-gate tran->tran_tgt_probe = scsa2usb_scsi_tgt_probe; 8540Sstevel@tonic-gate tran->tran_tgt_free = scsa2usb_scsi_tgt_free; 8550Sstevel@tonic-gate tran->tran_start = scsa2usb_scsi_start; 8560Sstevel@tonic-gate tran->tran_abort = scsa2usb_scsi_abort; 8570Sstevel@tonic-gate tran->tran_reset = scsa2usb_scsi_reset; 8580Sstevel@tonic-gate tran->tran_getcap = scsa2usb_scsi_getcap; 8590Sstevel@tonic-gate tran->tran_setcap = scsa2usb_scsi_setcap; 8600Sstevel@tonic-gate tran->tran_init_pkt = scsa2usb_scsi_init_pkt; 8610Sstevel@tonic-gate tran->tran_destroy_pkt = scsa2usb_scsi_destroy_pkt; 8620Sstevel@tonic-gate tran->tran_dmafree = NULL; 8630Sstevel@tonic-gate tran->tran_sync_pkt = NULL; 8640Sstevel@tonic-gate tran->tran_reset_notify = NULL; 8650Sstevel@tonic-gate tran->tran_get_bus_addr = NULL; 8660Sstevel@tonic-gate tran->tran_get_name = NULL; 8670Sstevel@tonic-gate tran->tran_quiesce = NULL; 8680Sstevel@tonic-gate tran->tran_unquiesce = NULL; 8690Sstevel@tonic-gate tran->tran_bus_reset = NULL; 8700Sstevel@tonic-gate tran->tran_add_eventcall = NULL; 8710Sstevel@tonic-gate tran->tran_get_eventcookie = NULL; 8720Sstevel@tonic-gate tran->tran_post_event = NULL; 8730Sstevel@tonic-gate tran->tran_remove_eventcall = NULL; 8740Sstevel@tonic-gate tran->tran_bus_config = scsa2usb_scsi_bus_config; 8750Sstevel@tonic-gate tran->tran_bus_unconfig = scsa2usb_scsi_bus_unconfig; 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate /* 8780Sstevel@tonic-gate * register with SCSA as an HBA 8790Sstevel@tonic-gate * Note that the dma attributes are from parent nexus 8800Sstevel@tonic-gate */ 8810Sstevel@tonic-gate if (scsi_hba_attach_setup(dip, usba_get_hc_dma_attr(dip), tran, 0)) { 8820Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 8830Sstevel@tonic-gate "scsi_hba_attach_setup failed"); 8840Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 8850Sstevel@tonic-gate 8860Sstevel@tonic-gate goto fail; 8870Sstevel@tonic-gate } 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate scsa2usbp->scsa2usb_flags |= SCSA2USB_FLAGS_HBA_ATTACH_SETUP; 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate /* create minor node */ 8920Sstevel@tonic-gate if (ddi_create_minor_node(dip, "scsa2usb", S_IFCHR, 8930Sstevel@tonic-gate instance << SCSA2USB_MINOR_INSTANCE_SHIFT, 8940Sstevel@tonic-gate DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) { 8950Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 8960Sstevel@tonic-gate "scsi_attach: ddi_create_minor_node failed"); 8970Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 8980Sstevel@tonic-gate 8990Sstevel@tonic-gate goto fail; 9000Sstevel@tonic-gate } 9010Sstevel@tonic-gate 9020Sstevel@tonic-gate /* open pipes and set scsa2usb_flags */ 9030Sstevel@tonic-gate if (scsa2usb_open_usb_pipes(scsa2usbp) == USB_FAILURE) { 9040Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 9050Sstevel@tonic-gate "error opening pipes"); 9060Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 9070Sstevel@tonic-gate 9080Sstevel@tonic-gate goto fail; 9090Sstevel@tonic-gate } 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate /* set default block size. updated after read cap cmd */ 9120Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 9130Sstevel@tonic-gate scsa2usbp->scsa2usb_lbasize[lun] = DEV_BSIZE; 9140Sstevel@tonic-gate } 9150Sstevel@tonic-gate 9160Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 9170Sstevel@tonic-gate 9180Sstevel@tonic-gate /* initialize PANIC callback */ 9190Sstevel@tonic-gate scsa2usb_panic_callb_init(scsa2usbp); 9200Sstevel@tonic-gate 9210Sstevel@tonic-gate /* finally we are all done 'initializing' the device */ 9220Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 9230Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_ONLINE; 9240Sstevel@tonic-gate 9250Sstevel@tonic-gate /* enable PM, mutex needs to be held across this */ 9260Sstevel@tonic-gate scsa2usb_create_pm_components(dip, scsa2usbp); 9270Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate /* register for connect/disconnect events */ 9300Sstevel@tonic-gate if (usb_register_event_cbs(scsa2usbp->scsa2usb_dip, &scsa2usb_events, 9310Sstevel@tonic-gate 0) != USB_SUCCESS) { 9320Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 9330Sstevel@tonic-gate "error cb registering"); 9340Sstevel@tonic-gate goto fail; 9350Sstevel@tonic-gate } 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate /* free the dev_data tree, we no longer need it */ 9380Sstevel@tonic-gate usb_free_descr_tree(dip, dev_data); 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate scsa2usb_pm_idle_component(scsa2usbp); 9410Sstevel@tonic-gate 9420Sstevel@tonic-gate /* log the conf file override string if there is one */ 9430Sstevel@tonic-gate if (scsa2usbp->scsa2usb_override_str) { 944978Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 9450Sstevel@tonic-gate "scsa2usb.conf override: %s", 9460Sstevel@tonic-gate scsa2usbp->scsa2usb_override_str); 9470Sstevel@tonic-gate } 9480Sstevel@tonic-gate 9490Sstevel@tonic-gate if (usb_owns_device(dip)) { 9500Sstevel@tonic-gate /* get a ugen handle */ 9510Sstevel@tonic-gate bzero(&usb_ugen_info, sizeof (usb_ugen_info)); 9520Sstevel@tonic-gate usb_ugen_info.usb_ugen_flags = 0; 9530Sstevel@tonic-gate usb_ugen_info.usb_ugen_minor_node_ugen_bits_mask = 9544700Sfb209375 (dev_t)SCSA2USB_MINOR_UGEN_BITS_MASK; 9550Sstevel@tonic-gate usb_ugen_info.usb_ugen_minor_node_instance_mask = 9564700Sfb209375 (dev_t)~SCSA2USB_MINOR_UGEN_BITS_MASK; 9570Sstevel@tonic-gate scsa2usbp->scsa2usb_ugen_hdl = 9584700Sfb209375 usb_ugen_get_hdl(dip, &usb_ugen_info); 9590Sstevel@tonic-gate 9600Sstevel@tonic-gate if (usb_ugen_attach(scsa2usbp->scsa2usb_ugen_hdl, cmd) != 9610Sstevel@tonic-gate USB_SUCCESS) { 9620Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 9630Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 9640Sstevel@tonic-gate "usb_ugen_attach failed"); 9650Sstevel@tonic-gate 9660Sstevel@tonic-gate usb_ugen_release_hdl(scsa2usbp->scsa2usb_ugen_hdl); 9670Sstevel@tonic-gate scsa2usbp->scsa2usb_ugen_hdl = NULL; 9680Sstevel@tonic-gate } 9690Sstevel@tonic-gate } 9700Sstevel@tonic-gate 9710Sstevel@tonic-gate /* report device */ 9720Sstevel@tonic-gate ddi_report_dev(dip); 9730Sstevel@tonic-gate 9740Sstevel@tonic-gate return (DDI_SUCCESS); 9750Sstevel@tonic-gate 9760Sstevel@tonic-gate fail: 9770Sstevel@tonic-gate if (scsa2usbp) { 9780Sstevel@tonic-gate (void) scsa2usb_cleanup(dip, scsa2usbp); 9790Sstevel@tonic-gate } 9800Sstevel@tonic-gate 9810Sstevel@tonic-gate return (DDI_FAILURE); 9820Sstevel@tonic-gate } 9830Sstevel@tonic-gate 9840Sstevel@tonic-gate 9850Sstevel@tonic-gate /* 9860Sstevel@tonic-gate * scsa2usb_detach: 9870Sstevel@tonic-gate * detach or suspend driver instance 9880Sstevel@tonic-gate */ 9890Sstevel@tonic-gate static int 9900Sstevel@tonic-gate scsa2usb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 9910Sstevel@tonic-gate { 9920Sstevel@tonic-gate scsi_hba_tran_t *tran; 9930Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 9940Sstevel@tonic-gate int rval; 9950Sstevel@tonic-gate 9960Sstevel@tonic-gate tran = ddi_get_driver_private(dip); 9970Sstevel@tonic-gate ASSERT(tran != NULL); 9980Sstevel@tonic-gate 9990Sstevel@tonic-gate scsa2usbp = (scsa2usb_state_t *)tran->tran_hba_private; 10000Sstevel@tonic-gate ASSERT(scsa2usbp); 10010Sstevel@tonic-gate 10020Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 10036898Sfb209375 "scsa2usb_detach: dip = 0x%p, cmd = %d", (void *)dip, cmd); 10040Sstevel@tonic-gate 10050Sstevel@tonic-gate switch (cmd) { 10060Sstevel@tonic-gate case DDI_DETACH: 10070Sstevel@tonic-gate 10080Sstevel@tonic-gate if (scsa2usb_cleanup(dip, scsa2usbp) != USB_SUCCESS) { 10090Sstevel@tonic-gate 10100Sstevel@tonic-gate return (DDI_FAILURE); 10110Sstevel@tonic-gate } 10120Sstevel@tonic-gate 10130Sstevel@tonic-gate return (DDI_SUCCESS); 10140Sstevel@tonic-gate case DDI_SUSPEND: 10150Sstevel@tonic-gate rval = scsa2usb_cpr_suspend(dip); 10160Sstevel@tonic-gate 10170Sstevel@tonic-gate return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 10180Sstevel@tonic-gate default: 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate return (DDI_FAILURE); 10210Sstevel@tonic-gate } 10220Sstevel@tonic-gate } 10230Sstevel@tonic-gate 10240Sstevel@tonic-gate 10250Sstevel@tonic-gate /* 10260Sstevel@tonic-gate * ugen support 10270Sstevel@tonic-gate */ 10280Sstevel@tonic-gate /* 10290Sstevel@tonic-gate * scsa2usb_ugen_open() 10300Sstevel@tonic-gate * (all ugen opens and pipe opens are by definition exclusive so it is OK 10310Sstevel@tonic-gate * to count opens) 10320Sstevel@tonic-gate */ 10330Sstevel@tonic-gate static int 10340Sstevel@tonic-gate scsa2usb_ugen_open(dev_t *devp, int flag, int sflag, cred_t *cr) 10350Sstevel@tonic-gate { 10360Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 10370Sstevel@tonic-gate int rval; 10380Sstevel@tonic-gate 10390Sstevel@tonic-gate if ((scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 10400Sstevel@tonic-gate SCSA2USB_MINOR_TO_INSTANCE(getminor(*devp)))) == NULL) { 10410Sstevel@tonic-gate /* deferred detach */ 10420Sstevel@tonic-gate 10430Sstevel@tonic-gate return (ENXIO); 10440Sstevel@tonic-gate } 10450Sstevel@tonic-gate 10460Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 10470Sstevel@tonic-gate "scsa2usb_ugen_open: dev_t=0x%lx", *devp); 10480Sstevel@tonic-gate 10490Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 10500Sstevel@tonic-gate 10510Sstevel@tonic-gate /* if this is the first ugen open, check on transport busy */ 10520Sstevel@tonic-gate if (scsa2usbp->scsa2usb_ugen_open_count == 0) { 10530Sstevel@tonic-gate while (scsa2usbp->scsa2usb_transport_busy || 10540Sstevel@tonic-gate (scsa2usb_all_waitQs_empty(scsa2usbp) != 10550Sstevel@tonic-gate USB_SUCCESS)) { 10560Sstevel@tonic-gate rval = cv_wait_sig( 10574700Sfb209375 &scsa2usbp->scsa2usb_transport_busy_cv, 10584700Sfb209375 &scsa2usbp->scsa2usb_mutex); 10590Sstevel@tonic-gate if (rval == 0) { 10600Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 10610Sstevel@tonic-gate 10620Sstevel@tonic-gate return (EINTR); 10630Sstevel@tonic-gate } 10640Sstevel@tonic-gate } 10650Sstevel@tonic-gate scsa2usbp->scsa2usb_transport_busy++; 10660Sstevel@tonic-gate scsa2usbp->scsa2usb_busy_thread = curthread; 10670Sstevel@tonic-gate } 10680Sstevel@tonic-gate scsa2usbp->scsa2usb_ugen_open_count++; 10690Sstevel@tonic-gate 10700Sstevel@tonic-gate scsa2usb_raise_power(scsa2usbp); 10710Sstevel@tonic-gate 10720Sstevel@tonic-gate scsa2usb_close_usb_pipes(scsa2usbp); 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 10750Sstevel@tonic-gate 10760Sstevel@tonic-gate rval = usb_ugen_open(scsa2usbp->scsa2usb_ugen_hdl, devp, flag, 10774700Sfb209375 sflag, cr); 10780Sstevel@tonic-gate 10790Sstevel@tonic-gate if (rval) { 10800Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 10810Sstevel@tonic-gate 10820Sstevel@tonic-gate /* reopen the pipes */ 10830Sstevel@tonic-gate if (--scsa2usbp->scsa2usb_ugen_open_count == 0) { 10840Sstevel@tonic-gate scsa2usbp->scsa2usb_transport_busy--; 10850Sstevel@tonic-gate scsa2usbp->scsa2usb_busy_thread = NULL; 10860Sstevel@tonic-gate cv_signal(&scsa2usbp->scsa2usb_transport_busy_cv); 10870Sstevel@tonic-gate } 1088189Sfrits mutex_exit(&scsa2usbp->scsa2usb_mutex); 1089189Sfrits 10900Sstevel@tonic-gate scsa2usb_pm_idle_component(scsa2usbp); 10910Sstevel@tonic-gate } 10920Sstevel@tonic-gate 10930Sstevel@tonic-gate return (rval); 10940Sstevel@tonic-gate } 10950Sstevel@tonic-gate 10960Sstevel@tonic-gate 10970Sstevel@tonic-gate /* 10980Sstevel@tonic-gate * scsa2usb_ugen_close() 10990Sstevel@tonic-gate */ 11000Sstevel@tonic-gate static int 11010Sstevel@tonic-gate scsa2usb_ugen_close(dev_t dev, int flag, int otype, cred_t *cr) 11020Sstevel@tonic-gate { 11030Sstevel@tonic-gate int rval; 11040Sstevel@tonic-gate 11050Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 11064700Sfb209375 SCSA2USB_MINOR_TO_INSTANCE(getminor(dev))); 11070Sstevel@tonic-gate 11080Sstevel@tonic-gate if (scsa2usbp == NULL) { 11090Sstevel@tonic-gate 11100Sstevel@tonic-gate return (ENXIO); 11110Sstevel@tonic-gate } 11120Sstevel@tonic-gate 11130Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 11140Sstevel@tonic-gate "scsa2usb_ugen_close: dev_t=0x%lx", dev); 11150Sstevel@tonic-gate 11160Sstevel@tonic-gate rval = usb_ugen_close(scsa2usbp->scsa2usb_ugen_hdl, dev, flag, 11174700Sfb209375 otype, cr); 11180Sstevel@tonic-gate 11190Sstevel@tonic-gate if (rval == 0) { 11200Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 11210Sstevel@tonic-gate 11220Sstevel@tonic-gate /* reopen the pipes */ 11230Sstevel@tonic-gate if (--scsa2usbp->scsa2usb_ugen_open_count == 0) { 11240Sstevel@tonic-gate scsa2usbp->scsa2usb_transport_busy--; 11250Sstevel@tonic-gate scsa2usbp->scsa2usb_busy_thread = NULL; 11260Sstevel@tonic-gate cv_signal(&scsa2usbp->scsa2usb_transport_busy_cv); 11270Sstevel@tonic-gate } 1128189Sfrits mutex_exit(&scsa2usbp->scsa2usb_mutex); 1129189Sfrits 11300Sstevel@tonic-gate scsa2usb_pm_idle_component(scsa2usbp); 11310Sstevel@tonic-gate } 11320Sstevel@tonic-gate 11330Sstevel@tonic-gate return (rval); 11340Sstevel@tonic-gate } 11350Sstevel@tonic-gate 11360Sstevel@tonic-gate 11370Sstevel@tonic-gate /* 11380Sstevel@tonic-gate * scsa2usb_ugen_read/write() 11390Sstevel@tonic-gate */ 11400Sstevel@tonic-gate /*ARGSUSED*/ 11410Sstevel@tonic-gate static int 11420Sstevel@tonic-gate scsa2usb_ugen_read(dev_t dev, struct uio *uiop, cred_t *credp) 11430Sstevel@tonic-gate { 11440Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 11454700Sfb209375 SCSA2USB_MINOR_TO_INSTANCE(getminor(dev))); 11460Sstevel@tonic-gate 11470Sstevel@tonic-gate if (scsa2usbp == NULL) { 11480Sstevel@tonic-gate 11490Sstevel@tonic-gate return (ENXIO); 11500Sstevel@tonic-gate } 11510Sstevel@tonic-gate 11520Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 11530Sstevel@tonic-gate "scsa2usb_ugen_read: dev_t=0x%lx", dev); 11540Sstevel@tonic-gate 11550Sstevel@tonic-gate 11560Sstevel@tonic-gate return (usb_ugen_read(scsa2usbp->scsa2usb_ugen_hdl, dev, 11574700Sfb209375 uiop, credp)); 11580Sstevel@tonic-gate } 11590Sstevel@tonic-gate 11600Sstevel@tonic-gate 11610Sstevel@tonic-gate /*ARGSUSED*/ 11620Sstevel@tonic-gate static int 11630Sstevel@tonic-gate scsa2usb_ugen_write(dev_t dev, struct uio *uiop, cred_t *credp) 11640Sstevel@tonic-gate { 11650Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 11664700Sfb209375 SCSA2USB_MINOR_TO_INSTANCE(getminor(dev))); 11670Sstevel@tonic-gate 11680Sstevel@tonic-gate if (scsa2usbp == NULL) { 11690Sstevel@tonic-gate 11700Sstevel@tonic-gate return (ENXIO); 11710Sstevel@tonic-gate } 11720Sstevel@tonic-gate 11730Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 11740Sstevel@tonic-gate "scsa2usb_ugen_write: dev_t=0x%lx", dev); 11750Sstevel@tonic-gate 11760Sstevel@tonic-gate return (usb_ugen_write(scsa2usbp->scsa2usb_ugen_hdl, 11774700Sfb209375 dev, uiop, credp)); 11780Sstevel@tonic-gate } 11790Sstevel@tonic-gate 11800Sstevel@tonic-gate 11810Sstevel@tonic-gate /* 11820Sstevel@tonic-gate * scsa2usb_ugen_poll 11830Sstevel@tonic-gate */ 11840Sstevel@tonic-gate static int 11850Sstevel@tonic-gate scsa2usb_ugen_poll(dev_t dev, short events, 11860Sstevel@tonic-gate int anyyet, short *reventsp, struct pollhead **phpp) 11870Sstevel@tonic-gate { 11880Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 11894700Sfb209375 SCSA2USB_MINOR_TO_INSTANCE(getminor(dev))); 11900Sstevel@tonic-gate 11910Sstevel@tonic-gate if (scsa2usbp == NULL) { 11920Sstevel@tonic-gate 11930Sstevel@tonic-gate return (ENXIO); 11940Sstevel@tonic-gate } 11950Sstevel@tonic-gate 11960Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 11970Sstevel@tonic-gate "scsa2usb_ugen_poll: dev_t=0x%lx", dev); 11980Sstevel@tonic-gate 11990Sstevel@tonic-gate return (usb_ugen_poll(scsa2usbp->scsa2usb_ugen_hdl, dev, events, 12004700Sfb209375 anyyet, reventsp, phpp)); 12010Sstevel@tonic-gate } 12020Sstevel@tonic-gate 12030Sstevel@tonic-gate 12040Sstevel@tonic-gate /* 12050Sstevel@tonic-gate * scsa2usb_cleanup: 12060Sstevel@tonic-gate * cleanup whatever attach has setup 12070Sstevel@tonic-gate */ 12080Sstevel@tonic-gate static int 12090Sstevel@tonic-gate scsa2usb_cleanup(dev_info_t *dip, scsa2usb_state_t *scsa2usbp) 12100Sstevel@tonic-gate { 12110Sstevel@tonic-gate int rval, i; 12120Sstevel@tonic-gate scsa2usb_power_t *pm; 12130Sstevel@tonic-gate uint_t lun; 12140Sstevel@tonic-gate 12150Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 12160Sstevel@tonic-gate "scsa2usb_cleanup:"); 12170Sstevel@tonic-gate 12180Sstevel@tonic-gate /* wait till the work thread is done */ 12190Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 12200Sstevel@tonic-gate for (i = 0; i < SCSA2USB_DRAIN_TIMEOUT; i++) { 12210Sstevel@tonic-gate if (scsa2usbp->scsa2usb_work_thread_id == NULL) { 12220Sstevel@tonic-gate 12230Sstevel@tonic-gate break; 12240Sstevel@tonic-gate } 12250Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 12260Sstevel@tonic-gate delay(drv_usectohz(1000000)); 12270Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 12280Sstevel@tonic-gate } 12290Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 12300Sstevel@tonic-gate 12310Sstevel@tonic-gate if (i >= SCSA2USB_DRAIN_TIMEOUT) { 12320Sstevel@tonic-gate 12330Sstevel@tonic-gate return (USB_FAILURE); 12340Sstevel@tonic-gate } 12350Sstevel@tonic-gate 12360Sstevel@tonic-gate /* 12370Sstevel@tonic-gate * Disable the event callbacks first, after this point, event 12380Sstevel@tonic-gate * callbacks will never get called. Note we shouldn't hold 12390Sstevel@tonic-gate * mutex while unregistering events because there may be a 12400Sstevel@tonic-gate * competing event callback thread. Event callbacks are done 12410Sstevel@tonic-gate * with ndi mutex held and this can cause a potential deadlock. 12420Sstevel@tonic-gate */ 12430Sstevel@tonic-gate usb_unregister_event_cbs(scsa2usbp->scsa2usb_dip, &scsa2usb_events); 12440Sstevel@tonic-gate 12450Sstevel@tonic-gate if (scsa2usbp->scsa2usb_flags & SCSA2USB_FLAGS_LOCKS_INIT) { 12460Sstevel@tonic-gate /* 12470Sstevel@tonic-gate * if a waitQ exists, get rid of it before destroying it 12480Sstevel@tonic-gate */ 12490Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 12500Sstevel@tonic-gate scsa2usb_flush_waitQ(scsa2usbp, lun, CMD_TRAN_ERR); 12510Sstevel@tonic-gate usba_destroy_list(&scsa2usbp->scsa2usb_waitQ[lun]); 12520Sstevel@tonic-gate } 12530Sstevel@tonic-gate 12540Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 12550Sstevel@tonic-gate if (scsa2usbp->scsa2usb_flags & 12560Sstevel@tonic-gate SCSA2USB_FLAGS_HBA_ATTACH_SETUP) { 12570Sstevel@tonic-gate (void) scsi_hba_detach(dip); 12580Sstevel@tonic-gate scsi_hba_tran_free(scsa2usbp->scsa2usb_tran); 12590Sstevel@tonic-gate } 12600Sstevel@tonic-gate 12610Sstevel@tonic-gate if (scsa2usbp->scsa2usb_flags & 12620Sstevel@tonic-gate SCSA2USB_FLAGS_PIPES_OPENED) { 12630Sstevel@tonic-gate scsa2usb_close_usb_pipes(scsa2usbp); 12640Sstevel@tonic-gate } 12650Sstevel@tonic-gate 12660Sstevel@tonic-gate /* Lower the power */ 12670Sstevel@tonic-gate pm = scsa2usbp->scsa2usb_pm; 12680Sstevel@tonic-gate 12690Sstevel@tonic-gate if (pm && (scsa2usbp->scsa2usb_dev_state != 12700Sstevel@tonic-gate USB_DEV_DISCONNECTED)) { 12710Sstevel@tonic-gate if (pm->scsa2usb_wakeup_enabled) { 12720Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 12730Sstevel@tonic-gate (void) pm_raise_power(dip, 0, 12744700Sfb209375 USB_DEV_OS_FULL_PWR); 12750Sstevel@tonic-gate 12760Sstevel@tonic-gate if ((rval = usb_handle_remote_wakeup(dip, 12770Sstevel@tonic-gate USB_REMOTE_WAKEUP_DISABLE)) != 12780Sstevel@tonic-gate USB_SUCCESS) { 1279978Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, 12800Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 12810Sstevel@tonic-gate "disable remote wakeup failed " 12820Sstevel@tonic-gate "(%d)", rval); 12830Sstevel@tonic-gate } 12840Sstevel@tonic-gate } else { 12850Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 12860Sstevel@tonic-gate } 12870Sstevel@tonic-gate 12880Sstevel@tonic-gate (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF); 12890Sstevel@tonic-gate 12900Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 12910Sstevel@tonic-gate } 12920Sstevel@tonic-gate 12930Sstevel@tonic-gate if (pm) { 12940Sstevel@tonic-gate kmem_free(pm, sizeof (scsa2usb_power_t)); 12950Sstevel@tonic-gate } 12960Sstevel@tonic-gate 12970Sstevel@tonic-gate if (scsa2usbp->scsa2usb_override_str) { 12980Sstevel@tonic-gate kmem_free(scsa2usbp->scsa2usb_override_str, 12990Sstevel@tonic-gate strlen(scsa2usbp->scsa2usb_override_str) + 1); 13000Sstevel@tonic-gate scsa2usbp->scsa2usb_override_str = NULL; 13010Sstevel@tonic-gate } 13020Sstevel@tonic-gate 13030Sstevel@tonic-gate /* remove the minor nodes */ 13040Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 13050Sstevel@tonic-gate 13060Sstevel@tonic-gate /* Cancel the registered panic callback */ 13070Sstevel@tonic-gate scsa2usb_panic_callb_fini(scsa2usbp); 13080Sstevel@tonic-gate 13090Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 13100Sstevel@tonic-gate 13110Sstevel@tonic-gate mutex_destroy(&scsa2usbp->scsa2usb_mutex); 13120Sstevel@tonic-gate cv_destroy(&scsa2usbp->scsa2usb_transport_busy_cv); 13130Sstevel@tonic-gate } 13140Sstevel@tonic-gate 13150Sstevel@tonic-gate usb_client_detach(scsa2usbp->scsa2usb_dip, 13164700Sfb209375 scsa2usbp->scsa2usb_dev_data); 13170Sstevel@tonic-gate 13180Sstevel@tonic-gate if (scsa2usbp->scsa2usb_ugen_hdl) { 13190Sstevel@tonic-gate (void) usb_ugen_detach(scsa2usbp->scsa2usb_ugen_hdl, 13204700Sfb209375 DDI_DETACH); 13210Sstevel@tonic-gate usb_ugen_release_hdl(scsa2usbp->scsa2usb_ugen_hdl); 13220Sstevel@tonic-gate } 13230Sstevel@tonic-gate 13240Sstevel@tonic-gate usb_free_log_hdl(scsa2usbp->scsa2usb_log_handle); 13250Sstevel@tonic-gate 13260Sstevel@tonic-gate ddi_prop_remove_all(dip); 13270Sstevel@tonic-gate 13280Sstevel@tonic-gate ddi_soft_state_free(scsa2usb_statep, ddi_get_instance(dip)); 13290Sstevel@tonic-gate 13300Sstevel@tonic-gate return (USB_SUCCESS); 13310Sstevel@tonic-gate } 13320Sstevel@tonic-gate 13330Sstevel@tonic-gate 13340Sstevel@tonic-gate /* 13350Sstevel@tonic-gate * scsa2usb_override: 13360Sstevel@tonic-gate * some devices may be attached even though their subclass or 13370Sstevel@tonic-gate * protocol info is not according to spec. 13380Sstevel@tonic-gate * these can be determined by the 'subclass-protocol-override' 13390Sstevel@tonic-gate * property set in the conf file. 13400Sstevel@tonic-gate */ 13410Sstevel@tonic-gate static void 13420Sstevel@tonic-gate scsa2usb_override(scsa2usb_state_t *scsa2usbp) 13430Sstevel@tonic-gate { 13440Sstevel@tonic-gate scsa2usb_ov_t ov; 13450Sstevel@tonic-gate char **override_str = NULL; 13460Sstevel@tonic-gate char *override_str_cpy; 13470Sstevel@tonic-gate uint_t override_str_len, override_str_cpy_len; 13480Sstevel@tonic-gate uint_t i; 13490Sstevel@tonic-gate usb_dev_descr_t *descr = scsa2usbp->scsa2usb_dev_data->dev_descr; 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 13520Sstevel@tonic-gate 13530Sstevel@tonic-gate scsa2usbp->scsa2usb_subclass_override = 13540Sstevel@tonic-gate scsa2usbp->scsa2usb_protocol_override = 0; 13550Sstevel@tonic-gate 13560Sstevel@tonic-gate if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, scsa2usbp->scsa2usb_dip, 13570Sstevel@tonic-gate DDI_PROP_DONTPASS, "attribute-override-list", 13580Sstevel@tonic-gate &override_str, &override_str_len) != DDI_PROP_SUCCESS) { 13590Sstevel@tonic-gate 13600Sstevel@tonic-gate return; 13610Sstevel@tonic-gate } 13620Sstevel@tonic-gate 13630Sstevel@tonic-gate /* parse each string in the subclass-protocol-override property */ 13640Sstevel@tonic-gate for (i = 0; i < override_str_len; i++) { 13650Sstevel@tonic-gate 13660Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 13670Sstevel@tonic-gate "override_str[%d] = %s", i, override_str[i]); 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate /* 13700Sstevel@tonic-gate * save a copy of the override string for possible 13710Sstevel@tonic-gate * inclusion in soft state later 13720Sstevel@tonic-gate */ 13730Sstevel@tonic-gate override_str_cpy_len = strlen(override_str[i]) + 1; 13740Sstevel@tonic-gate override_str_cpy = kmem_zalloc(override_str_cpy_len, KM_SLEEP); 13750Sstevel@tonic-gate (void) strcpy(override_str_cpy, override_str[i]); 13760Sstevel@tonic-gate 13770Sstevel@tonic-gate bzero(&ov, sizeof (scsa2usb_ov_t)); 13780Sstevel@tonic-gate 13790Sstevel@tonic-gate if (scsa2usb_parse_input_str(override_str[i], &ov, 13800Sstevel@tonic-gate scsa2usbp) == USB_FAILURE) { 13810Sstevel@tonic-gate kmem_free(override_str_cpy, override_str_cpy_len); 13820Sstevel@tonic-gate continue; 13830Sstevel@tonic-gate } 13840Sstevel@tonic-gate 13850Sstevel@tonic-gate /* 13860Sstevel@tonic-gate * see if subclass/protocol needs to be overridden for device 13870Sstevel@tonic-gate * or if device should not be power managed 13880Sstevel@tonic-gate * if there'a a match, save the override string in soft state 13890Sstevel@tonic-gate */ 13900Sstevel@tonic-gate if (((descr->idVendor == (uint16_t)ov.vid) || (ov.vid == 0)) && 13910Sstevel@tonic-gate ((descr->idProduct == (uint16_t)ov.pid) || (ov.pid == 0)) && 13920Sstevel@tonic-gate ((descr->bcdDevice == (uint16_t)ov.rev) || (ov.rev == 0))) { 13930Sstevel@tonic-gate scsa2usbp->scsa2usb_subclass_override = ov.subclass; 13940Sstevel@tonic-gate scsa2usbp->scsa2usb_protocol_override = ov.protocol; 13950Sstevel@tonic-gate 1396880Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, 13970Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 13980Sstevel@tonic-gate "vid=0x%x pid=0x%x rev=0x%x subclass=0x%x " 13990Sstevel@tonic-gate "protocol=0x%x " 14001415Scg149915 "pmoff=%d fake_removable=%d modesense=%d " 14010Sstevel@tonic-gate "reduced-cmd-support=%d", 14020Sstevel@tonic-gate ov.vid, ov.pid, ov.rev, ov.subclass, ov.protocol, 14031415Scg149915 ov.pmoff, ov.fake_removable, ov.no_modesense, 14040Sstevel@tonic-gate ov.reduced_cmd_support); 14050Sstevel@tonic-gate 14060Sstevel@tonic-gate if (ov.pmoff) { 14070Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= ~SCSA2USB_ATTRS_PM; 14080Sstevel@tonic-gate } 14091415Scg149915 if (ov.fake_removable) { 14100Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= 14110Sstevel@tonic-gate ~SCSA2USB_ATTRS_RMB; 14120Sstevel@tonic-gate } 14130Sstevel@tonic-gate if (ov.no_modesense) { 14140Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= 14150Sstevel@tonic-gate ~SCSA2USB_ATTRS_MODE_SENSE; 14160Sstevel@tonic-gate } 14170Sstevel@tonic-gate if (ov.reduced_cmd_support) { 14180Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= 14190Sstevel@tonic-gate ~SCSA2USB_ATTRS_REDUCED_CMD; 14200Sstevel@tonic-gate } 14210Sstevel@tonic-gate scsa2usbp->scsa2usb_override_str = override_str_cpy; 14220Sstevel@tonic-gate break; 14230Sstevel@tonic-gate } else { 14240Sstevel@tonic-gate kmem_free(override_str_cpy, override_str_cpy_len); 14250Sstevel@tonic-gate } 14260Sstevel@tonic-gate } 14270Sstevel@tonic-gate 14280Sstevel@tonic-gate ddi_prop_free(override_str); 14290Sstevel@tonic-gate } 14300Sstevel@tonic-gate 14310Sstevel@tonic-gate 14320Sstevel@tonic-gate /* 14330Sstevel@tonic-gate * scsa2usb_parse_input_str: 14340Sstevel@tonic-gate * parse one conf file subclass-protocol-override string 14350Sstevel@tonic-gate * return vendor id, product id, revision, subclass, protocol 14360Sstevel@tonic-gate * function return is success or failure 14370Sstevel@tonic-gate */ 14380Sstevel@tonic-gate static int 14390Sstevel@tonic-gate scsa2usb_parse_input_str(char *str, scsa2usb_ov_t *ovp, 14400Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp) 14410Sstevel@tonic-gate { 14420Sstevel@tonic-gate char *input_field, *input_value; 14430Sstevel@tonic-gate char *lasts; 14440Sstevel@tonic-gate uint_t i; 14450Sstevel@tonic-gate u_longlong_t value; 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate /* parse all the input pairs in the string */ 14480Sstevel@tonic-gate for (input_field = scsa2usb_strtok_r(str, "=", &lasts); 14490Sstevel@tonic-gate input_field != NULL; 14500Sstevel@tonic-gate input_field = scsa2usb_strtok_r(lasts, "=", &lasts)) { 14510Sstevel@tonic-gate 14520Sstevel@tonic-gate if ((input_value = scsa2usb_strtok_r(lasts, " ", &lasts)) == 14530Sstevel@tonic-gate NULL) { 14540Sstevel@tonic-gate scsa2usb_override_error("format", scsa2usbp); 14550Sstevel@tonic-gate 14560Sstevel@tonic-gate return (USB_FAILURE); 14570Sstevel@tonic-gate } 14580Sstevel@tonic-gate /* if input value is a 'don't care', skip to the next pair */ 14590Sstevel@tonic-gate if (strcmp(input_value, "*") == 0) { 14600Sstevel@tonic-gate continue; 14610Sstevel@tonic-gate } 14620Sstevel@tonic-gate if (strcasecmp(input_field, "vid") == 0) { 14630Sstevel@tonic-gate if (kobj_getvalue(input_value, &value) == -1) { 14640Sstevel@tonic-gate scsa2usb_override_error("vendor id", scsa2usbp); 14650Sstevel@tonic-gate 14660Sstevel@tonic-gate return (USB_FAILURE); 14670Sstevel@tonic-gate } 14680Sstevel@tonic-gate ovp->vid = (int)value; 14690Sstevel@tonic-gate } else if (strcasecmp(input_field, "pid") == 0) { 14700Sstevel@tonic-gate if (kobj_getvalue(input_value, &value) == -1) { 14710Sstevel@tonic-gate scsa2usb_override_error("product id", 14720Sstevel@tonic-gate scsa2usbp); 14730Sstevel@tonic-gate 14740Sstevel@tonic-gate return (USB_FAILURE); 14750Sstevel@tonic-gate } 14760Sstevel@tonic-gate ovp->pid = (int)value; 14770Sstevel@tonic-gate } else if (strcasecmp(input_field, "rev") == 0) { 14780Sstevel@tonic-gate if (kobj_getvalue(input_value, &value) == -1) { 14790Sstevel@tonic-gate scsa2usb_override_error("revision id", 14800Sstevel@tonic-gate scsa2usbp); 14810Sstevel@tonic-gate 14820Sstevel@tonic-gate return (USB_FAILURE); 14830Sstevel@tonic-gate } 14840Sstevel@tonic-gate ovp->rev = (int)value; 14850Sstevel@tonic-gate } else if (strcasecmp(input_field, "subclass") == 0) { 14860Sstevel@tonic-gate for (i = 0; i < N_SCSA2USB_SUBC_OVERRIDE; i++) { 14870Sstevel@tonic-gate if (strcasecmp(input_value, 14880Sstevel@tonic-gate scsa2usb_subclass[i].name) == 0) { 14890Sstevel@tonic-gate ovp->subclass = 14900Sstevel@tonic-gate scsa2usb_subclass[i].value; 14910Sstevel@tonic-gate break; 14920Sstevel@tonic-gate } 14930Sstevel@tonic-gate } 14940Sstevel@tonic-gate if (ovp->subclass == 0) { 14950Sstevel@tonic-gate scsa2usb_override_error("subclass", scsa2usbp); 14960Sstevel@tonic-gate 14970Sstevel@tonic-gate return (USB_FAILURE); 14980Sstevel@tonic-gate } 14990Sstevel@tonic-gate } else if (strcasecmp(input_field, "protocol") == 0) { 15000Sstevel@tonic-gate for (i = 0; i < N_SCSA2USB_PROT_OVERRIDE; i++) { 15010Sstevel@tonic-gate if (strcasecmp(input_value, 15020Sstevel@tonic-gate scsa2usb_protocol[i].name) == 0) { 15030Sstevel@tonic-gate ovp->protocol = 15040Sstevel@tonic-gate scsa2usb_protocol[i].value; 15050Sstevel@tonic-gate break; 15060Sstevel@tonic-gate } 15070Sstevel@tonic-gate } 15080Sstevel@tonic-gate if (ovp->protocol == 0) { 15090Sstevel@tonic-gate scsa2usb_override_error("protocol", scsa2usbp); 15100Sstevel@tonic-gate 15110Sstevel@tonic-gate return (USB_FAILURE); 15120Sstevel@tonic-gate } 15130Sstevel@tonic-gate } else if (strcasecmp(input_field, "pm") == 0) { 15140Sstevel@tonic-gate if (strcasecmp(input_value, "off") == 0) { 15150Sstevel@tonic-gate ovp->pmoff = 1; 15160Sstevel@tonic-gate break; 15170Sstevel@tonic-gate } else { 15180Sstevel@tonic-gate scsa2usb_override_error("pm", scsa2usbp); 15190Sstevel@tonic-gate 15200Sstevel@tonic-gate return (USB_FAILURE); 15210Sstevel@tonic-gate } 15220Sstevel@tonic-gate } else if (strcasecmp(input_field, "removable") == 0) { 15231415Scg149915 if (strcasecmp(input_value, "true") == 0) { 15241415Scg149915 ovp->fake_removable = 1; 15250Sstevel@tonic-gate break; 15260Sstevel@tonic-gate } else { 15270Sstevel@tonic-gate scsa2usb_override_error("removable", scsa2usbp); 15280Sstevel@tonic-gate 15290Sstevel@tonic-gate return (USB_FAILURE); 15300Sstevel@tonic-gate } 15310Sstevel@tonic-gate } else if (strcasecmp(input_field, "modesense") == 0) { 15320Sstevel@tonic-gate if (strcasecmp(input_value, "false") == 0) { 15330Sstevel@tonic-gate ovp->no_modesense = 1; 15340Sstevel@tonic-gate break; 15350Sstevel@tonic-gate } else { 15360Sstevel@tonic-gate scsa2usb_override_error("modesense", 15374700Sfb209375 scsa2usbp); 15380Sstevel@tonic-gate 15390Sstevel@tonic-gate return (USB_FAILURE); 15400Sstevel@tonic-gate } 15410Sstevel@tonic-gate } else if (strcasecmp(input_field, 15420Sstevel@tonic-gate "reduced-cmd-support") == 0) { 15430Sstevel@tonic-gate if (strcasecmp(input_value, "true") == 0) { 15440Sstevel@tonic-gate ovp->reduced_cmd_support = 1; 15450Sstevel@tonic-gate break; 15460Sstevel@tonic-gate } else { 15470Sstevel@tonic-gate scsa2usb_override_error( 15480Sstevel@tonic-gate "reduced-cmd-support", scsa2usbp); 15490Sstevel@tonic-gate 15500Sstevel@tonic-gate return (USB_FAILURE); 15510Sstevel@tonic-gate } 15520Sstevel@tonic-gate } else { 1553880Sfrits scsa2usb_override_error(input_field, scsa2usbp); 15540Sstevel@tonic-gate 15550Sstevel@tonic-gate return (USB_FAILURE); 15560Sstevel@tonic-gate } 15570Sstevel@tonic-gate } 15580Sstevel@tonic-gate 15590Sstevel@tonic-gate return (USB_SUCCESS); 15600Sstevel@tonic-gate } 15610Sstevel@tonic-gate 15620Sstevel@tonic-gate 15630Sstevel@tonic-gate /* 15640Sstevel@tonic-gate * scsa2usb_override_error: 15650Sstevel@tonic-gate * print an error message if conf file string is bad format 15660Sstevel@tonic-gate */ 15670Sstevel@tonic-gate static void 15680Sstevel@tonic-gate scsa2usb_override_error(char *input_field, scsa2usb_state_t *scsa2usbp) 15690Sstevel@tonic-gate { 15700Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 1571880Sfrits "invalid %s in scsa2usb.conf file entry", input_field); 15720Sstevel@tonic-gate } 15730Sstevel@tonic-gate 15740Sstevel@tonic-gate /* 15750Sstevel@tonic-gate * scsa2usb_strtok_r: 15760Sstevel@tonic-gate * parse a list of tokens 15770Sstevel@tonic-gate */ 15780Sstevel@tonic-gate static char * 15790Sstevel@tonic-gate scsa2usb_strtok_r(char *p, char *sep, char **lasts) 15800Sstevel@tonic-gate { 15810Sstevel@tonic-gate char *e; 15820Sstevel@tonic-gate char *tok = NULL; 15830Sstevel@tonic-gate 15840Sstevel@tonic-gate if (p == 0 || *p == 0) { 15850Sstevel@tonic-gate 15860Sstevel@tonic-gate return (NULL); 15870Sstevel@tonic-gate } 15880Sstevel@tonic-gate 15890Sstevel@tonic-gate e = p+strlen(p); 15900Sstevel@tonic-gate 15910Sstevel@tonic-gate do { 15920Sstevel@tonic-gate if (strchr(sep, *p) != NULL) { 15930Sstevel@tonic-gate if (tok != NULL) { 15940Sstevel@tonic-gate *p = 0; 15950Sstevel@tonic-gate *lasts = p+1; 15960Sstevel@tonic-gate 15970Sstevel@tonic-gate return (tok); 15980Sstevel@tonic-gate } 15990Sstevel@tonic-gate } else if (tok == NULL) { 16000Sstevel@tonic-gate tok = p; 16010Sstevel@tonic-gate } 16020Sstevel@tonic-gate } while (++p < e); 16030Sstevel@tonic-gate 16040Sstevel@tonic-gate *lasts = NULL; 16050Sstevel@tonic-gate 16060Sstevel@tonic-gate return (tok); 16070Sstevel@tonic-gate } 16080Sstevel@tonic-gate 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate /* 16110Sstevel@tonic-gate * scsa2usb_validate_attrs: 16120Sstevel@tonic-gate * many devices have BO/CB/CBI protocol support issues. 16130Sstevel@tonic-gate * use vendor/product info to reset the 16140Sstevel@tonic-gate * individual erroneous attributes 16150Sstevel@tonic-gate * 16160Sstevel@tonic-gate * NOTE: we look at only device at a time (at attach time) 16170Sstevel@tonic-gate */ 16180Sstevel@tonic-gate static void 16190Sstevel@tonic-gate scsa2usb_validate_attrs(scsa2usb_state_t *scsa2usbp) 16200Sstevel@tonic-gate { 16210Sstevel@tonic-gate int i, mask; 16220Sstevel@tonic-gate usb_dev_descr_t *desc = scsa2usbp->scsa2usb_dev_data->dev_descr; 16230Sstevel@tonic-gate 16240Sstevel@tonic-gate if (!SCSA2USB_IS_BULK_ONLY(scsa2usbp)) { 16250Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= ~SCSA2USB_ATTRS_GET_LUN; 16260Sstevel@tonic-gate } 16270Sstevel@tonic-gate 16280Sstevel@tonic-gate /* determine if this device is on the blacklist */ 16290Sstevel@tonic-gate for (i = 0; i < N_SCSA2USB_BLACKLIST; i++) { 16300Sstevel@tonic-gate if ((scsa2usb_blacklist[i].idVendor == desc->idVendor) && 16310Sstevel@tonic-gate ((scsa2usb_blacklist[i].idProduct == desc->idProduct) || 16320Sstevel@tonic-gate (scsa2usb_blacklist[i].idProduct == X))) { 16330Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= 16344700Sfb209375 ~(scsa2usb_blacklist[i].attributes); 16350Sstevel@tonic-gate break; 16360Sstevel@tonic-gate } 16370Sstevel@tonic-gate } 16380Sstevel@tonic-gate 16390Sstevel@tonic-gate /* 16400Sstevel@tonic-gate * Mitsumi's CD-RW drives subclass isn't UFI. 16410Sstevel@tonic-gate * But they support UFI command-set (this code ensures that) 16420Sstevel@tonic-gate * NOTE: This is a special case, and is being called out so. 16430Sstevel@tonic-gate */ 16440Sstevel@tonic-gate if (desc->idVendor == MS_MITSUMI_VID) { 16450Sstevel@tonic-gate mask = scsa2usbp->scsa2usb_cmd_protocol & SCSA2USB_CMDSET_MASK; 16460Sstevel@tonic-gate if (mask) { 16470Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol &= ~mask; 16480Sstevel@tonic-gate } 16490Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_UFI_CMDSET; 16500Sstevel@tonic-gate } 16510Sstevel@tonic-gate 16520Sstevel@tonic-gate if (scsa2usbp->scsa2usb_attrs != SCSA2USB_ALL_ATTRS) { 16530Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 16540Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 16550Sstevel@tonic-gate "scsa2usb attributes modified: 0x%x", 16560Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs); 16570Sstevel@tonic-gate } 16580Sstevel@tonic-gate } 16590Sstevel@tonic-gate 16600Sstevel@tonic-gate 16610Sstevel@tonic-gate /* 16620Sstevel@tonic-gate * scsa2usb_create_luns: 16630Sstevel@tonic-gate * check the number of luns but continue if the check fails, 16640Sstevel@tonic-gate * create child nodes for each lun 16650Sstevel@tonic-gate */ 16660Sstevel@tonic-gate static void 16670Sstevel@tonic-gate scsa2usb_create_luns(scsa2usb_state_t *scsa2usbp) 16680Sstevel@tonic-gate { 16690Sstevel@tonic-gate int lun, rval; 16700Sstevel@tonic-gate char *compatible[MAX_COMPAT_NAMES]; /* compatible names */ 16710Sstevel@tonic-gate dev_info_t *cdip; 16720Sstevel@tonic-gate uchar_t dtype; 16730Sstevel@tonic-gate char *node_name; 16740Sstevel@tonic-gate char *driver_name = NULL; 16750Sstevel@tonic-gate 16760Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 16770Sstevel@tonic-gate "scsa2usb_create_luns:"); 16780Sstevel@tonic-gate 16790Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 16800Sstevel@tonic-gate 16810Sstevel@tonic-gate /* Set n_luns to 1 by default (for floppies and other devices) */ 16820Sstevel@tonic-gate scsa2usbp->scsa2usb_n_luns = 1; 16830Sstevel@tonic-gate 16840Sstevel@tonic-gate /* 16850Sstevel@tonic-gate * Check if there are any device out there which don't 16860Sstevel@tonic-gate * support the GET_MAX_LUN command. If so, don't issue 16870Sstevel@tonic-gate * control request to them. 16880Sstevel@tonic-gate */ 16890Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_GET_LUN) == 0) { 16900Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 16910Sstevel@tonic-gate "get_max_lun cmd not supported"); 16920Sstevel@tonic-gate } else { 16930Sstevel@tonic-gate if (SCSA2USB_IS_BULK_ONLY(scsa2usbp)) { 16940Sstevel@tonic-gate scsa2usbp->scsa2usb_n_luns = 16954700Sfb209375 scsa2usb_bulk_only_get_max_lun(scsa2usbp); 16960Sstevel@tonic-gate } 16970Sstevel@tonic-gate } 16980Sstevel@tonic-gate 16990Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 17000Sstevel@tonic-gate "scsa2usb_create_luns: %d luns found", scsa2usbp->scsa2usb_n_luns); 17010Sstevel@tonic-gate 17020Sstevel@tonic-gate /* 17030Sstevel@tonic-gate * create disk child for each lun 17040Sstevel@tonic-gate */ 17050Sstevel@tonic-gate for (lun = 0; lun < scsa2usbp->scsa2usb_n_luns; lun++) { 17060Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_lun_dip[lun] == NULL); 17070Sstevel@tonic-gate 17080Sstevel@tonic-gate /* do an inquiry to get the dtype of this lun */ 17090Sstevel@tonic-gate scsa2usb_do_inquiry(scsa2usbp, 0, lun); 17100Sstevel@tonic-gate 17110Sstevel@tonic-gate dtype = scsa2usbp->scsa2usb_lun_inquiry[lun]. 17124700Sfb209375 inq_dtype & DTYPE_MASK; 17130Sstevel@tonic-gate 17140Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 17150Sstevel@tonic-gate "dtype[%d]=0x%x", lun, dtype); 17160Sstevel@tonic-gate 17170Sstevel@tonic-gate driver_name = NULL; 17180Sstevel@tonic-gate 17190Sstevel@tonic-gate switch (dtype) { 17200Sstevel@tonic-gate case DTYPE_DIRECT: 17210Sstevel@tonic-gate case DTYPE_RODIRECT: 17220Sstevel@tonic-gate case DTYPE_OPTICAL: 17230Sstevel@tonic-gate node_name = "disk"; 17240Sstevel@tonic-gate driver_name = "sd"; 17250Sstevel@tonic-gate 17260Sstevel@tonic-gate break; 17270Sstevel@tonic-gate case DTYPE_SEQUENTIAL: 17280Sstevel@tonic-gate node_name = "tape"; 17290Sstevel@tonic-gate driver_name = "st"; 17300Sstevel@tonic-gate 17310Sstevel@tonic-gate break; 17320Sstevel@tonic-gate case DTYPE_PRINTER: 17330Sstevel@tonic-gate node_name = "printer"; 17340Sstevel@tonic-gate 17350Sstevel@tonic-gate break; 17360Sstevel@tonic-gate case DTYPE_PROCESSOR: 17370Sstevel@tonic-gate node_name = "processor"; 17380Sstevel@tonic-gate 17390Sstevel@tonic-gate break; 17400Sstevel@tonic-gate case DTYPE_WORM: 17410Sstevel@tonic-gate node_name = "worm"; 17420Sstevel@tonic-gate 17430Sstevel@tonic-gate break; 17440Sstevel@tonic-gate case DTYPE_SCANNER: 17450Sstevel@tonic-gate node_name = "scanner"; 17460Sstevel@tonic-gate 17470Sstevel@tonic-gate break; 17480Sstevel@tonic-gate case DTYPE_CHANGER: 17490Sstevel@tonic-gate node_name = "changer"; 17500Sstevel@tonic-gate 17510Sstevel@tonic-gate break; 17520Sstevel@tonic-gate case DTYPE_COMM: 17530Sstevel@tonic-gate node_name = "comm"; 17540Sstevel@tonic-gate 17550Sstevel@tonic-gate break; 17560Sstevel@tonic-gate case DTYPE_ARRAY_CTRL: 17570Sstevel@tonic-gate node_name = "array_ctrl"; 17580Sstevel@tonic-gate 17590Sstevel@tonic-gate break; 17600Sstevel@tonic-gate case DTYPE_ESI: 17610Sstevel@tonic-gate node_name = "esi"; 17620Sstevel@tonic-gate driver_name = "ses"; 17630Sstevel@tonic-gate 17640Sstevel@tonic-gate break; 17650Sstevel@tonic-gate default: 17660Sstevel@tonic-gate node_name = "generic"; 17670Sstevel@tonic-gate 17680Sstevel@tonic-gate break; 17690Sstevel@tonic-gate } 17700Sstevel@tonic-gate 17710Sstevel@tonic-gate if (driver_name) { 17720Sstevel@tonic-gate compatible[0] = driver_name; 17730Sstevel@tonic-gate } 17740Sstevel@tonic-gate 17750Sstevel@tonic-gate ndi_devi_alloc_sleep(scsa2usbp->scsa2usb_dip, node_name, 1776789Sahrens (pnode_t)DEVI_SID_NODEID, &cdip); 17770Sstevel@tonic-gate 17780Sstevel@tonic-gate /* attach target & lun properties */ 17790Sstevel@tonic-gate rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "target", 0); 17800Sstevel@tonic-gate if (rval != DDI_PROP_SUCCESS) { 17810Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 17820Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 17830Sstevel@tonic-gate "ndi_prop_update_int target failed %d", rval); 17840Sstevel@tonic-gate (void) ndi_devi_free(cdip); 17850Sstevel@tonic-gate continue; 17860Sstevel@tonic-gate } 17870Sstevel@tonic-gate 17881415Scg149915 rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, 17891415Scg149915 "hotpluggable"); 17901415Scg149915 if (rval != DDI_PROP_SUCCESS) { 17911415Scg149915 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 17921415Scg149915 scsa2usbp->scsa2usb_log_handle, 17931415Scg149915 "ndi_prop_create_boolean hotpluggable failed %d", 17941415Scg149915 rval); 17951415Scg149915 ddi_prop_remove_all(cdip); 17961415Scg149915 (void) ndi_devi_free(cdip); 17971415Scg149915 continue; 17981415Scg149915 } 17991415Scg149915 /* 18001415Scg149915 * Some devices don't support LOG SENSE, so tells 18011415Scg149915 * sd driver not to send this command. 18021415Scg149915 */ 18031415Scg149915 rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, 18041415Scg149915 "pm-capable", 1); 18051415Scg149915 if (rval != DDI_PROP_SUCCESS) { 18061415Scg149915 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 18071415Scg149915 scsa2usbp->scsa2usb_log_handle, 18081415Scg149915 "ndi_prop_update_int pm-capable failed %d", rval); 18091415Scg149915 ddi_prop_remove_all(cdip); 18101415Scg149915 (void) ndi_devi_free(cdip); 18111415Scg149915 continue; 18121415Scg149915 } 18131415Scg149915 18140Sstevel@tonic-gate rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "lun", lun); 18150Sstevel@tonic-gate if (rval != DDI_PROP_SUCCESS) { 18160Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 18170Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 18180Sstevel@tonic-gate "ndi_prop_update_int lun failed %d", rval); 18190Sstevel@tonic-gate ddi_prop_remove_all(cdip); 18200Sstevel@tonic-gate (void) ndi_devi_free(cdip); 18210Sstevel@tonic-gate continue; 18220Sstevel@tonic-gate } 18230Sstevel@tonic-gate 18240Sstevel@tonic-gate if (driver_name) { 18250Sstevel@tonic-gate rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, 18260Sstevel@tonic-gate cdip, "compatible", (char **)compatible, 18270Sstevel@tonic-gate MAX_COMPAT_NAMES); 18280Sstevel@tonic-gate if (rval != DDI_PROP_SUCCESS) { 18290Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 18300Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 18310Sstevel@tonic-gate "ndi_prop_update_string_array failed %d", 18320Sstevel@tonic-gate rval); 18330Sstevel@tonic-gate ddi_prop_remove_all(cdip); 18340Sstevel@tonic-gate (void) ndi_devi_free(cdip); 18350Sstevel@tonic-gate continue; 18360Sstevel@tonic-gate } 18370Sstevel@tonic-gate } 18380Sstevel@tonic-gate 18390Sstevel@tonic-gate /* 18400Sstevel@tonic-gate * add property "usb" so we always verify that it is our child 18410Sstevel@tonic-gate */ 18420Sstevel@tonic-gate rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "usb"); 18430Sstevel@tonic-gate if (rval != DDI_PROP_SUCCESS) { 18440Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 18450Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 18460Sstevel@tonic-gate "ndi_prop_create_boolean failed %d", rval); 18470Sstevel@tonic-gate ddi_prop_remove_all(cdip); 18480Sstevel@tonic-gate (void) ndi_devi_free(cdip); 18490Sstevel@tonic-gate continue; 18500Sstevel@tonic-gate } 18510Sstevel@tonic-gate 18520Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 18530Sstevel@tonic-gate (void) ddi_initchild(scsa2usbp->scsa2usb_dip, cdip); 18540Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 18550Sstevel@tonic-gate 18560Sstevel@tonic-gate usba_set_usba_device(cdip, 18574700Sfb209375 usba_get_usba_device(scsa2usbp->scsa2usb_dip)); 18580Sstevel@tonic-gate } 18590Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 18600Sstevel@tonic-gate } 18610Sstevel@tonic-gate 18620Sstevel@tonic-gate 18630Sstevel@tonic-gate /* 18640Sstevel@tonic-gate * scsa2usb_is_usb: 18650Sstevel@tonic-gate * scsa2usb gets called for all possible sd children. 18660Sstevel@tonic-gate * we can only accept usb children 18670Sstevel@tonic-gate */ 18680Sstevel@tonic-gate static int 18690Sstevel@tonic-gate scsa2usb_is_usb(dev_info_t *dip) 18700Sstevel@tonic-gate { 18710Sstevel@tonic-gate if (dip) { 18720Sstevel@tonic-gate return (ddi_prop_exists(DDI_DEV_T_ANY, dip, 18730Sstevel@tonic-gate DDI_PROP_DONTPASS, "usb")); 18740Sstevel@tonic-gate } 18750Sstevel@tonic-gate return (0); 18760Sstevel@tonic-gate } 18770Sstevel@tonic-gate 18780Sstevel@tonic-gate 18790Sstevel@tonic-gate /* 18800Sstevel@tonic-gate * Panic Stuff 18810Sstevel@tonic-gate * scsa2usb_panic_callb_init: 18820Sstevel@tonic-gate * initialize PANIC callb and free allocated resources 18830Sstevel@tonic-gate */ 18840Sstevel@tonic-gate static void 18850Sstevel@tonic-gate scsa2usb_panic_callb_init(scsa2usb_state_t *scsa2usbp) 18860Sstevel@tonic-gate { 18870Sstevel@tonic-gate /* 18880Sstevel@tonic-gate * In case the system panics, the sync command flushes 18890Sstevel@tonic-gate * dirty FS pages or buffers. This would cause a hang 18900Sstevel@tonic-gate * in USB. 18910Sstevel@tonic-gate * The reason for the failure is that we enter 18920Sstevel@tonic-gate * polled mode (interrupts disabled) and HCD gets stuck 18930Sstevel@tonic-gate * trying to execute bulk requests 18940Sstevel@tonic-gate * The panic_callback registered below provides a warning 18950Sstevel@tonic-gate * that a panic has occurred and from that point onwards, we 18960Sstevel@tonic-gate * complete each request successfully and immediately. This 18970Sstevel@tonic-gate * will fake successful syncing so at least the rest of the 18980Sstevel@tonic-gate * filesystems complete syncing. 18990Sstevel@tonic-gate */ 19000Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info = 19014700Sfb209375 kmem_zalloc(sizeof (scsa2usb_cpr_t), KM_SLEEP); 19020Sstevel@tonic-gate mutex_init(&scsa2usbp->scsa2usb_panic_info->lockp, 19034700Sfb209375 NULL, MUTEX_DRIVER, 19044700Sfb209375 scsa2usbp->scsa2usb_dev_data->dev_iblock_cookie); 19050Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info->statep = scsa2usbp; 19060Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info->cpr.cc_lockp = 19074700Sfb209375 &scsa2usbp->scsa2usb_panic_info->lockp; 19080Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info->cpr.cc_id = 19094700Sfb209375 callb_add(scsa2usb_panic_callb, 19104700Sfb209375 (void *)scsa2usbp->scsa2usb_panic_info, 19114700Sfb209375 CB_CL_PANIC, "scsa2usb"); 19120Sstevel@tonic-gate } 19130Sstevel@tonic-gate 19140Sstevel@tonic-gate 19150Sstevel@tonic-gate /* 19160Sstevel@tonic-gate * scsa2usb_panic_callb_fini: 19170Sstevel@tonic-gate * cancel out PANIC callb and free allocated resources 19180Sstevel@tonic-gate */ 19190Sstevel@tonic-gate static void 19200Sstevel@tonic-gate scsa2usb_panic_callb_fini(scsa2usb_state_t *scsa2usbp) 19210Sstevel@tonic-gate { 19220Sstevel@tonic-gate if (scsa2usbp->scsa2usb_panic_info) { 19230Sstevel@tonic-gate SCSA2USB_CANCEL_CB(scsa2usbp->scsa2usb_panic_info->cpr.cc_id); 19240Sstevel@tonic-gate mutex_destroy(&scsa2usbp->scsa2usb_panic_info->lockp); 19250Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info->statep = NULL; 19260Sstevel@tonic-gate kmem_free(scsa2usbp->scsa2usb_panic_info, 19270Sstevel@tonic-gate sizeof (scsa2usb_cpr_t)); 19280Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info = NULL; 19290Sstevel@tonic-gate } 19300Sstevel@tonic-gate } 19310Sstevel@tonic-gate 19320Sstevel@tonic-gate 19330Sstevel@tonic-gate /* 19340Sstevel@tonic-gate * scsa2usb_panic_callb: 19350Sstevel@tonic-gate * This routine is called when there is a system panic. 19360Sstevel@tonic-gate */ 19370Sstevel@tonic-gate /* ARGSUSED */ 19380Sstevel@tonic-gate static boolean_t 19390Sstevel@tonic-gate scsa2usb_panic_callb(void *arg, int code) 19400Sstevel@tonic-gate { 19410Sstevel@tonic-gate scsa2usb_cpr_t *cpr_infop; 19420Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 19430Sstevel@tonic-gate uint_t lun; 19440Sstevel@tonic-gate 19450Sstevel@tonic-gate _NOTE(NO_COMPETING_THREADS_NOW); 19460Sstevel@tonic-gate cpr_infop = (scsa2usb_cpr_t *)arg; 19470Sstevel@tonic-gate scsa2usbp = (scsa2usb_state_t *)cpr_infop->statep; 19480Sstevel@tonic-gate 19490Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 19500Sstevel@tonic-gate "scsa2usb_panic_callb: code=%d", code); 19510Sstevel@tonic-gate 19520Sstevel@tonic-gate /* 19530Sstevel@tonic-gate * If we return error here, "sd" prints lots of error 19540Sstevel@tonic-gate * messages and could retry the same pkt over and over again. 19550Sstevel@tonic-gate * The sync recovery isn't "smooth" in that case. By faking 19560Sstevel@tonic-gate * a success return, instead, we force sync to complete. 19570Sstevel@tonic-gate */ 19580Sstevel@tonic-gate if (scsa2usbp->scsa2usb_cur_pkt) { 19590Sstevel@tonic-gate /* 19600Sstevel@tonic-gate * Do not print the "no sync" warning here. it will then be 19610Sstevel@tonic-gate * displayed before we actually start syncing. Also we don't 19620Sstevel@tonic-gate * replace this code with a call to scsa2usb_pkt_completion(). 19630Sstevel@tonic-gate * NOTE: mutexes are disabled during panic. 19640Sstevel@tonic-gate */ 19650Sstevel@tonic-gate scsa2usbp->scsa2usb_cur_pkt->pkt_reason = CMD_CMPLT; 19660Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 19670Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usbp, scsa2usbp->scsa2usb_cur_pkt); 19680Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 19690Sstevel@tonic-gate } 19700Sstevel@tonic-gate 19710Sstevel@tonic-gate /* get rid of waitQ */ 19720Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 19730Sstevel@tonic-gate scsa2usb_flush_waitQ(scsa2usbp, lun, CMD_CMPLT); 19740Sstevel@tonic-gate } 19750Sstevel@tonic-gate 19762840Scarlsonj #ifndef lint 19770Sstevel@tonic-gate _NOTE(COMPETING_THREADS_NOW); 19782840Scarlsonj #endif 19790Sstevel@tonic-gate 19800Sstevel@tonic-gate return (B_TRUE); 19810Sstevel@tonic-gate } 19820Sstevel@tonic-gate 19830Sstevel@tonic-gate /* 19840Sstevel@tonic-gate * scsa2usb_cpr_suspend 19850Sstevel@tonic-gate * determine if the device's state can be changed to SUSPENDED 19860Sstevel@tonic-gate * close pipes if there is no activity 19870Sstevel@tonic-gate */ 19880Sstevel@tonic-gate /* ARGSUSED */ 19890Sstevel@tonic-gate static int 19900Sstevel@tonic-gate scsa2usb_cpr_suspend(dev_info_t *dip) 19910Sstevel@tonic-gate { 19920Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 19930Sstevel@tonic-gate int prev_state; 19940Sstevel@tonic-gate int rval = USB_FAILURE; 19950Sstevel@tonic-gate 19960Sstevel@tonic-gate scsa2usbp = ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 19970Sstevel@tonic-gate 19980Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 19990Sstevel@tonic-gate 20000Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 20010Sstevel@tonic-gate "scsa2usb_cpr_suspend:"); 20020Sstevel@tonic-gate 20030Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 20040Sstevel@tonic-gate switch (scsa2usbp->scsa2usb_dev_state) { 20050Sstevel@tonic-gate case USB_DEV_ONLINE: 20060Sstevel@tonic-gate case USB_DEV_PWRED_DOWN: 20070Sstevel@tonic-gate case USB_DEV_DISCONNECTED: 20080Sstevel@tonic-gate prev_state = scsa2usbp->scsa2usb_dev_state; 20090Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_SUSPENDED; 20100Sstevel@tonic-gate 20110Sstevel@tonic-gate /* 20120Sstevel@tonic-gate * If the device is busy, we cannot suspend 20130Sstevel@tonic-gate */ 20140Sstevel@tonic-gate if (SCSA2USB_BUSY(scsa2usbp)) { 20150Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 20160Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 20170Sstevel@tonic-gate "scsa2usb_cpr_suspend: I/O active"); 20180Sstevel@tonic-gate 20190Sstevel@tonic-gate /* fall back to previous state */ 20200Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = prev_state; 20210Sstevel@tonic-gate } else { 20220Sstevel@tonic-gate rval = USB_SUCCESS; 20230Sstevel@tonic-gate } 20240Sstevel@tonic-gate 20250Sstevel@tonic-gate break; 20260Sstevel@tonic-gate case USB_DEV_SUSPENDED: 20270Sstevel@tonic-gate default: 20280Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 20290Sstevel@tonic-gate "scsa2usb_cpr_suspend: Illegal dev state: %d", 20300Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state); 20310Sstevel@tonic-gate 20320Sstevel@tonic-gate break; 20330Sstevel@tonic-gate } 20340Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 20350Sstevel@tonic-gate 20360Sstevel@tonic-gate if ((rval == USB_SUCCESS) && scsa2usbp->scsa2usb_ugen_hdl) { 20370Sstevel@tonic-gate rval = usb_ugen_detach(scsa2usbp->scsa2usb_ugen_hdl, 20384700Sfb209375 DDI_SUSPEND); 20390Sstevel@tonic-gate } 20400Sstevel@tonic-gate 20410Sstevel@tonic-gate return (rval); 20420Sstevel@tonic-gate } 20430Sstevel@tonic-gate 20440Sstevel@tonic-gate 20450Sstevel@tonic-gate /* 20460Sstevel@tonic-gate * scsa2usb_cpr_resume: 20470Sstevel@tonic-gate * restore device's state 20480Sstevel@tonic-gate */ 20490Sstevel@tonic-gate static void 20500Sstevel@tonic-gate scsa2usb_cpr_resume(dev_info_t *dip) 20510Sstevel@tonic-gate { 20520Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = 20530Sstevel@tonic-gate ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 20540Sstevel@tonic-gate 20550Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 20560Sstevel@tonic-gate 20570Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 20586898Sfb209375 "scsa2usb_cpr_resume: dip = 0x%p", (void *)dip); 20590Sstevel@tonic-gate 20600Sstevel@tonic-gate scsa2usb_restore_device_state(dip, scsa2usbp); 20610Sstevel@tonic-gate 20620Sstevel@tonic-gate if (scsa2usbp->scsa2usb_ugen_hdl) { 20630Sstevel@tonic-gate (void) usb_ugen_attach(scsa2usbp->scsa2usb_ugen_hdl, 20644700Sfb209375 DDI_RESUME); 20650Sstevel@tonic-gate } 20660Sstevel@tonic-gate } 20670Sstevel@tonic-gate 20680Sstevel@tonic-gate 20690Sstevel@tonic-gate /* 20700Sstevel@tonic-gate * scsa2usb_restore_device_state: 20710Sstevel@tonic-gate * - raise the device's power 20720Sstevel@tonic-gate * - reopen all the pipes 20730Sstevel@tonic-gate */ 20740Sstevel@tonic-gate static void 20750Sstevel@tonic-gate scsa2usb_restore_device_state(dev_info_t *dip, scsa2usb_state_t *scsa2usbp) 20760Sstevel@tonic-gate { 20770Sstevel@tonic-gate uint_t prev_state; 20780Sstevel@tonic-gate 20790Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 20800Sstevel@tonic-gate "scsa2usb_restore_device_state:"); 20810Sstevel@tonic-gate 20820Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 20830Sstevel@tonic-gate prev_state = scsa2usbp->scsa2usb_dev_state; 20840Sstevel@tonic-gate 20850Sstevel@tonic-gate scsa2usb_raise_power(scsa2usbp); 20860Sstevel@tonic-gate 20870Sstevel@tonic-gate ASSERT((prev_state == USB_DEV_DISCONNECTED) || 20880Sstevel@tonic-gate (prev_state == USB_DEV_SUSPENDED)); 20890Sstevel@tonic-gate 20900Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 20910Sstevel@tonic-gate 20920Sstevel@tonic-gate /* Check for the same device */ 20930Sstevel@tonic-gate if (usb_check_same_device(dip, scsa2usbp->scsa2usb_log_handle, 20940Sstevel@tonic-gate USB_LOG_L0, DPRINT_MASK_ALL, USB_CHK_ALL, NULL) != USB_SUCCESS) { 20950Sstevel@tonic-gate 20960Sstevel@tonic-gate /* change the flags to active */ 20970Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 20980Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_DISCONNECTED; 2099189Sfrits mutex_exit(&scsa2usbp->scsa2usb_mutex); 21000Sstevel@tonic-gate 21010Sstevel@tonic-gate scsa2usb_pm_idle_component(scsa2usbp); 21020Sstevel@tonic-gate 21030Sstevel@tonic-gate return; 21040Sstevel@tonic-gate } 21050Sstevel@tonic-gate 21060Sstevel@tonic-gate /* 21070Sstevel@tonic-gate * if the device had remote wakeup earlier, 21080Sstevel@tonic-gate * enable it again 21090Sstevel@tonic-gate */ 21100Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 21110Sstevel@tonic-gate if (scsa2usbp->scsa2usb_pm && 21120Sstevel@tonic-gate scsa2usbp->scsa2usb_pm->scsa2usb_wakeup_enabled) { 21130Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 21140Sstevel@tonic-gate (void) usb_handle_remote_wakeup(scsa2usbp->scsa2usb_dip, 21150Sstevel@tonic-gate USB_REMOTE_WAKEUP_ENABLE); 21160Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 21170Sstevel@tonic-gate } 21180Sstevel@tonic-gate 21190Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_ONLINE; 21200Sstevel@tonic-gate scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_NONE; 2121189Sfrits mutex_exit(&scsa2usbp->scsa2usb_mutex); 21220Sstevel@tonic-gate 21230Sstevel@tonic-gate scsa2usb_pm_idle_component(scsa2usbp); 21240Sstevel@tonic-gate } 21250Sstevel@tonic-gate 21260Sstevel@tonic-gate 21270Sstevel@tonic-gate /* 21280Sstevel@tonic-gate * SCSA entry points: 21290Sstevel@tonic-gate * 21300Sstevel@tonic-gate * scsa2usb_scsi_tgt_probe: 21310Sstevel@tonic-gate * scsa functions are exported by means of the transport table 21320Sstevel@tonic-gate * Issue a probe to get the inquiry data. 21330Sstevel@tonic-gate */ 21340Sstevel@tonic-gate /* ARGSUSED */ 21350Sstevel@tonic-gate static int 21360Sstevel@tonic-gate scsa2usb_scsi_tgt_probe(struct scsi_device *sd, int (*waitfunc)(void)) 21370Sstevel@tonic-gate { 21380Sstevel@tonic-gate scsi_hba_tran_t *tran; 21390Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 21400Sstevel@tonic-gate dev_info_t *dip = ddi_get_parent(sd->sd_dev); 21411415Scg149915 int rval; 21420Sstevel@tonic-gate 21430Sstevel@tonic-gate ASSERT(dip); 21440Sstevel@tonic-gate 21450Sstevel@tonic-gate tran = ddi_get_driver_private(dip); 21460Sstevel@tonic-gate ASSERT(tran != NULL); 21470Sstevel@tonic-gate scsa2usbp = (scsa2usb_state_t *)tran->tran_hba_private; 21480Sstevel@tonic-gate ASSERT(scsa2usbp); 21490Sstevel@tonic-gate 21500Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 21510Sstevel@tonic-gate "scsa2usb_scsi_tgt_probe:"); 21520Sstevel@tonic-gate 21530Sstevel@tonic-gate /* if device is disconnected (ie. pipes closed), fail immediately */ 21540Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 21550Sstevel@tonic-gate if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 21560Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 21570Sstevel@tonic-gate 21580Sstevel@tonic-gate return (SCSIPROBE_FAILURE); 21590Sstevel@tonic-gate } 21600Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 21610Sstevel@tonic-gate 21620Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 21636898Sfb209375 "scsa2usb_scsi_tgt_probe: scsi_device = 0x%p", (void *)sd); 21640Sstevel@tonic-gate 21650Sstevel@tonic-gate if ((rval = scsi_hba_probe(sd, waitfunc)) == SCSIPROBE_EXISTS) { 21660Sstevel@tonic-gate /* 21671415Scg149915 * respect the removable bit on all USB storage devices 21680Sstevel@tonic-gate * unless overridden by a scsa2usb.conf entry 21690Sstevel@tonic-gate */ 21700Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 21711415Scg149915 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_RMB)) { 21720Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unshared", scsi_inquiry)) 21730Sstevel@tonic-gate sd->sd_inq->inq_rmb = 1; 21740Sstevel@tonic-gate } 21750Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 21760Sstevel@tonic-gate } 21770Sstevel@tonic-gate 21780Sstevel@tonic-gate return (rval); 21790Sstevel@tonic-gate } 21800Sstevel@tonic-gate 21810Sstevel@tonic-gate 21820Sstevel@tonic-gate /* 21830Sstevel@tonic-gate * scsa2usb_scsi_tgt_init: 21840Sstevel@tonic-gate * check whether we created this child ourselves 21850Sstevel@tonic-gate */ 21860Sstevel@tonic-gate /* ARGSUSED */ 21870Sstevel@tonic-gate static int 21880Sstevel@tonic-gate scsa2usb_scsi_tgt_init(dev_info_t *dip, dev_info_t *cdip, 21890Sstevel@tonic-gate scsi_hba_tran_t *tran, struct scsi_device *sd) 21900Sstevel@tonic-gate { 21910Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *) 21924700Sfb209375 tran->tran_hba_private; 21930Sstevel@tonic-gate int lun; 21940Sstevel@tonic-gate int t_len = sizeof (lun); 21950Sstevel@tonic-gate 21960Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF, 21970Sstevel@tonic-gate DDI_PROP_DONTPASS|DDI_PROP_CANSLEEP, "lun", (caddr_t)&lun, 21980Sstevel@tonic-gate &t_len) != DDI_PROP_SUCCESS) { 21990Sstevel@tonic-gate 22000Sstevel@tonic-gate return (DDI_FAILURE); 22010Sstevel@tonic-gate } 22020Sstevel@tonic-gate 22030Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 22040Sstevel@tonic-gate "scsa2usb_scsi_tgt_init: %s, lun%d", ddi_driver_name(cdip), lun); 22050Sstevel@tonic-gate 22060Sstevel@tonic-gate /* is this a child we created? */ 22070Sstevel@tonic-gate if (scsa2usb_is_usb(cdip) == 0) { 22080Sstevel@tonic-gate 22090Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 22100Sstevel@tonic-gate "scsa2usb_scsi_tgt_init: new child %s%d", 22110Sstevel@tonic-gate ddi_driver_name(cdip), ddi_get_instance(cdip)); 22120Sstevel@tonic-gate 22130Sstevel@tonic-gate /* 22140Sstevel@tonic-gate * add property "usb" so we can always verify that it 22150Sstevel@tonic-gate * is our child 22160Sstevel@tonic-gate */ 22170Sstevel@tonic-gate if (ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "usb") != 22180Sstevel@tonic-gate DDI_PROP_SUCCESS) { 22190Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 22200Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 22210Sstevel@tonic-gate "ndi_prop_create_boolean failed"); 22220Sstevel@tonic-gate 22230Sstevel@tonic-gate return (DDI_FAILURE); 22240Sstevel@tonic-gate } 22250Sstevel@tonic-gate 22260Sstevel@tonic-gate usba_set_usba_device(cdip, 22274700Sfb209375 usba_get_usba_device(scsa2usbp->scsa2usb_dip)); 22280Sstevel@tonic-gate 22290Sstevel@tonic-gate /* 22300Sstevel@tonic-gate * we don't store this dip in scsa2usb_lun_dip, there 22310Sstevel@tonic-gate * might be multiple dips for the same device 22320Sstevel@tonic-gate */ 22330Sstevel@tonic-gate 22340Sstevel@tonic-gate return (DDI_SUCCESS); 22350Sstevel@tonic-gate } 22360Sstevel@tonic-gate 22370Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 22380Sstevel@tonic-gate if ((lun >= scsa2usbp->scsa2usb_n_luns) || 22390Sstevel@tonic-gate (scsa2usbp->scsa2usb_lun_dip[lun] != NULL)) { 22400Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 22410Sstevel@tonic-gate 22420Sstevel@tonic-gate return (DDI_FAILURE); 22430Sstevel@tonic-gate } 22440Sstevel@tonic-gate 22450Sstevel@tonic-gate scsa2usbp->scsa2usb_lun_dip[lun] = cdip; 22460Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 22470Sstevel@tonic-gate 22480Sstevel@tonic-gate return (DDI_SUCCESS); 22490Sstevel@tonic-gate } 22500Sstevel@tonic-gate 22510Sstevel@tonic-gate 22520Sstevel@tonic-gate /* 22530Sstevel@tonic-gate * scsa2usb_scsi_tgt_free: 22540Sstevel@tonic-gate */ 22550Sstevel@tonic-gate /* ARGSUSED */ 22560Sstevel@tonic-gate static void 22570Sstevel@tonic-gate scsa2usb_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *cdip, 22580Sstevel@tonic-gate scsi_hba_tran_t *tran, struct scsi_device *sd) 22590Sstevel@tonic-gate { 22600Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *) 22614700Sfb209375 tran->tran_hba_private; 22620Sstevel@tonic-gate int lun; 22630Sstevel@tonic-gate int t_len = sizeof (lun); 22640Sstevel@tonic-gate 22650Sstevel@tonic-gate /* is this our child? */ 22660Sstevel@tonic-gate if (scsa2usb_is_usb(cdip) == 0) { 22670Sstevel@tonic-gate 22680Sstevel@tonic-gate return; 22690Sstevel@tonic-gate } 22700Sstevel@tonic-gate 22710Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF, 22720Sstevel@tonic-gate DDI_PROP_DONTPASS|DDI_PROP_CANSLEEP, "lun", (caddr_t)&lun, 22730Sstevel@tonic-gate &t_len) != DDI_PROP_SUCCESS) { 22740Sstevel@tonic-gate 22750Sstevel@tonic-gate return; 22760Sstevel@tonic-gate } 22770Sstevel@tonic-gate 22780Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 22790Sstevel@tonic-gate "scsa2usb_scsi_tgt_free: %s lun%d", ddi_driver_name(cdip), lun); 22800Sstevel@tonic-gate 22810Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 22820Sstevel@tonic-gate if (lun < scsa2usbp->scsa2usb_n_luns) { 22830Sstevel@tonic-gate if (scsa2usbp->scsa2usb_lun_dip[lun] == cdip) { 22840Sstevel@tonic-gate scsa2usbp->scsa2usb_lun_dip[lun] = NULL; 22850Sstevel@tonic-gate } 22860Sstevel@tonic-gate } 22870Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 22880Sstevel@tonic-gate } 22890Sstevel@tonic-gate 22900Sstevel@tonic-gate 22910Sstevel@tonic-gate /* 22920Sstevel@tonic-gate * bus enumeration entry points 22930Sstevel@tonic-gate */ 22940Sstevel@tonic-gate static int 22950Sstevel@tonic-gate scsa2usb_scsi_bus_config(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op, 22960Sstevel@tonic-gate void *arg, dev_info_t **child) 22970Sstevel@tonic-gate { 22980Sstevel@tonic-gate int circ; 22990Sstevel@tonic-gate int rval; 23000Sstevel@tonic-gate 23010Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = 23020Sstevel@tonic-gate ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 23030Sstevel@tonic-gate 23040Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 23050Sstevel@tonic-gate 23060Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 23070Sstevel@tonic-gate "scsa2usb_scsi_bus_config: op=%d", op); 23080Sstevel@tonic-gate 23090Sstevel@tonic-gate if (scsa2usb_scsi_bus_config_debug) { 23100Sstevel@tonic-gate flag |= NDI_DEVI_DEBUG; 23110Sstevel@tonic-gate } 23120Sstevel@tonic-gate 23130Sstevel@tonic-gate ndi_devi_enter(dip, &circ); 23140Sstevel@tonic-gate /* create children if necessary */ 23150Sstevel@tonic-gate if (DEVI(dip)->devi_child == NULL) { 23160Sstevel@tonic-gate scsa2usb_create_luns(scsa2usbp); 23170Sstevel@tonic-gate } 23180Sstevel@tonic-gate 23190Sstevel@tonic-gate rval = ndi_busop_bus_config(dip, flag, op, arg, child, 0); 23200Sstevel@tonic-gate 23210Sstevel@tonic-gate ndi_devi_exit(dip, circ); 23220Sstevel@tonic-gate 23230Sstevel@tonic-gate return (rval); 23240Sstevel@tonic-gate } 23250Sstevel@tonic-gate 23260Sstevel@tonic-gate 23270Sstevel@tonic-gate static int 23280Sstevel@tonic-gate scsa2usb_scsi_bus_unconfig(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op, 23290Sstevel@tonic-gate void *arg) 23300Sstevel@tonic-gate { 23310Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = 23320Sstevel@tonic-gate ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 23330Sstevel@tonic-gate 23340Sstevel@tonic-gate int circular_count; 23350Sstevel@tonic-gate int rval = NDI_SUCCESS; 23360Sstevel@tonic-gate uint_t save_flag = flag; 23370Sstevel@tonic-gate 23380Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 23390Sstevel@tonic-gate 23400Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 23410Sstevel@tonic-gate "scsa2usb_scsi_bus_unconfig: op=%d", op); 23420Sstevel@tonic-gate 23430Sstevel@tonic-gate if (scsa2usb_scsi_bus_config_debug) { 23440Sstevel@tonic-gate flag |= NDI_DEVI_DEBUG; 23450Sstevel@tonic-gate } 23460Sstevel@tonic-gate 23470Sstevel@tonic-gate /* 23480Sstevel@tonic-gate * first offline and if offlining successful, then 23490Sstevel@tonic-gate * remove children 23500Sstevel@tonic-gate */ 23510Sstevel@tonic-gate if (op == BUS_UNCONFIG_ALL) { 23520Sstevel@tonic-gate flag &= ~(NDI_DEVI_REMOVE | NDI_UNCONFIG); 23530Sstevel@tonic-gate } 23540Sstevel@tonic-gate 23550Sstevel@tonic-gate ndi_devi_enter(dip, &circular_count); 23560Sstevel@tonic-gate rval = ndi_busop_bus_unconfig(dip, flag, op, arg); 23570Sstevel@tonic-gate 23580Sstevel@tonic-gate /* 23590Sstevel@tonic-gate * If unconfig is successful and not part of modunload 23600Sstevel@tonic-gate * daemon, attempt to remove children. 23610Sstevel@tonic-gate */ 23620Sstevel@tonic-gate if (op == BUS_UNCONFIG_ALL && rval == NDI_SUCCESS && 23630Sstevel@tonic-gate (flag & NDI_AUTODETACH) == 0) { 23640Sstevel@tonic-gate flag |= NDI_DEVI_REMOVE; 23650Sstevel@tonic-gate rval = ndi_busop_bus_unconfig(dip, flag, op, arg); 23660Sstevel@tonic-gate } 23670Sstevel@tonic-gate ndi_devi_exit(dip, circular_count); 23680Sstevel@tonic-gate 23690Sstevel@tonic-gate if ((rval != NDI_SUCCESS) && (op == BUS_UNCONFIG_ALL) && 23700Sstevel@tonic-gate (save_flag & NDI_DEVI_REMOVE)) { 23710Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 23720Sstevel@tonic-gate if (scsa2usbp->scsa2usb_warning_given != B_TRUE) { 23737231Slg150142 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 23740Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 23750Sstevel@tonic-gate "Disconnected device was busy, " 23760Sstevel@tonic-gate "please reconnect."); 23770Sstevel@tonic-gate scsa2usbp->scsa2usb_warning_given = B_TRUE; 23780Sstevel@tonic-gate } 23790Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 23800Sstevel@tonic-gate } 23810Sstevel@tonic-gate 23820Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 23830Sstevel@tonic-gate "scsa2usb_scsi_bus_unconfig: rval=%d", rval); 23840Sstevel@tonic-gate 23850Sstevel@tonic-gate return (rval); 23860Sstevel@tonic-gate } 23870Sstevel@tonic-gate 23880Sstevel@tonic-gate 23890Sstevel@tonic-gate /* 23900Sstevel@tonic-gate * scsa2usb_scsi_init_pkt: 23910Sstevel@tonic-gate * Set up the scsi_pkt for transport. Also initialize 23920Sstevel@tonic-gate * scsa2usb_cmd struct for the transport. 23930Sstevel@tonic-gate * NOTE: We do not do any DMA setup here as USBA framework 23940Sstevel@tonic-gate * does that for us. 23950Sstevel@tonic-gate */ 23960Sstevel@tonic-gate static struct scsi_pkt * 23970Sstevel@tonic-gate scsa2usb_scsi_init_pkt(struct scsi_address *ap, 23980Sstevel@tonic-gate struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen, 23990Sstevel@tonic-gate int tgtlen, int flags, int (*callback)(), caddr_t arg) 24000Sstevel@tonic-gate { 24010Sstevel@tonic-gate scsa2usb_cmd_t *cmd; 24020Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 24030Sstevel@tonic-gate struct scsi_pkt *in_pkt = pkt; 24040Sstevel@tonic-gate 24050Sstevel@tonic-gate ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC); 24060Sstevel@tonic-gate 24070Sstevel@tonic-gate scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap); 24080Sstevel@tonic-gate 24090Sstevel@tonic-gate /* Print sync message */ 24100Sstevel@tonic-gate if (ddi_in_panic()) { 24110Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 24120Sstevel@tonic-gate SCSA2USB_PRINT_SYNC_MSG(scsa2usb_sync_message, scsa2usbp); 24130Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 24140Sstevel@tonic-gate /* continue so caller will not hang or complain */ 24150Sstevel@tonic-gate } 24160Sstevel@tonic-gate 24170Sstevel@tonic-gate /* allocate a pkt, if none already allocated */ 24180Sstevel@tonic-gate if (pkt == NULL) { 24190Sstevel@tonic-gate if (statuslen < sizeof (struct scsi_arq_status)) { 24200Sstevel@tonic-gate statuslen = sizeof (struct scsi_arq_status); 24210Sstevel@tonic-gate } 24220Sstevel@tonic-gate 24230Sstevel@tonic-gate pkt = scsi_hba_pkt_alloc(scsa2usbp->scsa2usb_dip, ap, cmdlen, 24244700Sfb209375 statuslen, tgtlen, sizeof (scsa2usb_cmd_t), 24254700Sfb209375 callback, arg); 24260Sstevel@tonic-gate if (pkt == NULL) { 24270Sstevel@tonic-gate 24280Sstevel@tonic-gate return (NULL); 24290Sstevel@tonic-gate } 24300Sstevel@tonic-gate 24310Sstevel@tonic-gate cmd = PKT2CMD(pkt); 24320Sstevel@tonic-gate cmd->cmd_pkt = pkt; /* back link to pkt */ 24330Sstevel@tonic-gate cmd->cmd_scblen = statuslen; 24340Sstevel@tonic-gate cmd->cmd_cdblen = (uchar_t)cmdlen; 24350Sstevel@tonic-gate 24360Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 24370Sstevel@tonic-gate cmd->cmd_tag = scsa2usbp->scsa2usb_tag++; 24380Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 24390Sstevel@tonic-gate 24400Sstevel@tonic-gate cmd->cmd_bp = bp; 24415727Slh195018 /* 24425727Slh195018 * The buffer size of cmd->cmd_scb is constrained 24435727Slh195018 * to sizeof (struct scsi_arq_status), if the scblen 24445727Slh195018 * is bigger than that, we use pkt->pkt_scbp directly. 24455727Slh195018 */ 24465727Slh195018 if (cmd->cmd_scblen == sizeof (struct scsi_arq_status)) { 24475727Slh195018 pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb; 24485727Slh195018 } 24490Sstevel@tonic-gate 24500Sstevel@tonic-gate usba_init_list(&cmd->cmd_waitQ, (usb_opaque_t)cmd, 24514700Sfb209375 scsa2usbp->scsa2usb_dev_data->dev_iblock_cookie); 24520Sstevel@tonic-gate } else { 24530Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 24540Sstevel@tonic-gate "scsa2usb: pkt != NULL"); 24550Sstevel@tonic-gate 24560Sstevel@tonic-gate /* nothing to do */ 24570Sstevel@tonic-gate } 24580Sstevel@tonic-gate 24592506Ssl147100 if (bp && (bp->b_bcount != 0)) { 24600Sstevel@tonic-gate if ((bp_mapin_common(bp, (callback == SLEEP_FUNC) ? 24610Sstevel@tonic-gate VM_SLEEP : VM_NOSLEEP)) == NULL) { 24620Sstevel@tonic-gate if (pkt != in_pkt) { 24630Sstevel@tonic-gate scsi_hba_pkt_free(ap, pkt); 24640Sstevel@tonic-gate } 24650Sstevel@tonic-gate 24660Sstevel@tonic-gate return (NULL); 24670Sstevel@tonic-gate } 24680Sstevel@tonic-gate 24690Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 24700Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 24710Sstevel@tonic-gate "scsa2usb_scsi_init_pkt: mapped in 0x%p, addr=0x%p", 24726898Sfb209375 (void *)bp, (void *)bp->b_un.b_addr); 24730Sstevel@tonic-gate } 24740Sstevel@tonic-gate 24750Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 24760Sstevel@tonic-gate "scsa2usb_scsi_init_pkt: ap = 0x%p pkt: 0x%p\n\t" 24770Sstevel@tonic-gate "bp = 0x%p cmdlen = %x stlen = 0x%x tlen = 0x%x flags = 0x%x", 24786898Sfb209375 (void *)ap, (void *)pkt, (void *)bp, cmdlen, statuslen, 24796898Sfb209375 tgtlen, flags); 24800Sstevel@tonic-gate 24810Sstevel@tonic-gate return (pkt); 24820Sstevel@tonic-gate } 24830Sstevel@tonic-gate 24840Sstevel@tonic-gate 24850Sstevel@tonic-gate /* 24860Sstevel@tonic-gate * scsa2usb_scsi_destroy_pkt: 24870Sstevel@tonic-gate * We are done with the packet. Get rid of it. 24880Sstevel@tonic-gate */ 24890Sstevel@tonic-gate static void 24900Sstevel@tonic-gate scsa2usb_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 24910Sstevel@tonic-gate { 24920Sstevel@tonic-gate scsa2usb_cmd_t *cmd = PKT2CMD(pkt); 24930Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ADDR2SCSA2USB(ap); 24940Sstevel@tonic-gate 24950Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 24966898Sfb209375 "scsa2usb_scsi_destroy_pkt: pkt=0x%p", (void *)pkt); 24970Sstevel@tonic-gate 24980Sstevel@tonic-gate usba_destroy_list(&cmd->cmd_waitQ); 24990Sstevel@tonic-gate scsi_hba_pkt_free(ap, pkt); 25000Sstevel@tonic-gate } 25010Sstevel@tonic-gate 25020Sstevel@tonic-gate 25030Sstevel@tonic-gate /* 25040Sstevel@tonic-gate * scsa2usb_scsi_start: 25050Sstevel@tonic-gate * For each command being issued, build up the CDB 25060Sstevel@tonic-gate * and call scsi_transport to issue the command. This 25070Sstevel@tonic-gate * function is based on the assumption that USB allows 25080Sstevel@tonic-gate * a subset of SCSI commands. Other SCSI commands we fail. 25090Sstevel@tonic-gate */ 25100Sstevel@tonic-gate static int 25110Sstevel@tonic-gate scsa2usb_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 25120Sstevel@tonic-gate { 25130Sstevel@tonic-gate scsa2usb_cmd_t *cmd; 25140Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ADDR2SCSA2USB(ap); 25150Sstevel@tonic-gate uint_t lun = ap->a_lun; 25160Sstevel@tonic-gate 25170Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 25180Sstevel@tonic-gate 25190Sstevel@tonic-gate cmd = PKT2CMD(pkt); 25200Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 25210Sstevel@tonic-gate "scsa2usb_scsi_start:\n\t" 25220Sstevel@tonic-gate "bp: 0x%p ap: 0x%p pkt: 0x%p flag: 0x%x time: 0x%x\n\tcdb0: 0x%x " 25230Sstevel@tonic-gate "dev_state: 0x%x pkt_state: 0x%x flags: 0x%x pipe_state: 0x%x", 25246898Sfb209375 (void *)cmd->cmd_bp, (void *)ap, (void *)pkt, pkt->pkt_flags, 25256898Sfb209375 pkt->pkt_time, pkt->pkt_cdbp[0], scsa2usbp->scsa2usb_dev_state, 25260Sstevel@tonic-gate scsa2usbp->scsa2usb_pkt_state, scsa2usbp->scsa2usb_flags, 25270Sstevel@tonic-gate scsa2usbp->scsa2usb_pipe_state); 25280Sstevel@tonic-gate 25290Sstevel@tonic-gate if (pkt->pkt_time == 0) { 25300Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 25310Sstevel@tonic-gate "pkt submitted with 0 timeout which may cause indefinite " 25320Sstevel@tonic-gate "hangs"); 25330Sstevel@tonic-gate } 25340Sstevel@tonic-gate 25350Sstevel@tonic-gate /* 25360Sstevel@tonic-gate * if we are in panic, we are in polled mode, so we can just 25370Sstevel@tonic-gate * accept the request, drop it and return 25380Sstevel@tonic-gate * if we fail this request, the rest of the file systems do not 25390Sstevel@tonic-gate * get synced 25400Sstevel@tonic-gate */ 25410Sstevel@tonic-gate if (ddi_in_panic()) { 25420Sstevel@tonic-gate extern int do_polled_io; 25430Sstevel@tonic-gate 25440Sstevel@tonic-gate ASSERT(do_polled_io); 25450Sstevel@tonic-gate scsa2usb_prepare_pkt(scsa2usbp, pkt); 25460Sstevel@tonic-gate SCSA2USB_PRINT_SYNC_MSG(scsa2usb_sync_message, scsa2usbp); 25470Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 25480Sstevel@tonic-gate 25490Sstevel@tonic-gate return (TRAN_ACCEPT); 25500Sstevel@tonic-gate } 25510Sstevel@tonic-gate 25520Sstevel@tonic-gate /* we cannot do polling, this should not happen */ 25530Sstevel@tonic-gate if (pkt->pkt_flags & FLAG_NOINTR) { 25540Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 25550Sstevel@tonic-gate "NOINTR packet: opcode = 0%x", pkt->pkt_cdbp[0]); 25560Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 25570Sstevel@tonic-gate 25580Sstevel@tonic-gate return (TRAN_BADPKT); 25590Sstevel@tonic-gate } 25600Sstevel@tonic-gate 25610Sstevel@tonic-gate /* is there a ugen open? */ 25620Sstevel@tonic-gate if (scsa2usbp->scsa2usb_ugen_open_count) { 25630Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 25640Sstevel@tonic-gate "ugen access in progress (count=%d)", 25650Sstevel@tonic-gate scsa2usbp->scsa2usb_ugen_open_count); 25660Sstevel@tonic-gate 25670Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 25680Sstevel@tonic-gate 25690Sstevel@tonic-gate return (TRAN_BUSY); 25700Sstevel@tonic-gate } 25710Sstevel@tonic-gate 25720Sstevel@tonic-gate /* prepare packet */ 25730Sstevel@tonic-gate scsa2usb_prepare_pkt(scsa2usbp, pkt); 25740Sstevel@tonic-gate 25750Sstevel@tonic-gate /* just queue up the requests in the waitQ if below max */ 25760Sstevel@tonic-gate if (usba_list_entry_count(&scsa2usbp->scsa2usb_waitQ[lun]) > 25770Sstevel@tonic-gate SCSA2USB_MAX_REQ_PER_LUN) { 25780Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 25790Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 25800Sstevel@tonic-gate "scsa2usb_scsi_start: limit (%d) exceeded", 25810Sstevel@tonic-gate SCSA2USB_MAX_REQ_PER_LUN); 25820Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 25830Sstevel@tonic-gate 25840Sstevel@tonic-gate return (TRAN_BUSY); 25850Sstevel@tonic-gate } 25860Sstevel@tonic-gate 25870Sstevel@tonic-gate usba_add_to_list(&scsa2usbp->scsa2usb_waitQ[lun], &cmd->cmd_waitQ); 25880Sstevel@tonic-gate 2589189Sfrits USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 25906898Sfb209375 "scsa2usb_work_thread_id=0x%p, count=%d, lun=%d", 25916898Sfb209375 (void *)scsa2usbp->scsa2usb_work_thread_id, 2592189Sfrits usba_list_entry_count(&scsa2usbp->scsa2usb_waitQ[lun]), lun); 2593189Sfrits 25940Sstevel@tonic-gate /* fire up a thread to start executing the protocol */ 25950Sstevel@tonic-gate if (scsa2usbp->scsa2usb_work_thread_id == 0) { 25960Sstevel@tonic-gate if ((usb_async_req(scsa2usbp->scsa2usb_dip, 25970Sstevel@tonic-gate scsa2usb_work_thread, 25980Sstevel@tonic-gate (void *)scsa2usbp, USB_FLAGS_SLEEP)) != USB_SUCCESS) { 25990Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 26000Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 26010Sstevel@tonic-gate "no work thread started"); 26020Sstevel@tonic-gate 26030Sstevel@tonic-gate if (usba_rm_from_list( 26040Sstevel@tonic-gate &scsa2usbp->scsa2usb_waitQ[lun], 26050Sstevel@tonic-gate &cmd->cmd_waitQ) == USB_SUCCESS) { 26060Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 26070Sstevel@tonic-gate 26080Sstevel@tonic-gate return (TRAN_BUSY); 26090Sstevel@tonic-gate } else { 26100Sstevel@tonic-gate 26110Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 26120Sstevel@tonic-gate 26130Sstevel@tonic-gate return (TRAN_ACCEPT); 26140Sstevel@tonic-gate } 26150Sstevel@tonic-gate } 26160Sstevel@tonic-gate scsa2usbp->scsa2usb_work_thread_id = (kthread_t *)1; 26170Sstevel@tonic-gate } 2618189Sfrits 26190Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 26200Sstevel@tonic-gate 26210Sstevel@tonic-gate return (TRAN_ACCEPT); 26220Sstevel@tonic-gate } 26230Sstevel@tonic-gate 26240Sstevel@tonic-gate 26250Sstevel@tonic-gate /* 26260Sstevel@tonic-gate * scsa2usb_scsi_abort: 26270Sstevel@tonic-gate * Issue SCSI abort command. This function is a NOP. 26280Sstevel@tonic-gate */ 26290Sstevel@tonic-gate /* ARGSUSED */ 26300Sstevel@tonic-gate static int 26310Sstevel@tonic-gate scsa2usb_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 26320Sstevel@tonic-gate { 26330Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap); 26340Sstevel@tonic-gate 26350Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 26366898Sfb209375 "scsa2usb_scsi_abort: pkt = %p", (void *)pkt); 26370Sstevel@tonic-gate 26380Sstevel@tonic-gate /* if device is disconnected (ie. pipes closed), fail immediately */ 26390Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 26400Sstevel@tonic-gate if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 26410Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 26420Sstevel@tonic-gate 26430Sstevel@tonic-gate return (0); 26440Sstevel@tonic-gate } 26450Sstevel@tonic-gate 26460Sstevel@tonic-gate /* flush waitQ if target and lun match */ 26470Sstevel@tonic-gate if ((ap->a_target == pkt->pkt_address.a_target) && 26480Sstevel@tonic-gate (ap->a_lun == pkt->pkt_address.a_lun)) { 26490Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 26500Sstevel@tonic-gate scsa2usb_flush_waitQ(scsa2usbp, ap->a_lun, CMD_ABORTED); 26510Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 26520Sstevel@tonic-gate } 26530Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 26540Sstevel@tonic-gate 26550Sstevel@tonic-gate return (0); 26560Sstevel@tonic-gate } 26570Sstevel@tonic-gate 26580Sstevel@tonic-gate 26590Sstevel@tonic-gate /* 26600Sstevel@tonic-gate * scsa2usb_scsi_reset: 26610Sstevel@tonic-gate * device reset may turn the device into a brick and bus reset 26620Sstevel@tonic-gate * is not applicable. 26630Sstevel@tonic-gate * just flush the waitQ 26640Sstevel@tonic-gate * We return success, always. 26650Sstevel@tonic-gate */ 26660Sstevel@tonic-gate /* ARGSUSED */ 26670Sstevel@tonic-gate static int 26680Sstevel@tonic-gate scsa2usb_scsi_reset(struct scsi_address *ap, int level) 26690Sstevel@tonic-gate { 26700Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap); 26710Sstevel@tonic-gate 26720Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 26736898Sfb209375 "scsa2usb_scsi_reset: ap = 0x%p, level = %d", (void *)ap, level); 26740Sstevel@tonic-gate 26750Sstevel@tonic-gate /* flush waitQ */ 26760Sstevel@tonic-gate scsa2usb_flush_waitQ(scsa2usbp, ap->a_lun, CMD_RESET); 26770Sstevel@tonic-gate 26780Sstevel@tonic-gate return (1); 26790Sstevel@tonic-gate } 26800Sstevel@tonic-gate 26810Sstevel@tonic-gate 26820Sstevel@tonic-gate /* 26830Sstevel@tonic-gate * scsa2usb_scsi_getcap: 26840Sstevel@tonic-gate * Get SCSI capabilities. 26850Sstevel@tonic-gate */ 26860Sstevel@tonic-gate /* ARGSUSED */ 26870Sstevel@tonic-gate static int 26880Sstevel@tonic-gate scsa2usb_scsi_getcap(struct scsi_address *ap, char *cap, int whom) 26890Sstevel@tonic-gate { 26900Sstevel@tonic-gate int rval = -1; 26910Sstevel@tonic-gate uint_t cidx; 26920Sstevel@tonic-gate size_t dev_bsize_cap; 26930Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap); 26940Sstevel@tonic-gate ASSERT(scsa2usbp); 26950Sstevel@tonic-gate 26960Sstevel@tonic-gate if (cap == NULL) { 26970Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 26980Sstevel@tonic-gate "scsa2usb_scsi_getcap: invalid arg, " 26996898Sfb209375 "cap = 0x%p whom = %d", (void *)cap, whom); 27000Sstevel@tonic-gate 27010Sstevel@tonic-gate return (rval); 27020Sstevel@tonic-gate } 27030Sstevel@tonic-gate 27040Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 27050Sstevel@tonic-gate "scsa2usb_scsi_getcap: cap = %s", cap); 27060Sstevel@tonic-gate 27070Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 27080Sstevel@tonic-gate 27090Sstevel@tonic-gate /* if device is disconnected (ie. pipes closed), fail immediately */ 27100Sstevel@tonic-gate if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 27110Sstevel@tonic-gate 27120Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 27130Sstevel@tonic-gate 27140Sstevel@tonic-gate return (rval); 27150Sstevel@tonic-gate } 27160Sstevel@tonic-gate 27170Sstevel@tonic-gate cidx = scsi_hba_lookup_capstr(cap); 27180Sstevel@tonic-gate switch (cidx) { 27190Sstevel@tonic-gate case SCSI_CAP_GEOMETRY: 27207015Sbc224572 /* Just check and fail immediately if zero, rarely happens */ 27217015Sbc224572 if (scsa2usbp->scsa2usb_secsz[ap->a_lun] == 0) { 27227015Sbc224572 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 27237015Sbc224572 scsa2usbp->scsa2usb_log_handle, 27247015Sbc224572 "scsa2usb_scsi_getcap failed:" 27257015Sbc224572 "scsa2usbp->scsa2usb_secsz[ap->a_lun] == 0"); 27267015Sbc224572 mutex_exit(&scsa2usbp->scsa2usb_mutex); 27277015Sbc224572 27287015Sbc224572 return (rval); 27297015Sbc224572 } 27307015Sbc224572 27310Sstevel@tonic-gate dev_bsize_cap = scsa2usbp->scsa2usb_totalsec[ap->a_lun]; 27320Sstevel@tonic-gate 27330Sstevel@tonic-gate if (scsa2usbp->scsa2usb_secsz[ap->a_lun] > DEV_BSIZE) { 27340Sstevel@tonic-gate dev_bsize_cap *= 27350Sstevel@tonic-gate scsa2usbp->scsa2usb_secsz[ap->a_lun] / DEV_BSIZE; 27360Sstevel@tonic-gate } else if (scsa2usbp->scsa2usb_secsz[ap->a_lun] < 27370Sstevel@tonic-gate DEV_BSIZE) { 27380Sstevel@tonic-gate dev_bsize_cap /= 27390Sstevel@tonic-gate DEV_BSIZE / scsa2usbp->scsa2usb_secsz[ap->a_lun]; 27400Sstevel@tonic-gate } 27410Sstevel@tonic-gate 27420Sstevel@tonic-gate if (dev_bsize_cap < 65536 * 2 * 18) { /* < ~1GB */ 27430Sstevel@tonic-gate /* unlabeled floppy, 18k per cylinder */ 27440Sstevel@tonic-gate rval = ((2 << 16) | 18); 27450Sstevel@tonic-gate } else if (dev_bsize_cap < 65536 * 64 * 32) { /* < 64GB */ 27460Sstevel@tonic-gate /* 1024k per cylinder */ 27470Sstevel@tonic-gate rval = ((64 << 16) | 32); 27480Sstevel@tonic-gate } else if (dev_bsize_cap < 65536 * 255 * 63) { /* < ~500GB */ 27490Sstevel@tonic-gate /* ~8m per cylinder */ 27500Sstevel@tonic-gate rval = ((255 << 16) | 63); 27510Sstevel@tonic-gate } else { /* .. 8TB */ 27520Sstevel@tonic-gate /* 64m per cylinder */ 27530Sstevel@tonic-gate rval = ((512 << 16) | 256); 27540Sstevel@tonic-gate } 27550Sstevel@tonic-gate break; 27560Sstevel@tonic-gate 27570Sstevel@tonic-gate case SCSI_CAP_DMA_MAX: 27580Sstevel@tonic-gate rval = scsa2usbp->scsa2usb_max_bulk_xfer_size; 27590Sstevel@tonic-gate break; 27600Sstevel@tonic-gate case SCSI_CAP_SCSI_VERSION: 27610Sstevel@tonic-gate rval = SCSI_VERSION_2; 27620Sstevel@tonic-gate break; 27630Sstevel@tonic-gate case SCSI_CAP_INTERCONNECT_TYPE: 27640Sstevel@tonic-gate rval = INTERCONNECT_USB; 27650Sstevel@tonic-gate break; 27660Sstevel@tonic-gate case SCSI_CAP_ARQ: 27670Sstevel@tonic-gate /* FALLTHRU */ 27680Sstevel@tonic-gate case SCSI_CAP_UNTAGGED_QING: 27690Sstevel@tonic-gate rval = 1; 27700Sstevel@tonic-gate break; 27710Sstevel@tonic-gate default: 27720Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 27730Sstevel@tonic-gate "scsa2usb_scsi_getcap: unsupported cap = %s", cap); 27740Sstevel@tonic-gate break; 27750Sstevel@tonic-gate } 27760Sstevel@tonic-gate 27770Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 27780Sstevel@tonic-gate "scsa2usb_scsi_getcap: cap = %s, returned = %d", cap, rval); 27790Sstevel@tonic-gate 27800Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 27810Sstevel@tonic-gate 27820Sstevel@tonic-gate return (rval); 27830Sstevel@tonic-gate } 27840Sstevel@tonic-gate 27850Sstevel@tonic-gate 27860Sstevel@tonic-gate /* 27870Sstevel@tonic-gate * scsa2usb_scsi_setcap: 27880Sstevel@tonic-gate * Set SCSI capabilities. 27890Sstevel@tonic-gate */ 27900Sstevel@tonic-gate /* ARGSUSED */ 27910Sstevel@tonic-gate static int 27920Sstevel@tonic-gate scsa2usb_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) 27930Sstevel@tonic-gate { 27940Sstevel@tonic-gate int rval = -1; /* default is cap undefined */ 27950Sstevel@tonic-gate uint_t cidx; 27960Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap); 27970Sstevel@tonic-gate ASSERT(scsa2usbp); 27980Sstevel@tonic-gate 27990Sstevel@tonic-gate if (cap == NULL || whom == 0) { 28000Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 28010Sstevel@tonic-gate "scsa2usb_scsi_setcap: invalid arg"); 28020Sstevel@tonic-gate 28030Sstevel@tonic-gate return (rval); 28040Sstevel@tonic-gate } 28050Sstevel@tonic-gate 28060Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 28070Sstevel@tonic-gate /* if device is disconnected (ie. pipes closed), fail immediately */ 28080Sstevel@tonic-gate if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 28090Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 28100Sstevel@tonic-gate 28110Sstevel@tonic-gate return (rval); 28120Sstevel@tonic-gate } 28130Sstevel@tonic-gate 28140Sstevel@tonic-gate cidx = scsi_hba_lookup_capstr(cap); 28150Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 28160Sstevel@tonic-gate "scsa2usb_scsi_setcap: ap = 0x%p value = 0x%x whom = 0x%x " 28176898Sfb209375 "cidx = 0x%x", (void *)ap, value, whom, cidx); 28180Sstevel@tonic-gate 28190Sstevel@tonic-gate switch (cidx) { 28200Sstevel@tonic-gate case SCSI_CAP_SECTOR_SIZE: 28210Sstevel@tonic-gate if (value) { 28220Sstevel@tonic-gate scsa2usbp->scsa2usb_secsz[ap->a_lun] = value; 28230Sstevel@tonic-gate } 28240Sstevel@tonic-gate break; 28250Sstevel@tonic-gate case SCSI_CAP_TOTAL_SECTORS: 28260Sstevel@tonic-gate if (value) { 28270Sstevel@tonic-gate scsa2usbp->scsa2usb_totalsec[ap->a_lun] = value; 28280Sstevel@tonic-gate } 28290Sstevel@tonic-gate break; 28300Sstevel@tonic-gate case SCSI_CAP_ARQ: 28310Sstevel@tonic-gate rval = 1; 28320Sstevel@tonic-gate break; 28330Sstevel@tonic-gate case SCSI_CAP_DMA_MAX: 28340Sstevel@tonic-gate case SCSI_CAP_SCSI_VERSION: 28350Sstevel@tonic-gate case SCSI_CAP_INTERCONNECT_TYPE: 28360Sstevel@tonic-gate case SCSI_CAP_UNTAGGED_QING: 28370Sstevel@tonic-gate /* supported but not settable */ 28380Sstevel@tonic-gate rval = 0; 28390Sstevel@tonic-gate break; 28400Sstevel@tonic-gate default: 28410Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 28420Sstevel@tonic-gate "scsa2usb_scsi_setcap: unsupported cap = %s", cap); 28430Sstevel@tonic-gate break; 28440Sstevel@tonic-gate } 28450Sstevel@tonic-gate 28460Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 28470Sstevel@tonic-gate 28480Sstevel@tonic-gate return (rval); 28490Sstevel@tonic-gate } 28500Sstevel@tonic-gate 28510Sstevel@tonic-gate 28520Sstevel@tonic-gate /* 28530Sstevel@tonic-gate * scsa2usb - cmd and transport stuff 28540Sstevel@tonic-gate */ 28550Sstevel@tonic-gate /* 28560Sstevel@tonic-gate * scsa2usb_prepare_pkt: 28570Sstevel@tonic-gate * initialize some fields of the pkt and cmd 28580Sstevel@tonic-gate * (the pkt may have been resubmitted/retried) 28590Sstevel@tonic-gate */ 28600Sstevel@tonic-gate static void 28610Sstevel@tonic-gate scsa2usb_prepare_pkt(scsa2usb_state_t *scsa2usbp, struct scsi_pkt *pkt) 28620Sstevel@tonic-gate { 28630Sstevel@tonic-gate scsa2usb_cmd_t *cmd = PKT2CMD(pkt); 28640Sstevel@tonic-gate 28650Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 28660Sstevel@tonic-gate "scsa2usb_prepare_pkt: pkt=0x%p cdb: 0x%x (%s)", 28676898Sfb209375 (void *)pkt, pkt->pkt_cdbp[0], 28680Sstevel@tonic-gate scsi_cname(pkt->pkt_cdbp[0], scsa2usb_cmds)); 28690Sstevel@tonic-gate 28700Sstevel@tonic-gate pkt->pkt_reason = CMD_CMPLT; /* Set reason to pkt_complete */ 28710Sstevel@tonic-gate pkt->pkt_state = 0; /* Reset next three fields */ 28720Sstevel@tonic-gate pkt->pkt_statistics = 0; 28730Sstevel@tonic-gate pkt->pkt_resid = 0; 28740Sstevel@tonic-gate bzero(pkt->pkt_scbp, cmd->cmd_scblen); /* Set status to good */ 28750Sstevel@tonic-gate 28760Sstevel@tonic-gate if (cmd) { 28770Sstevel@tonic-gate cmd->cmd_timeout = pkt->pkt_time; 28780Sstevel@tonic-gate cmd->cmd_xfercount = 0; /* Reset the fields */ 28790Sstevel@tonic-gate cmd->cmd_total_xfercount = 0; 28800Sstevel@tonic-gate cmd->cmd_lba = 0; 28810Sstevel@tonic-gate cmd->cmd_done = 0; 28820Sstevel@tonic-gate cmd->cmd_dir = 0; 28830Sstevel@tonic-gate cmd->cmd_offset = 0; 28840Sstevel@tonic-gate cmd->cmd_actual_len = cmd->cmd_cdblen; 28850Sstevel@tonic-gate } 28860Sstevel@tonic-gate } 28870Sstevel@tonic-gate 28880Sstevel@tonic-gate 28890Sstevel@tonic-gate /* 28900Sstevel@tonic-gate * scsa2usb_force_invalid_request 28910Sstevel@tonic-gate */ 28920Sstevel@tonic-gate static void 28930Sstevel@tonic-gate scsa2usb_force_invalid_request(scsa2usb_state_t *scsa2usbp, 28940Sstevel@tonic-gate scsa2usb_cmd_t *cmd) 28950Sstevel@tonic-gate { 28960Sstevel@tonic-gate struct scsi_arq_status *arqp; 28970Sstevel@tonic-gate 28980Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 28996898Sfb209375 "scsa2usb_force_invalid_request: pkt = 0x%p", (void *)cmd->cmd_pkt); 29000Sstevel@tonic-gate 29010Sstevel@tonic-gate if (cmd->cmd_scblen >= sizeof (struct scsi_arq_status)) { 29020Sstevel@tonic-gate arqp = (struct scsi_arq_status *)cmd->cmd_pkt->pkt_scbp; 29030Sstevel@tonic-gate bzero(arqp, cmd->cmd_scblen); 29040Sstevel@tonic-gate 29050Sstevel@tonic-gate arqp->sts_status.sts_chk = 1; 29060Sstevel@tonic-gate arqp->sts_rqpkt_reason = CMD_CMPLT; 29070Sstevel@tonic-gate arqp->sts_rqpkt_state = STATE_XFERRED_DATA | 29080Sstevel@tonic-gate STATE_GOT_BUS | STATE_GOT_STATUS; 29090Sstevel@tonic-gate arqp->sts_sensedata.es_valid = 1; 29100Sstevel@tonic-gate arqp->sts_sensedata.es_class = 7; 29110Sstevel@tonic-gate arqp->sts_sensedata.es_key = KEY_ILLEGAL_REQUEST; 29120Sstevel@tonic-gate 29130Sstevel@tonic-gate cmd->cmd_pkt->pkt_state = STATE_ARQ_DONE | 29140Sstevel@tonic-gate STATE_GOT_BUS | STATE_GOT_BUS | STATE_GOT_BUS | 29150Sstevel@tonic-gate STATE_GOT_STATUS; 29160Sstevel@tonic-gate #ifdef DEBUG 29170Sstevel@tonic-gate { 29180Sstevel@tonic-gate uchar_t *p = (uchar_t *)(&arqp->sts_sensedata); 29190Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 29200Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 29210Sstevel@tonic-gate "cdb: %x rqsense: " 29220Sstevel@tonic-gate "%x %x %x %x %x %x %x %x %x %x " 29230Sstevel@tonic-gate "%x %x %x %x %x %x %x %x %x %x", 29240Sstevel@tonic-gate cmd->cmd_pkt->pkt_cdbp[0], 29250Sstevel@tonic-gate p[0], p[1], p[2], p[3], p[4], 29260Sstevel@tonic-gate p[5], p[6], p[7], p[8], p[9], 29270Sstevel@tonic-gate p[10], p[11], p[12], p[13], p[14], 29280Sstevel@tonic-gate p[15], p[16], p[17], p[18], p[19]); 29290Sstevel@tonic-gate } 29300Sstevel@tonic-gate #endif 29310Sstevel@tonic-gate 29320Sstevel@tonic-gate } 29330Sstevel@tonic-gate } 29340Sstevel@tonic-gate 29350Sstevel@tonic-gate 29360Sstevel@tonic-gate /* 29370Sstevel@tonic-gate * scsa2usb_cmd_transport: 29380Sstevel@tonic-gate */ 29390Sstevel@tonic-gate static int 29400Sstevel@tonic-gate scsa2usb_cmd_transport(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) 29410Sstevel@tonic-gate { 29420Sstevel@tonic-gate int rval, transport; 29430Sstevel@tonic-gate struct scsi_pkt *pkt; 29440Sstevel@tonic-gate 29450Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 29460Sstevel@tonic-gate "scsa2usb_cmd_transport: pkt: 0x%p, cur_pkt = 0x%p", 29476898Sfb209375 (void *)cmd->cmd_pkt, (void *)scsa2usbp->scsa2usb_cur_pkt); 29480Sstevel@tonic-gate 29490Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 29500Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_cur_pkt == NULL); 29510Sstevel@tonic-gate 29520Sstevel@tonic-gate pkt = scsa2usbp->scsa2usb_cur_pkt = cmd->cmd_pkt; 29530Sstevel@tonic-gate 29540Sstevel@tonic-gate /* check black-listed attrs first */ 29550Sstevel@tonic-gate if (SCSA2USB_IS_BULK_ONLY(scsa2usbp)) { 29560Sstevel@tonic-gate transport = scsa2usb_check_bulkonly_blacklist_attrs(scsa2usbp, 29574700Sfb209375 cmd, pkt->pkt_cdbp[0]); 29580Sstevel@tonic-gate } else if (SCSA2USB_IS_CB(scsa2usbp) || SCSA2USB_IS_CBI(scsa2usbp)) { 29590Sstevel@tonic-gate transport = scsa2usb_check_ufi_blacklist_attrs(scsa2usbp, 29604700Sfb209375 pkt->pkt_cdbp[0], cmd); 29610Sstevel@tonic-gate } 29620Sstevel@tonic-gate 29630Sstevel@tonic-gate /* just accept the command */ 29640Sstevel@tonic-gate if (transport == SCSA2USB_JUST_ACCEPT) { 29650Sstevel@tonic-gate SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 29660Sstevel@tonic-gate 29670Sstevel@tonic-gate return (TRAN_ACCEPT); 29680Sstevel@tonic-gate } 29690Sstevel@tonic-gate 29700Sstevel@tonic-gate /* check command set next */ 29710Sstevel@tonic-gate if (SCSA2USB_IS_SCSI_CMDSET(scsa2usbp) || 29720Sstevel@tonic-gate SCSA2USB_IS_ATAPI_CMDSET(scsa2usbp)) { 29730Sstevel@tonic-gate transport = 29740Sstevel@tonic-gate scsa2usb_handle_scsi_cmd_sub_class(scsa2usbp, cmd, pkt); 29750Sstevel@tonic-gate } else if (SCSA2USB_IS_UFI_CMDSET(scsa2usbp)) { 29760Sstevel@tonic-gate transport = 29770Sstevel@tonic-gate scsa2usb_handle_ufi_subclass_cmd(scsa2usbp, cmd, pkt); 29780Sstevel@tonic-gate } else { 29790Sstevel@tonic-gate transport = SCSA2USB_REJECT; 29800Sstevel@tonic-gate } 29810Sstevel@tonic-gate 29821984Scg149915 switch (transport) { 29831984Scg149915 case SCSA2USB_TRANSPORT: 29840Sstevel@tonic-gate if (SCSA2USB_IS_BULK_ONLY(scsa2usbp)) { 29850Sstevel@tonic-gate rval = scsa2usb_bulk_only_transport(scsa2usbp, cmd); 29860Sstevel@tonic-gate } else if (SCSA2USB_IS_CB(scsa2usbp) || 29870Sstevel@tonic-gate SCSA2USB_IS_CBI(scsa2usbp)) { 29880Sstevel@tonic-gate rval = scsa2usb_cbi_transport(scsa2usbp, cmd); 29890Sstevel@tonic-gate } else { 29900Sstevel@tonic-gate rval = TRAN_FATAL_ERROR; 29910Sstevel@tonic-gate } 29921984Scg149915 break; 29931984Scg149915 case SCSA2USB_JUST_ACCEPT: 29941984Scg149915 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 29951984Scg149915 rval = TRAN_ACCEPT; 29961984Scg149915 break; 29971984Scg149915 default: 29980Sstevel@tonic-gate rval = TRAN_FATAL_ERROR; 29990Sstevel@tonic-gate } 30000Sstevel@tonic-gate 30010Sstevel@tonic-gate return (rval); 30020Sstevel@tonic-gate } 30030Sstevel@tonic-gate 30040Sstevel@tonic-gate 30050Sstevel@tonic-gate /* 30060Sstevel@tonic-gate * scsa2usb_check_bulkonly_blacklist_attrs: 30070Sstevel@tonic-gate * validate "scsa2usb_blacklist_attrs" (see scsa2usb.h) 30080Sstevel@tonic-gate * if blacklisted attrs match accept the request 30090Sstevel@tonic-gate * attributes checked are:- 30100Sstevel@tonic-gate * SCSA2USB_ATTRS_START_STOP 30110Sstevel@tonic-gate */ 30120Sstevel@tonic-gate int 30130Sstevel@tonic-gate scsa2usb_check_bulkonly_blacklist_attrs(scsa2usb_state_t *scsa2usbp, 30140Sstevel@tonic-gate scsa2usb_cmd_t *cmd, uchar_t opcode) 30150Sstevel@tonic-gate { 3016880Sfrits struct scsi_inquiry *inq = 3017880Sfrits &scsa2usbp->scsa2usb_lun_inquiry[cmd->cmd_pkt->pkt_address.a_lun]; 3018880Sfrits 30190Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 30200Sstevel@tonic-gate "scsa2usb_check_bulkonly_blacklist_attrs: opcode = %s", 30210Sstevel@tonic-gate scsi_cname(opcode, scsa2usb_cmds)); 30220Sstevel@tonic-gate 30230Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 30240Sstevel@tonic-gate 30250Sstevel@tonic-gate /* 30260Sstevel@tonic-gate * decode and convert the packet 30270Sstevel@tonic-gate * for most cmds, we can bcopy the cdb 30280Sstevel@tonic-gate */ 30290Sstevel@tonic-gate switch (opcode) { 30300Sstevel@tonic-gate case SCMD_DOORLOCK: 30310Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_DOORLOCK)) { 30320Sstevel@tonic-gate 30330Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 30340Sstevel@tonic-gate 3035880Sfrits /* 3036880Sfrits * only lock the door for CD and DVD drives 3037880Sfrits */ 3038880Sfrits } else if ((inq->inq_dtype == DTYPE_RODIRECT) || 3039880Sfrits (inq->inq_dtype == DTYPE_OPTICAL)) { 3040880Sfrits 3041880Sfrits if (inq->inq_rmb) { 3042880Sfrits 3043880Sfrits break; 3044880Sfrits } 30450Sstevel@tonic-gate } 30460Sstevel@tonic-gate 30470Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 30480Sstevel@tonic-gate 30490Sstevel@tonic-gate case SCMD_START_STOP: 30500Sstevel@tonic-gate /* 30510Sstevel@tonic-gate * these devices don't have mechanics that spin the 30520Sstevel@tonic-gate * media up and down. So, it doesn't make much sense 30530Sstevel@tonic-gate * to issue this cmd. 30540Sstevel@tonic-gate * 30550Sstevel@tonic-gate * Furthermore, Hagiwara devices do not handle these 30560Sstevel@tonic-gate * cmds well. just accept this command as success. 30570Sstevel@tonic-gate */ 30580Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_START_STOP)) { 30590Sstevel@tonic-gate 30600Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 30610Sstevel@tonic-gate 30620Sstevel@tonic-gate } else if (cmd->cmd_pkt->pkt_cdbp[4] & LOEJECT) { 30630Sstevel@tonic-gate /* 30640Sstevel@tonic-gate * if the device is really a removable then 30650Sstevel@tonic-gate * pass it on to the device, else just accept 30660Sstevel@tonic-gate */ 3067880Sfrits if (inq->inq_rmb) { 30680Sstevel@tonic-gate 30690Sstevel@tonic-gate break; 30700Sstevel@tonic-gate } 30710Sstevel@tonic-gate 30720Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 30730Sstevel@tonic-gate 30740Sstevel@tonic-gate } else if (!scsa2usbp->scsa2usb_rcvd_not_ready) { 30750Sstevel@tonic-gate /* 30760Sstevel@tonic-gate * if we have not received a NOT READY condition, 30770Sstevel@tonic-gate * just accept since some device choke on this too. 30780Sstevel@tonic-gate * we do have to let EJECT get through though 30790Sstevel@tonic-gate */ 30800Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 30810Sstevel@tonic-gate } 30820Sstevel@tonic-gate 30830Sstevel@tonic-gate break; 30840Sstevel@tonic-gate case SCMD_INQUIRY: 30850Sstevel@tonic-gate /* 30860Sstevel@tonic-gate * Some devices do not handle the inquiry cmd well 30870Sstevel@tonic-gate * so build an inquiry and accept this command as 30880Sstevel@tonic-gate * success. 30890Sstevel@tonic-gate */ 30900Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_INQUIRY)) { 30910Sstevel@tonic-gate uchar_t evpd = 0x01; 30920Sstevel@tonic-gate 30930Sstevel@tonic-gate if (cmd->cmd_cdb[1] & evpd) { 30940Sstevel@tonic-gate 30950Sstevel@tonic-gate return (SCSA2USB_REJECT); 30960Sstevel@tonic-gate } 30970Sstevel@tonic-gate cmd->cmd_pkt->pkt_resid -= 30984700Sfb209375 scsa2usb_fake_inquiry(scsa2usbp, cmd, 30994700Sfb209375 cmd->cmd_pkt->pkt_address.a_lun); 31000Sstevel@tonic-gate cmd->cmd_pkt->pkt_state |= STATE_XFERRED_DATA; 31010Sstevel@tonic-gate 31020Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 31030Sstevel@tonic-gate } 31040Sstevel@tonic-gate break; 31050Sstevel@tonic-gate 31060Sstevel@tonic-gate /* 3107880Sfrits * Fake accepting the following Opcodes 3108880Sfrits * (as most drives don't support these) 31090Sstevel@tonic-gate * These are needed by format command. 31100Sstevel@tonic-gate */ 31110Sstevel@tonic-gate case SCMD_RESERVE: 31120Sstevel@tonic-gate case SCMD_RELEASE: 31130Sstevel@tonic-gate case SCMD_PERSISTENT_RESERVE_IN: 31140Sstevel@tonic-gate case SCMD_PERSISTENT_RESERVE_OUT: 31150Sstevel@tonic-gate 31160Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 31170Sstevel@tonic-gate 31180Sstevel@tonic-gate case SCMD_MODE_SENSE: 31190Sstevel@tonic-gate case SCMD_MODE_SELECT: 31200Sstevel@tonic-gate case SCMD_MODE_SENSE_G1: 31210Sstevel@tonic-gate case SCMD_MODE_SELECT_G1: 31220Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_MODE_SENSE)) { 31230Sstevel@tonic-gate if (cmd->cmd_bp) { 31240Sstevel@tonic-gate cmd->cmd_pkt->pkt_resid = cmd->cmd_bp-> 31254700Sfb209375 b_bcount; 31260Sstevel@tonic-gate } 31270Sstevel@tonic-gate scsa2usb_force_invalid_request(scsa2usbp, cmd); 31280Sstevel@tonic-gate 31290Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 31300Sstevel@tonic-gate } 31310Sstevel@tonic-gate 31320Sstevel@tonic-gate break; 31330Sstevel@tonic-gate default: 31340Sstevel@tonic-gate 31350Sstevel@tonic-gate break; 31360Sstevel@tonic-gate } 31370Sstevel@tonic-gate 31380Sstevel@tonic-gate return (SCSA2USB_TRANSPORT); 31390Sstevel@tonic-gate } 31400Sstevel@tonic-gate 31410Sstevel@tonic-gate 31420Sstevel@tonic-gate /* 31430Sstevel@tonic-gate * scsa2usb_handle_scsi_cmd_sub_class: 31440Sstevel@tonic-gate * prepare a scsi cmd 31450Sstevel@tonic-gate * returns SCSA2USB_TRANSPORT, SCSA2USB_REJECT, SCSA2USB_JUST_ACCEPT 31460Sstevel@tonic-gate */ 31470Sstevel@tonic-gate int 31480Sstevel@tonic-gate scsa2usb_handle_scsi_cmd_sub_class(scsa2usb_state_t *scsa2usbp, 31490Sstevel@tonic-gate scsa2usb_cmd_t *cmd, struct scsi_pkt *pkt) 31500Sstevel@tonic-gate { 31510Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 31520Sstevel@tonic-gate "scsa2usb_handle_scsi_cmd_sub_class: cmd = 0x%p pkt = 0x%p", 31536898Sfb209375 (void *)cmd, (void *)pkt); 31540Sstevel@tonic-gate 31550Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 31560Sstevel@tonic-gate 31570Sstevel@tonic-gate bzero(&cmd->cmd_cdb, SCSI_CDB_SIZE); 31580Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_OPCODE] = pkt->pkt_cdbp[0]; /* Set the opcode */ 31590Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LUN] = pkt->pkt_cdbp[1]; 31600Sstevel@tonic-gate 31610Sstevel@tonic-gate /* 31620Sstevel@tonic-gate * decode and convert the packet 31630Sstevel@tonic-gate * for most cmds, we can bcopy the cdb 31640Sstevel@tonic-gate */ 31650Sstevel@tonic-gate switch (pkt->pkt_cdbp[0]) { 31660Sstevel@tonic-gate case SCMD_FORMAT: 31670Sstevel@tonic-gate /* 31680Sstevel@tonic-gate * SCMD_FORMAT used to limit cmd->cmd_xfercount 31690Sstevel@tonic-gate * to 4 bytes, but this hangs 31700Sstevel@tonic-gate * formatting dvd media using cdrecord (that is, 31710Sstevel@tonic-gate * a SCSI FORMAT UNIT command with a parameter list > 4 bytes) 31720Sstevel@tonic-gate * (bit 4 in cdb1 is the Fmtdata bit) 31730Sstevel@tonic-gate */ 31740Sstevel@tonic-gate if ((pkt->pkt_cdbp[1] & 0x10) && cmd->cmd_bp) { 31750Sstevel@tonic-gate cmd->cmd_xfercount = cmd->cmd_bp->b_bcount; 31760Sstevel@tonic-gate } else { 31770Sstevel@tonic-gate cmd->cmd_xfercount = 4; 31780Sstevel@tonic-gate } 31790Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_OUT; 31800Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 31810Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 31820Sstevel@tonic-gate break; 31830Sstevel@tonic-gate 31840Sstevel@tonic-gate case SCMD_INQUIRY: 31850Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_IN; 31860Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 31870Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_0] = pkt->pkt_cdbp[2]; 31880Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = cmd->cmd_xfercount = 31890Sstevel@tonic-gate min(SCSA2USB_MAX_INQ_LEN, 31900Sstevel@tonic-gate cmd->cmd_bp ? cmd->cmd_bp->b_bcount : 0); 31910Sstevel@tonic-gate break; 31920Sstevel@tonic-gate 31930Sstevel@tonic-gate case SCMD_READ_CAPACITY: 31940Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_IN; 31950Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 31960Sstevel@tonic-gate cmd->cmd_xfercount = sizeof (scsa2usb_read_cap_t); 31970Sstevel@tonic-gate break; 31980Sstevel@tonic-gate 31990Sstevel@tonic-gate /* 32000Sstevel@tonic-gate * SCMD_READ/SCMD_WRITE are converted to G1 cmds 32010Sstevel@tonic-gate * (as ATAPI devices don't recognize G0 commands) 32020Sstevel@tonic-gate * 32030Sstevel@tonic-gate * SCMD_READ_LONG/SCMD_WRITE_LONG are handled in 32040Sstevel@tonic-gate * scsa2usb_rw_transport() along with other commands. 32050Sstevel@tonic-gate * 32060Sstevel@tonic-gate * USB Host Controllers cannot handle large (read/write) 32070Sstevel@tonic-gate * xfers. We split the large request to chunks of 32080Sstevel@tonic-gate * smaller ones to meet the HCD limitations. 32090Sstevel@tonic-gate */ 32100Sstevel@tonic-gate case SCMD_READ: 32110Sstevel@tonic-gate case SCMD_WRITE: 32120Sstevel@tonic-gate case SCMD_READ_G1: 32130Sstevel@tonic-gate case SCMD_WRITE_G1: 32140Sstevel@tonic-gate case SCMD_READ_G5: 32150Sstevel@tonic-gate case SCMD_WRITE_G5: 32160Sstevel@tonic-gate case SCMD_READ_LONG: 32170Sstevel@tonic-gate case SCMD_WRITE_LONG: 32180Sstevel@tonic-gate case SCMD_READ_CD: 32190Sstevel@tonic-gate switch (scsa2usbp-> 32200Sstevel@tonic-gate scsa2usb_lun_inquiry[pkt->pkt_address.a_lun]. 32210Sstevel@tonic-gate inq_dtype & DTYPE_MASK) { 32220Sstevel@tonic-gate case DTYPE_DIRECT: 32230Sstevel@tonic-gate case DTYPE_RODIRECT: 32240Sstevel@tonic-gate case DTYPE_OPTICAL: 32250Sstevel@tonic-gate return (scsa2usb_rw_transport( 32264700Sfb209375 scsa2usbp, pkt)); 32270Sstevel@tonic-gate default: 32280Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 32290Sstevel@tonic-gate if (cmd->cmd_bp) { 32300Sstevel@tonic-gate cmd->cmd_dir = 32310Sstevel@tonic-gate (cmd->cmd_bp->b_flags & B_READ) ? 32320Sstevel@tonic-gate CBW_DIR_IN : CBW_DIR_OUT; 32330Sstevel@tonic-gate cmd->cmd_xfercount = 32340Sstevel@tonic-gate cmd->cmd_bp->b_bcount; 32350Sstevel@tonic-gate } 32360Sstevel@tonic-gate break; 32370Sstevel@tonic-gate } 32380Sstevel@tonic-gate break; 32390Sstevel@tonic-gate 32400Sstevel@tonic-gate case SCMD_REQUEST_SENSE: 32410Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_IN; 32420Sstevel@tonic-gate cmd->cmd_xfercount = pkt->pkt_cdbp[4]; 32430Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = pkt->pkt_cdbp[4]; 32440Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 32450Sstevel@tonic-gate break; 32460Sstevel@tonic-gate 32470Sstevel@tonic-gate case SCMD_DOORLOCK: 32480Sstevel@tonic-gate case SCMD_START_STOP: 32490Sstevel@tonic-gate case SCMD_TEST_UNIT_READY: 32500Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 32510Sstevel@tonic-gate break; 32520Sstevel@tonic-gate 32530Sstevel@tonic-gate /* 32540Sstevel@tonic-gate * Needed by zip protocol to reset the device 32550Sstevel@tonic-gate */ 32560Sstevel@tonic-gate case SCMD_SDIAG: 32570Sstevel@tonic-gate case SCMD_REZERO_UNIT: 32580Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 32590Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 32600Sstevel@tonic-gate break; 32610Sstevel@tonic-gate 32620Sstevel@tonic-gate case SCMD_WRITE_VERIFY: 32630Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 32640Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_OUT; 32650Sstevel@tonic-gate cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8]; 32660Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 32670Sstevel@tonic-gate break; 32680Sstevel@tonic-gate 32690Sstevel@tonic-gate /* 32700Sstevel@tonic-gate * Next command does not have a SCSI equivalent as 32710Sstevel@tonic-gate * it is vendor specific. 32720Sstevel@tonic-gate * It was listed in the vendor's ATAPI Zip specs. 32730Sstevel@tonic-gate */ 32740Sstevel@tonic-gate case SCMD_READ_FORMAT_CAP: 32750Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 32760Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_IN; 32770Sstevel@tonic-gate cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8]; 32780Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 32790Sstevel@tonic-gate break; 32800Sstevel@tonic-gate case IOMEGA_CMD_CARTRIDGE_PROTECT: 32810Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_OUT; 32820Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = pkt->pkt_cdbp[4]; 32830Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] &= ~1; /* Make it even */ 32840Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LUN] = pkt->pkt_cdbp[1]; 32850Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 32860Sstevel@tonic-gate cmd->cmd_xfercount = pkt->pkt_cdbp[4]; /* Length of password */ 32870Sstevel@tonic-gate break; 32880Sstevel@tonic-gate 32892057Scg149915 /* 32902057Scg149915 * Do not convert SCMD_MODE_SENSE/SELECT to G1 cmds because 32912057Scg149915 * the mode header is different as well. USB devices don't 32922057Scg149915 * support 0x03 & 0x04 mode pages, which are already obsoleted 32932057Scg149915 * by SPC-2 specification. 32942057Scg149915 */ 32952057Scg149915 case SCMD_MODE_SENSE: 32962057Scg149915 case SCMD_MODE_SELECT: 32972057Scg149915 if ((pkt->pkt_cdbp[2] == SD_MODE_SENSE_PAGE3_CODE) || 32982057Scg149915 (pkt->pkt_cdbp[2] == SD_MODE_SENSE_PAGE4_CODE)) { 32992057Scg149915 if (cmd->cmd_bp) { 33002057Scg149915 cmd->cmd_pkt->pkt_resid = cmd->cmd_bp->b_bcount; 33012057Scg149915 } 33022057Scg149915 scsa2usb_force_invalid_request(scsa2usbp, cmd); 33032057Scg149915 return (SCSA2USB_JUST_ACCEPT); 33042057Scg149915 } 33052057Scg149915 /* FALLTHROUGH */ 33062057Scg149915 33070Sstevel@tonic-gate default: 33080Sstevel@tonic-gate /* 33090Sstevel@tonic-gate * an unknown command may be a uscsi cmd which we 33100Sstevel@tonic-gate * should let go thru without mapping 33110Sstevel@tonic-gate */ 33120Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 33130Sstevel@tonic-gate if (cmd->cmd_bp) { 33140Sstevel@tonic-gate cmd->cmd_dir = (cmd->cmd_bp->b_flags & B_READ) ? 33154700Sfb209375 CBW_DIR_IN : CBW_DIR_OUT; 33160Sstevel@tonic-gate cmd->cmd_xfercount = cmd->cmd_bp->b_bcount; 33170Sstevel@tonic-gate } 33180Sstevel@tonic-gate 33190Sstevel@tonic-gate break; 33200Sstevel@tonic-gate } /* end of switch */ 33210Sstevel@tonic-gate 33220Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 33230Sstevel@tonic-gate "scsa2usb_handle_scsi_cmd_sub_class: opcode = 0x%x count = 0x%lx", 33240Sstevel@tonic-gate pkt->pkt_cdbp[SCSA2USB_OPCODE], cmd->cmd_xfercount); 33250Sstevel@tonic-gate 33260Sstevel@tonic-gate cmd->cmd_total_xfercount = cmd->cmd_xfercount; 33270Sstevel@tonic-gate 33280Sstevel@tonic-gate return (SCSA2USB_TRANSPORT); 33290Sstevel@tonic-gate } 33300Sstevel@tonic-gate 33310Sstevel@tonic-gate 33320Sstevel@tonic-gate /* 33332506Ssl147100 * scsa2usb_do_tur is performed before READ CAPACITY command is issued. 33342506Ssl147100 * It returns media status, 0 for media ready, -1 for media not ready 33352506Ssl147100 * or other errors. 33362506Ssl147100 */ 33372506Ssl147100 static int 33382506Ssl147100 scsa2usb_do_tur(scsa2usb_state_t *scsa2usbp, struct scsi_address *ap) 33392506Ssl147100 { 33402506Ssl147100 struct scsi_pkt *pkt; 33412506Ssl147100 scsa2usb_cmd_t *turcmd; 33422506Ssl147100 int rval = -1; 33432506Ssl147100 33442506Ssl147100 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 33452506Ssl147100 "scsa2usb_do_tur:"); 33462506Ssl147100 33472506Ssl147100 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 33482506Ssl147100 33492506Ssl147100 mutex_exit(&scsa2usbp->scsa2usb_mutex); 33502506Ssl147100 if ((pkt = scsi_init_pkt(ap, NULL, NULL, CDB_GROUP0, 1, 33512506Ssl147100 PKT_PRIV_LEN, PKT_CONSISTENT, SLEEP_FUNC, NULL)) == NULL) { 33522506Ssl147100 mutex_enter(&scsa2usbp->scsa2usb_mutex); 33532506Ssl147100 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 33542506Ssl147100 scsa2usbp->scsa2usb_log_handle, 33552506Ssl147100 "scsa2usb_do_tur: init pkt failed"); 33562506Ssl147100 33572506Ssl147100 return (rval); 33582506Ssl147100 } 33592506Ssl147100 33602506Ssl147100 RQ_MAKECOM_G0(pkt, FLAG_HEAD | FLAG_NODISCON, 33612506Ssl147100 (char)SCMD_TEST_UNIT_READY, 0, 0); 33622506Ssl147100 33632506Ssl147100 pkt->pkt_comp = NULL; 33642506Ssl147100 pkt->pkt_time = PKT_DEFAULT_TIMEOUT; 33652506Ssl147100 turcmd = PKT2CMD(pkt); 33662506Ssl147100 33672506Ssl147100 mutex_enter(&scsa2usbp->scsa2usb_mutex); 33682506Ssl147100 scsa2usb_prepare_pkt(scsa2usbp, turcmd->cmd_pkt); 33692506Ssl147100 33702506Ssl147100 if (scsa2usb_cmd_transport(scsa2usbp, turcmd) != TRAN_ACCEPT) { 33712506Ssl147100 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 33722506Ssl147100 scsa2usbp->scsa2usb_log_handle, 33732506Ssl147100 "scsa2usb_do_tur: cmd transport failed, " 33742506Ssl147100 "pkt_reason=0x%x", turcmd->cmd_pkt->pkt_reason); 33752506Ssl147100 } else if (*(turcmd->cmd_pkt->pkt_scbp) != STATUS_GOOD) { 33762506Ssl147100 /* 33772506Ssl147100 * Theoretically, the sense data should be retrieved and 33782506Ssl147100 * sense key be checked when check condition happens. If 33792506Ssl147100 * the sense key is UNIT ATTENTION, TEST UNIT READY cmd 33802506Ssl147100 * needs to be sent again to clear the UNIT ATTENTION and 33812506Ssl147100 * another TUR to be sent to get the real media status. 33822506Ssl147100 * But the AMI virtual floppy device simply cannot recover 33832506Ssl147100 * from UNIT ATTENTION by re-sending a TUR cmd, so it 33842506Ssl147100 * doesn't make any difference whether to check sense key 33852506Ssl147100 * or not. Just ignore sense key checking here and assume 33862506Ssl147100 * the device is NOT READY. 33872506Ssl147100 */ 33882506Ssl147100 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 33892506Ssl147100 scsa2usbp->scsa2usb_log_handle, 33902506Ssl147100 "scsa2usb_do_tur: media not ready"); 33912506Ssl147100 } else { 33922506Ssl147100 rval = 0; 33932506Ssl147100 } 33942506Ssl147100 33952506Ssl147100 mutex_exit(&scsa2usbp->scsa2usb_mutex); 33962506Ssl147100 scsi_destroy_pkt(pkt); 33972506Ssl147100 mutex_enter(&scsa2usbp->scsa2usb_mutex); 33982506Ssl147100 33992506Ssl147100 return (rval); 34002506Ssl147100 } 34012506Ssl147100 34022506Ssl147100 34032506Ssl147100 /* 34040Sstevel@tonic-gate * scsa2usb_check_ufi_blacklist_attrs: 34050Sstevel@tonic-gate * validate "scsa2usb_blacklist_attrs" (see scsa2usb.h) 34060Sstevel@tonic-gate * if blacklisted attrs match accept the request 34070Sstevel@tonic-gate * attributes checked are:- 34080Sstevel@tonic-gate * SCSA2USB_ATTRS_GET_CONF 34090Sstevel@tonic-gate * SCSA2USB_ATTRS_GET_PERF 34100Sstevel@tonic-gate * SCSA2USB_ATTRS_GET_START_STOP 34110Sstevel@tonic-gate */ 34120Sstevel@tonic-gate static int 34130Sstevel@tonic-gate scsa2usb_check_ufi_blacklist_attrs(scsa2usb_state_t *scsa2usbp, uchar_t opcode, 34140Sstevel@tonic-gate scsa2usb_cmd_t *cmd) 34150Sstevel@tonic-gate { 34160Sstevel@tonic-gate int rval = SCSA2USB_TRANSPORT; 34170Sstevel@tonic-gate 34180Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 34190Sstevel@tonic-gate 34200Sstevel@tonic-gate switch (opcode) { 34210Sstevel@tonic-gate case SCMD_PRIN: 34220Sstevel@tonic-gate case SCMD_PROUT: 34230Sstevel@tonic-gate rval = SCSA2USB_JUST_ACCEPT; 34240Sstevel@tonic-gate break; 34250Sstevel@tonic-gate case SCMD_MODE_SENSE: 34260Sstevel@tonic-gate case SCMD_MODE_SELECT: 34270Sstevel@tonic-gate if (cmd->cmd_bp) { 34280Sstevel@tonic-gate cmd->cmd_pkt->pkt_resid = cmd->cmd_bp->b_bcount; 34290Sstevel@tonic-gate } 34300Sstevel@tonic-gate scsa2usb_force_invalid_request(scsa2usbp, cmd); 34310Sstevel@tonic-gate rval = SCSA2USB_JUST_ACCEPT; 34320Sstevel@tonic-gate break; 34330Sstevel@tonic-gate case SCMD_GET_CONFIGURATION: 34340Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_GET_CONF)) { 34350Sstevel@tonic-gate rval = SCSA2USB_JUST_ACCEPT; 34360Sstevel@tonic-gate } 34370Sstevel@tonic-gate break; 34380Sstevel@tonic-gate case SCMD_GET_PERFORMANCE: 34390Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_GET_PERF)) { 34400Sstevel@tonic-gate rval = SCSA2USB_JUST_ACCEPT; 34410Sstevel@tonic-gate } 34420Sstevel@tonic-gate break; 34430Sstevel@tonic-gate case SCMD_START_STOP: 34440Sstevel@tonic-gate /* 34450Sstevel@tonic-gate * some CB/CBI devices don't have mechanics that spin the 34460Sstevel@tonic-gate * media up and down. So, it doesn't make much sense 34470Sstevel@tonic-gate * to issue this cmd to those devices. 34480Sstevel@tonic-gate */ 34490Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_START_STOP)) { 34500Sstevel@tonic-gate rval = SCSA2USB_JUST_ACCEPT; 34510Sstevel@tonic-gate } 34520Sstevel@tonic-gate break; 34532506Ssl147100 case SCMD_READ_CAPACITY: 34542506Ssl147100 /* 34552506Ssl147100 * Some devices don't support READ CAPACITY command 34562506Ssl147100 * when media is not ready. Need to check media status 34572506Ssl147100 * before issuing the cmd to such device. 34582506Ssl147100 */ 34592506Ssl147100 if (!(scsa2usbp->scsa2usb_attrs & 34602506Ssl147100 SCSA2USB_ATTRS_NO_MEDIA_CHECK)) { 34612506Ssl147100 struct scsi_pkt *pkt = cmd->cmd_pkt; 34622506Ssl147100 34632506Ssl147100 ASSERT(scsa2usbp->scsa2usb_cur_pkt == pkt); 34642506Ssl147100 scsa2usbp->scsa2usb_cur_pkt = NULL; 34652506Ssl147100 34662506Ssl147100 if (scsa2usb_do_tur(scsa2usbp, 34672506Ssl147100 &pkt->pkt_address) != 0) { 34682506Ssl147100 /* media not ready, force cmd invalid */ 34692506Ssl147100 if (cmd->cmd_bp) { 34702506Ssl147100 cmd->cmd_pkt->pkt_resid = 34712506Ssl147100 cmd->cmd_bp->b_bcount; 34722506Ssl147100 } 34732506Ssl147100 scsa2usb_force_invalid_request(scsa2usbp, cmd); 34742506Ssl147100 rval = SCSA2USB_JUST_ACCEPT; 34752506Ssl147100 } 34762506Ssl147100 34772506Ssl147100 scsa2usbp->scsa2usb_cur_pkt = pkt; 34782506Ssl147100 } 34792506Ssl147100 break; 34800Sstevel@tonic-gate default: 34810Sstevel@tonic-gate break; 34820Sstevel@tonic-gate } 34830Sstevel@tonic-gate 34840Sstevel@tonic-gate return (rval); 34850Sstevel@tonic-gate } 34860Sstevel@tonic-gate 34870Sstevel@tonic-gate 34880Sstevel@tonic-gate /* 34890Sstevel@tonic-gate * scsa2usb_handle_ufi_subclass_cmd: 34900Sstevel@tonic-gate * prepare a UFI cmd 34910Sstevel@tonic-gate * returns SCSA2USB_TRANSPORT, SCSA2USB_REJECT 34920Sstevel@tonic-gate */ 34930Sstevel@tonic-gate int 34940Sstevel@tonic-gate scsa2usb_handle_ufi_subclass_cmd(scsa2usb_state_t *scsa2usbp, 34950Sstevel@tonic-gate scsa2usb_cmd_t *cmd, struct scsi_pkt *pkt) 34960Sstevel@tonic-gate { 34970Sstevel@tonic-gate uchar_t opcode = pkt->pkt_cdbp[0]; 34980Sstevel@tonic-gate 34990Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 35000Sstevel@tonic-gate "scsa2usb_handle_ufi_subclass_cmd: cmd = 0x%p pkt = 0x%p", 35016898Sfb209375 (void *)cmd, (void *)pkt); 35020Sstevel@tonic-gate 35030Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 35040Sstevel@tonic-gate 35050Sstevel@tonic-gate bzero(&cmd->cmd_cdb, SCSI_CDB_SIZE); 35060Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_OPCODE] = opcode; /* Set the opcode */ 35070Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LUN] = pkt->pkt_cdbp[1]; 35080Sstevel@tonic-gate 35090Sstevel@tonic-gate /* 35100Sstevel@tonic-gate * decode and convert the packet if necessary 35110Sstevel@tonic-gate * for most cmds, we can bcopy the cdb 35120Sstevel@tonic-gate */ 35130Sstevel@tonic-gate switch (opcode) { 35140Sstevel@tonic-gate case SCMD_FORMAT: 35150Sstevel@tonic-gate /* if parameter list is specified */ 35160Sstevel@tonic-gate if (pkt->pkt_cdbp[1] & 0x10) { 35170Sstevel@tonic-gate cmd->cmd_xfercount = 35184700Sfb209375 (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8]; 35190Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_OUT; 35200Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP5; 35210Sstevel@tonic-gate } 35220Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 35230Sstevel@tonic-gate break; 35240Sstevel@tonic-gate case SCMD_INQUIRY: 35250Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_IN; 35260Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 35270Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_0] = pkt->pkt_cdbp[2]; 35280Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = cmd->cmd_xfercount = 35290Sstevel@tonic-gate min(SCSA2USB_MAX_INQ_LEN, 35300Sstevel@tonic-gate cmd->cmd_bp ? cmd->cmd_bp->b_bcount : 0); 35310Sstevel@tonic-gate break; 35320Sstevel@tonic-gate case SCMD_READ_CAPACITY: 35330Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_IN; 35340Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 35350Sstevel@tonic-gate cmd->cmd_xfercount = sizeof (scsa2usb_read_cap_t); 35360Sstevel@tonic-gate break; 35370Sstevel@tonic-gate case SCMD_REQUEST_SENSE: 35380Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_IN; 35390Sstevel@tonic-gate cmd->cmd_xfercount = pkt->pkt_cdbp[4]; 35400Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = pkt->pkt_cdbp[4]; 35410Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 35420Sstevel@tonic-gate break; 35430Sstevel@tonic-gate 35440Sstevel@tonic-gate /* 35450Sstevel@tonic-gate * do not convert SCMD_MODE_SENSE/SELECT because the 35460Sstevel@tonic-gate * mode header is different as well 35470Sstevel@tonic-gate */ 35480Sstevel@tonic-gate 35490Sstevel@tonic-gate /* 35500Sstevel@tonic-gate * see usb_bulkonly.c for comments on the next set of commands 35510Sstevel@tonic-gate */ 35520Sstevel@tonic-gate case SCMD_READ: 35530Sstevel@tonic-gate case SCMD_WRITE: 35540Sstevel@tonic-gate case SCMD_READ_G1: 35550Sstevel@tonic-gate case SCMD_WRITE_G1: 35560Sstevel@tonic-gate case SCMD_READ_G5: 35570Sstevel@tonic-gate case SCMD_WRITE_G5: 35580Sstevel@tonic-gate case SCMD_READ_LONG: 35590Sstevel@tonic-gate case SCMD_WRITE_LONG: 35600Sstevel@tonic-gate case SCMD_READ_CD: 35610Sstevel@tonic-gate 35620Sstevel@tonic-gate return (scsa2usb_rw_transport(scsa2usbp, pkt)); 35630Sstevel@tonic-gate 35640Sstevel@tonic-gate case SCMD_TEST_UNIT_READY: 35650Sstevel@tonic-gate /* 35660Sstevel@tonic-gate * Some CB/CBI devices may not support TUR. 35670Sstevel@tonic-gate */ 35680Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 35690Sstevel@tonic-gate break; 35700Sstevel@tonic-gate case SCMD_READ_FORMAT_CAP: 35710Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 35720Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_IN; 35730Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 35740Sstevel@tonic-gate cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8]; 35750Sstevel@tonic-gate break; 35760Sstevel@tonic-gate case SCMD_WRITE_VERIFY: 35770Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 35780Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_OUT; 35790Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 35800Sstevel@tonic-gate cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8]; 35810Sstevel@tonic-gate break; 35820Sstevel@tonic-gate case SCMD_START_STOP: 35830Sstevel@tonic-gate /* A larger timeout is needed for 'flaky' CD-RW devices */ 35840Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_BIG_TIMEOUT)) { 35850Sstevel@tonic-gate cmd->cmd_timeout = max(cmd->cmd_timeout, 35864700Sfb209375 20 * SCSA2USB_BULK_PIPE_TIMEOUT); 35870Sstevel@tonic-gate } 35880Sstevel@tonic-gate /* FALLTHRU */ 35890Sstevel@tonic-gate default: 35900Sstevel@tonic-gate /* 35910Sstevel@tonic-gate * all other commands don't need special mapping 35920Sstevel@tonic-gate */ 35930Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 35940Sstevel@tonic-gate if (cmd->cmd_bp) { 35950Sstevel@tonic-gate cmd->cmd_dir = (cmd->cmd_bp->b_flags & B_READ) ? 35964700Sfb209375 CBW_DIR_IN : CBW_DIR_OUT; 35970Sstevel@tonic-gate cmd->cmd_xfercount = cmd->cmd_bp->b_bcount; 35980Sstevel@tonic-gate } 35990Sstevel@tonic-gate break; 36000Sstevel@tonic-gate 36010Sstevel@tonic-gate } /* end of switch */ 36020Sstevel@tonic-gate 36030Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 36040Sstevel@tonic-gate "scsa2usb_handle_ufi_subclass_cmd: opcode = 0x%x count = 0x%lx", 36050Sstevel@tonic-gate opcode, cmd->cmd_xfercount); 36060Sstevel@tonic-gate 36070Sstevel@tonic-gate cmd->cmd_total_xfercount = cmd->cmd_xfercount; 36080Sstevel@tonic-gate 36090Sstevel@tonic-gate return (SCSA2USB_TRANSPORT); 36100Sstevel@tonic-gate } 36110Sstevel@tonic-gate 36120Sstevel@tonic-gate 36130Sstevel@tonic-gate /* 36140Sstevel@tonic-gate * scsa2usb_rw_transport: 36150Sstevel@tonic-gate * Handle splitting READ and WRITE requests to the 36160Sstevel@tonic-gate * device to a size that the host controller allows. 36170Sstevel@tonic-gate * 36180Sstevel@tonic-gate * returns TRAN_* values and not USB_SUCCESS/FAILURE 36190Sstevel@tonic-gate * 36200Sstevel@tonic-gate * To support CD-R/CD-RW/DVD media, we need to support a 36210Sstevel@tonic-gate * variety of block sizes for the different types of CD 36220Sstevel@tonic-gate * data (audio, data, video, CD-XA, yellowbook, redbook etc.) 36230Sstevel@tonic-gate * 36240Sstevel@tonic-gate * Some of the block sizes used are:- 512, 1k, 2k, 2056, 2336 36250Sstevel@tonic-gate * 2340, 2352, 2368, 2448, 2646, 2647 etc. 36260Sstevel@tonic-gate * 36270Sstevel@tonic-gate * NOTE: the driver could be entertaining a SCSI CDB that uses 36280Sstevel@tonic-gate * any of the above listed block sizes at a given time, and a 36290Sstevel@tonic-gate * totally different block size at any other given time for a 36300Sstevel@tonic-gate * different CDB. 36310Sstevel@tonic-gate * 36320Sstevel@tonic-gate * We need to compute block size every time and figure out 36330Sstevel@tonic-gate * matching LBA and LEN accordingly. 36340Sstevel@tonic-gate * 36350Sstevel@tonic-gate * Also UHCI has a limitation that it can only xfer 32k at a 36360Sstevel@tonic-gate * given time. So, with "odd" sized blocks and a limitation of 36370Sstevel@tonic-gate * how much we can xfer per shot, we need to compute xfer_count 36380Sstevel@tonic-gate * as well each time. 36390Sstevel@tonic-gate * 36400Sstevel@tonic-gate * The same computation is also done in the function 36410Sstevel@tonic-gate * scsa2usb_setup_next_xfer(). To save computing block_size in 36420Sstevel@tonic-gate * this function, I am saving block_size in "cmd" now. 36430Sstevel@tonic-gate */ 36440Sstevel@tonic-gate int 36450Sstevel@tonic-gate scsa2usb_rw_transport(scsa2usb_state_t *scsa2usbp, struct scsi_pkt *pkt) 36460Sstevel@tonic-gate { 36470Sstevel@tonic-gate scsa2usb_cmd_t *cmd = PKT2CMD(pkt); 36480Sstevel@tonic-gate int lba, dir, opcode; 36490Sstevel@tonic-gate struct buf *bp = cmd->cmd_bp; 36500Sstevel@tonic-gate size_t len, xfer_count; 36510Sstevel@tonic-gate size_t blk_size; /* calculate the block size to be used */ 36520Sstevel@tonic-gate int sz; 36530Sstevel@tonic-gate 36540Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 36550Sstevel@tonic-gate "scsa2usb_rw_transport:"); 36560Sstevel@tonic-gate 36570Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 36580Sstevel@tonic-gate 36590Sstevel@tonic-gate opcode = pkt->pkt_cdbp[0]; 36600Sstevel@tonic-gate blk_size = scsa2usbp->scsa2usb_lbasize[pkt->pkt_address.a_lun]; 36610Sstevel@tonic-gate /* set to default */ 36620Sstevel@tonic-gate 36630Sstevel@tonic-gate switch (opcode) { 36640Sstevel@tonic-gate case SCMD_READ: 36650Sstevel@tonic-gate /* 36660Sstevel@tonic-gate * Note that READ/WRITE(6) are not supported by the drive. 36670Sstevel@tonic-gate * convert it into a 10 byte read/write. 36680Sstevel@tonic-gate */ 36690Sstevel@tonic-gate lba = SCSA2USB_LBA_6BYTE(pkt); 36700Sstevel@tonic-gate len = SCSA2USB_LEN_6BYTE(pkt); 36710Sstevel@tonic-gate opcode = SCMD_READ_G1; /* Overwrite it w/ byte 10 cmd val */ 36720Sstevel@tonic-gate dir = USB_EP_DIR_IN; 36730Sstevel@tonic-gate break; 36740Sstevel@tonic-gate case SCMD_WRITE: 36750Sstevel@tonic-gate lba = SCSA2USB_LBA_6BYTE(pkt); 36760Sstevel@tonic-gate len = SCSA2USB_LEN_6BYTE(pkt); 36770Sstevel@tonic-gate opcode = SCMD_WRITE_G1; /* Overwrite it w/ byte 10 cmd val */ 36780Sstevel@tonic-gate dir = USB_EP_DIR_OUT; 36790Sstevel@tonic-gate break; 36800Sstevel@tonic-gate case SCMD_READ_G1: 36810Sstevel@tonic-gate case SCMD_READ_LONG: 36820Sstevel@tonic-gate lba = SCSA2USB_LBA_10BYTE(pkt); 36830Sstevel@tonic-gate len = SCSA2USB_LEN_10BYTE(pkt); 36840Sstevel@tonic-gate dir = USB_EP_DIR_IN; 36850Sstevel@tonic-gate break; 36860Sstevel@tonic-gate case SCMD_WRITE_G1: 36870Sstevel@tonic-gate case SCMD_WRITE_LONG: 36880Sstevel@tonic-gate lba = SCSA2USB_LBA_10BYTE(pkt); 36890Sstevel@tonic-gate len = SCSA2USB_LEN_10BYTE(pkt); 36900Sstevel@tonic-gate dir = USB_EP_DIR_OUT; 36910Sstevel@tonic-gate if (len) { 36920Sstevel@tonic-gate sz = SCSA2USB_CDRW_BLKSZ(bp ? bp->b_bcount : 0, len); 36930Sstevel@tonic-gate if (SCSA2USB_VALID_CDRW_BLKSZ(sz)) { 36940Sstevel@tonic-gate blk_size = sz; /* change it accordingly */ 36950Sstevel@tonic-gate } 36960Sstevel@tonic-gate } 36970Sstevel@tonic-gate break; 36980Sstevel@tonic-gate case SCMD_READ_CD: 36990Sstevel@tonic-gate lba = SCSA2USB_LBA_10BYTE(pkt); 37000Sstevel@tonic-gate len = SCSA2USB_LEN_READ_CD(pkt); 37010Sstevel@tonic-gate dir = USB_EP_DIR_IN; 37020Sstevel@tonic-gate 37030Sstevel@tonic-gate /* Figure out the block size */ 37040Sstevel@tonic-gate blk_size = scsa2usb_read_cd_blk_size(pkt->pkt_cdbp[1] >> 2); 37050Sstevel@tonic-gate break; 37060Sstevel@tonic-gate case SCMD_READ_G5: 37070Sstevel@tonic-gate lba = SCSA2USB_LBA_12BYTE(pkt); 37080Sstevel@tonic-gate len = SCSA2USB_LEN_12BYTE(pkt); 37090Sstevel@tonic-gate dir = USB_EP_DIR_IN; 37100Sstevel@tonic-gate break; 37110Sstevel@tonic-gate case SCMD_WRITE_G5: 37120Sstevel@tonic-gate lba = SCSA2USB_LBA_12BYTE(pkt); 37130Sstevel@tonic-gate len = SCSA2USB_LEN_12BYTE(pkt); 37140Sstevel@tonic-gate dir = USB_EP_DIR_OUT; 37150Sstevel@tonic-gate break; 37160Sstevel@tonic-gate } 37170Sstevel@tonic-gate 37180Sstevel@tonic-gate cmd->cmd_total_xfercount = xfer_count = len * blk_size; 37190Sstevel@tonic-gate 37200Sstevel@tonic-gate /* reduce xfer count if necessary */ 37210Sstevel@tonic-gate if (blk_size && 37220Sstevel@tonic-gate (xfer_count > scsa2usbp->scsa2usb_max_bulk_xfer_size)) { 37230Sstevel@tonic-gate /* 37240Sstevel@tonic-gate * For CD-RW devices reduce the xfer count based 37250Sstevel@tonic-gate * on the block size used by these devices. The 37260Sstevel@tonic-gate * block size could change for READ_CD and WRITE 37270Sstevel@tonic-gate * opcodes. 37280Sstevel@tonic-gate * 37290Sstevel@tonic-gate * Also as UHCI allows a max xfer of 32k at a time; 37300Sstevel@tonic-gate * compute the xfer_count based on the new block_size. 37310Sstevel@tonic-gate * 37320Sstevel@tonic-gate * The len part of the cdb changes as a result of that. 37330Sstevel@tonic-gate */ 37340Sstevel@tonic-gate if (SCSA2USB_VALID_CDRW_BLKSZ(blk_size)) { 37350Sstevel@tonic-gate xfer_count = ((scsa2usbp->scsa2usb_max_bulk_xfer_size/ 37364700Sfb209375 blk_size) * blk_size); 37370Sstevel@tonic-gate len = xfer_count/blk_size; 37380Sstevel@tonic-gate xfer_count = blk_size * len; 37390Sstevel@tonic-gate } else { 37400Sstevel@tonic-gate xfer_count = scsa2usbp->scsa2usb_max_bulk_xfer_size; 37410Sstevel@tonic-gate len = xfer_count/blk_size; 37420Sstevel@tonic-gate } 37430Sstevel@tonic-gate } 37440Sstevel@tonic-gate 37450Sstevel@tonic-gate cmd->cmd_xfercount = xfer_count; 37460Sstevel@tonic-gate cmd->cmd_dir = (uchar_t)dir; 3747*7492SZhigang.Lu@Sun.COM cmd->cmd_blksize = (int)blk_size; 37480Sstevel@tonic-gate 37490Sstevel@tonic-gate /* 37500Sstevel@tonic-gate * Having figure out the 'partial' xfer len based on he 37510Sstevel@tonic-gate * block size; fill it in to the cmd->cmd_cdb 37520Sstevel@tonic-gate */ 37530Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_OPCODE] = (uchar_t)opcode; 37540Sstevel@tonic-gate switch (opcode) { 37550Sstevel@tonic-gate case SCMD_READ_CD: 37560Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 37570Sstevel@tonic-gate scsa2usb_fill_up_ReadCD_cdb_len(cmd, len, CDB_GROUP5); 37580Sstevel@tonic-gate break; 37590Sstevel@tonic-gate case SCMD_WRITE_G5: 37600Sstevel@tonic-gate case SCMD_READ_G5: 37610Sstevel@tonic-gate scsa2usb_fill_up_12byte_cdb_len(cmd, len, CDB_GROUP5); 37620Sstevel@tonic-gate break; 37630Sstevel@tonic-gate default: 37640Sstevel@tonic-gate scsa2usb_fill_up_cdb_len(cmd, len); 37650Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 37660Sstevel@tonic-gate break; 37670Sstevel@tonic-gate } 37680Sstevel@tonic-gate 37690Sstevel@tonic-gate scsa2usb_fill_up_cdb_lba(cmd, lba); 37700Sstevel@tonic-gate 37710Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 37720Sstevel@tonic-gate "bcount=0x%lx lba=0x%x len=0x%lx xfercount=0x%lx total=0x%lx", 37730Sstevel@tonic-gate bp ? bp->b_bcount : 0, lba, len, cmd->cmd_xfercount, 37740Sstevel@tonic-gate cmd->cmd_total_xfercount); 37750Sstevel@tonic-gate 37760Sstevel@tonic-gate /* Set the timeout value as per command request */ 37770Sstevel@tonic-gate if ((opcode == SCMD_WRITE_G1) && SCSA2USB_VALID_CDRW_BLKSZ(blk_size)) { 37780Sstevel@tonic-gate /* 37790Sstevel@tonic-gate * We increase the time as CD-RW writes have two things 37800Sstevel@tonic-gate * to do. After writing out the data to the media, a 37810Sstevel@tonic-gate * TOC needs to be filled up at the beginning of the media 37820Sstevel@tonic-gate * This is when the write gets "finalized". 37830Sstevel@tonic-gate * Hence the actual write could take longer than the 37840Sstevel@tonic-gate * value specified in cmd->cmd_timeout. 37850Sstevel@tonic-gate */ 37860Sstevel@tonic-gate cmd->cmd_timeout *= 4; 37870Sstevel@tonic-gate 37880Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, 37890Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 37900Sstevel@tonic-gate "new timeout value = 0x%x", cmd->cmd_timeout); 37910Sstevel@tonic-gate } 37920Sstevel@tonic-gate 37930Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 37940Sstevel@tonic-gate "lba 0x%x len 0x%lx xfercount 0x%lx total 0x%lx", 37950Sstevel@tonic-gate lba, len, cmd->cmd_xfercount, cmd->cmd_total_xfercount); 37960Sstevel@tonic-gate 37970Sstevel@tonic-gate return (SCSA2USB_TRANSPORT); 37980Sstevel@tonic-gate } 37990Sstevel@tonic-gate 38000Sstevel@tonic-gate 38010Sstevel@tonic-gate /* 38020Sstevel@tonic-gate * scsa2usb_setup_next_xfer: 38030Sstevel@tonic-gate * For READs and WRITEs we split up the transfer in terms of 38040Sstevel@tonic-gate * HCD understood units. This function handles the split transfers. 38050Sstevel@tonic-gate * 38060Sstevel@tonic-gate * See comments in the previous function scsa2usb_rw_transport 38070Sstevel@tonic-gate * 38080Sstevel@tonic-gate * The lba computation was being done based on scsa2usb_max_bulk_xfer_size 38090Sstevel@tonic-gate * earlier. With CD-RW devices, the xfer_count and the block_size may 38100Sstevel@tonic-gate * no longer be a multiple of scsa2usb_max_bulk_xfer_size. So compute 38110Sstevel@tonic-gate * xfer_count all over again. Adjust lba, based on the previous requests' 38120Sstevel@tonic-gate * len. Find out the len and add it to cmd->cmd_lba to get the new lba 38130Sstevel@tonic-gate */ 38140Sstevel@tonic-gate void 38150Sstevel@tonic-gate scsa2usb_setup_next_xfer(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) 38160Sstevel@tonic-gate { 38170Sstevel@tonic-gate int xfer_len = min(scsa2usbp->scsa2usb_max_bulk_xfer_size, 38184700Sfb209375 cmd->cmd_total_xfercount); 38190Sstevel@tonic-gate int cdb_len; 38200Sstevel@tonic-gate size_t blk_size; 38210Sstevel@tonic-gate 38220Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 38230Sstevel@tonic-gate 38240Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 38250Sstevel@tonic-gate "scsa2usb_setup_next_xfer: opcode = 0x%x lba = 0x%x " 38260Sstevel@tonic-gate "total count = 0x%lx", cmd->cmd_cdb[SCSA2USB_OPCODE], 38270Sstevel@tonic-gate cmd->cmd_lba, cmd->cmd_total_xfercount); 38280Sstevel@tonic-gate 38290Sstevel@tonic-gate ASSERT(cmd->cmd_total_xfercount > 0); 38300Sstevel@tonic-gate cmd->cmd_xfercount = xfer_len; 38310Sstevel@tonic-gate blk_size = scsa2usbp->scsa2usb_lbasize[ 38324700Sfb209375 cmd->cmd_pkt->pkt_address.a_lun]; 38330Sstevel@tonic-gate 38340Sstevel@tonic-gate /* 38350Sstevel@tonic-gate * For CD-RW devices reduce the xfer count based on the 38360Sstevel@tonic-gate * block_size used by these devices. See changes below 38370Sstevel@tonic-gate * where xfer_count is being adjusted. 38380Sstevel@tonic-gate * 38390Sstevel@tonic-gate * Also adjust len/lba based on the block_size and xfer_count. 38400Sstevel@tonic-gate * NOTE: Always calculate lba first, as it based on previous 38410Sstevel@tonic-gate * commands' values. 38420Sstevel@tonic-gate */ 38430Sstevel@tonic-gate switch (cmd->cmd_cdb[SCSA2USB_OPCODE]) { 38440Sstevel@tonic-gate case SCMD_READ_CD: 38450Sstevel@tonic-gate /* calculate lba = current_lba + len_of_prev_cmd */ 38460Sstevel@tonic-gate cmd->cmd_lba += (cmd->cmd_cdb[6] << 16) + 38470Sstevel@tonic-gate (cmd->cmd_cdb[7] << 8) + cmd->cmd_cdb[8]; 38480Sstevel@tonic-gate cdb_len = xfer_len/cmd->cmd_blksize; 38490Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_2] = (uchar_t)cdb_len; 38500Sstevel@tonic-gate /* re-adjust xfer count */ 38510Sstevel@tonic-gate cmd->cmd_xfercount = cdb_len * cmd->cmd_blksize; 38520Sstevel@tonic-gate break; 38530Sstevel@tonic-gate case SCMD_WRITE_G5: 38540Sstevel@tonic-gate case SCMD_READ_G5: 38550Sstevel@tonic-gate /* calculate lba = current_lba + len_of_prev_cmd */ 38560Sstevel@tonic-gate cmd->cmd_lba += (cmd->cmd_cdb[6] << 24) + 38570Sstevel@tonic-gate (cmd->cmd_cdb[7] << 16) + (cmd->cmd_cdb[8] << 8) + 38580Sstevel@tonic-gate cmd->cmd_cdb[9]; 38590Sstevel@tonic-gate if (blk_size) { 38600Sstevel@tonic-gate xfer_len /= blk_size; 38610Sstevel@tonic-gate } 38620Sstevel@tonic-gate scsa2usb_fill_up_12byte_cdb_len(cmd, xfer_len, CDB_GROUP5); 38630Sstevel@tonic-gate break; 38640Sstevel@tonic-gate case SCMD_WRITE_G1: 38650Sstevel@tonic-gate case SCMD_WRITE_LONG: 38660Sstevel@tonic-gate /* calculate lba = current_lba + len_of_prev_cmd */ 38670Sstevel@tonic-gate cmd->cmd_lba += (cmd->cmd_cdb[7] << 8) + cmd->cmd_cdb[8]; 38680Sstevel@tonic-gate if (SCSA2USB_VALID_CDRW_BLKSZ(cmd->cmd_blksize)) { 38690Sstevel@tonic-gate blk_size = cmd->cmd_blksize; 38700Sstevel@tonic-gate } 38710Sstevel@tonic-gate cdb_len = xfer_len/blk_size; 38720Sstevel@tonic-gate scsa2usb_fill_up_cdb_len(cmd, cdb_len); 38730Sstevel@tonic-gate /* re-adjust xfer count */ 38740Sstevel@tonic-gate cmd->cmd_xfercount = cdb_len * blk_size; 38750Sstevel@tonic-gate break; 38760Sstevel@tonic-gate default: 38770Sstevel@tonic-gate if (blk_size) { 38780Sstevel@tonic-gate xfer_len /= blk_size; 38790Sstevel@tonic-gate } 38800Sstevel@tonic-gate scsa2usb_fill_up_cdb_len(cmd, xfer_len); 38810Sstevel@tonic-gate cmd->cmd_lba += scsa2usbp->scsa2usb_max_bulk_xfer_size/blk_size; 38820Sstevel@tonic-gate } 38830Sstevel@tonic-gate 38840Sstevel@tonic-gate /* fill in the lba */ 38850Sstevel@tonic-gate scsa2usb_fill_up_cdb_lba(cmd, cmd->cmd_lba); 38860Sstevel@tonic-gate 38870Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 38880Sstevel@tonic-gate "scsa2usb_setup_next_xfer:\n\tlba = 0x%x xfer_len = 0x%x " 38890Sstevel@tonic-gate "xfercount = 0x%lx total = 0x%lx", cmd->cmd_lba, xfer_len, 38900Sstevel@tonic-gate cmd->cmd_xfercount, cmd->cmd_total_xfercount); 38910Sstevel@tonic-gate } 38920Sstevel@tonic-gate 38930Sstevel@tonic-gate 38940Sstevel@tonic-gate /* 38950Sstevel@tonic-gate * take one request from the lun's waitQ and transport it 38960Sstevel@tonic-gate */ 38970Sstevel@tonic-gate static void 38980Sstevel@tonic-gate scsa2usb_transport_request(scsa2usb_state_t *scsa2usbp, uint_t lun) 38990Sstevel@tonic-gate { 39000Sstevel@tonic-gate int rval; 39010Sstevel@tonic-gate struct scsi_pkt *pkt; 39020Sstevel@tonic-gate struct scsa2usb_cmd *cmd, *arqcmd; 39030Sstevel@tonic-gate 39040Sstevel@tonic-gate if ((cmd = (scsa2usb_cmd_t *) 39050Sstevel@tonic-gate usba_rm_first_pvt_from_list( 39060Sstevel@tonic-gate &scsa2usbp->scsa2usb_waitQ[lun])) == NULL) { 39070Sstevel@tonic-gate 39080Sstevel@tonic-gate return; 39090Sstevel@tonic-gate } 39100Sstevel@tonic-gate pkt = cmd->cmd_pkt; 39110Sstevel@tonic-gate 39120Sstevel@tonic-gate /* 39130Sstevel@tonic-gate * if device has been disconnected, just complete it 39140Sstevel@tonic-gate */ 39150Sstevel@tonic-gate if (scsa2usbp->scsa2usb_dev_state == USB_DEV_DISCONNECTED) { 39160Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 39170Sstevel@tonic-gate "device not accessible"); 39180Sstevel@tonic-gate pkt->pkt_reason = CMD_DEV_GONE; 39190Sstevel@tonic-gate SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 39200Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usbp, pkt); 39210Sstevel@tonic-gate 39220Sstevel@tonic-gate return; 39230Sstevel@tonic-gate } 39240Sstevel@tonic-gate 39250Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, 39260Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 39270Sstevel@tonic-gate "scsa2usb_transport_request: cmd=0x%p bp=0x%p addr=0x%p", 39286898Sfb209375 (void *)cmd, (void *)cmd->cmd_bp, 39296898Sfb209375 (void *)(cmd->cmd_bp ? cmd->cmd_bp->b_un.b_addr : NULL)); 39300Sstevel@tonic-gate 39310Sstevel@tonic-gate rval = scsa2usb_cmd_transport(scsa2usbp, cmd); 39320Sstevel@tonic-gate 39330Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 39340Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 39350Sstevel@tonic-gate "scsa2usb_transport_request: transport rval = %d", 39360Sstevel@tonic-gate rval); 39370Sstevel@tonic-gate 39380Sstevel@tonic-gate if (scsa2usbp->scsa2usb_cur_pkt == NULL) { 39390Sstevel@tonic-gate 39400Sstevel@tonic-gate return; 39410Sstevel@tonic-gate } 39420Sstevel@tonic-gate 39430Sstevel@tonic-gate ASSERT(pkt == scsa2usbp->scsa2usb_cur_pkt); 39440Sstevel@tonic-gate 39450Sstevel@tonic-gate if (ddi_in_panic()) { 39460Sstevel@tonic-gate pkt->pkt_reason = CMD_CMPLT; 39470Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usbp, pkt); 39480Sstevel@tonic-gate 39490Sstevel@tonic-gate return; 39500Sstevel@tonic-gate } 39510Sstevel@tonic-gate 39520Sstevel@tonic-gate /* 39530Sstevel@tonic-gate * start an auto-request sense iff 39540Sstevel@tonic-gate * there was a check condition, we have enough 39550Sstevel@tonic-gate * space in the status block, and we have not 39560Sstevel@tonic-gate * faked an auto request sense 39570Sstevel@tonic-gate */ 39580Sstevel@tonic-gate if ((*(pkt->pkt_scbp) == STATUS_CHECK) && 39590Sstevel@tonic-gate (cmd->cmd_scblen >= sizeof (struct scsi_arq_status)) && 39600Sstevel@tonic-gate ((pkt->pkt_state & STATE_ARQ_DONE) == 0) && 39610Sstevel@tonic-gate (scsa2usb_create_arq_pkt(scsa2usbp, 39620Sstevel@tonic-gate &pkt->pkt_address) == USB_SUCCESS)) { 39630Sstevel@tonic-gate arqcmd = scsa2usbp->scsa2usb_arq_cmd; 39640Sstevel@tonic-gate 39650Sstevel@tonic-gate /* 39660Sstevel@tonic-gate * copy the timeout from the 39670Sstevel@tonic-gate * original packet 39680Sstevel@tonic-gate * for lack of a better value 39690Sstevel@tonic-gate */ 39700Sstevel@tonic-gate arqcmd->cmd_pkt->pkt_time = pkt->pkt_time; 39710Sstevel@tonic-gate scsa2usb_prepare_pkt(scsa2usbp, 39724700Sfb209375 arqcmd->cmd_pkt); 39730Sstevel@tonic-gate 39740Sstevel@tonic-gate scsa2usbp->scsa2usb_cur_pkt = NULL; 39750Sstevel@tonic-gate if (scsa2usb_cmd_transport( 39760Sstevel@tonic-gate scsa2usbp, arqcmd) == TRAN_ACCEPT) { 39770Sstevel@tonic-gate 39780Sstevel@tonic-gate /* finish w/ this packet */ 39790Sstevel@tonic-gate scsa2usb_complete_arq_pkt( 39800Sstevel@tonic-gate scsa2usbp, arqcmd->cmd_pkt, cmd, 39810Sstevel@tonic-gate scsa2usbp->scsa2usb_arq_bp); 39820Sstevel@tonic-gate 39830Sstevel@tonic-gate /* 39840Sstevel@tonic-gate * we have valid request sense 39850Sstevel@tonic-gate * data so clear the pkt_reason 39860Sstevel@tonic-gate */ 39870Sstevel@tonic-gate pkt->pkt_reason = CMD_CMPLT; 39880Sstevel@tonic-gate } 39890Sstevel@tonic-gate scsa2usbp->scsa2usb_cur_pkt = pkt; 39900Sstevel@tonic-gate scsa2usb_delete_arq_pkt(scsa2usbp); 39910Sstevel@tonic-gate } 39920Sstevel@tonic-gate 39930Sstevel@tonic-gate if ((rval != TRAN_ACCEPT) && 39940Sstevel@tonic-gate (pkt->pkt_reason == CMD_CMPLT)) { 39950Sstevel@tonic-gate pkt->pkt_reason = CMD_TRAN_ERR; 39960Sstevel@tonic-gate } 39970Sstevel@tonic-gate 39980Sstevel@tonic-gate SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 39990Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usbp, pkt); 40000Sstevel@tonic-gate 40010Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_cur_pkt == NULL); 40020Sstevel@tonic-gate } 40030Sstevel@tonic-gate 40040Sstevel@tonic-gate 40050Sstevel@tonic-gate /* 40060Sstevel@tonic-gate * scsa2usb_work_thread: 40070Sstevel@tonic-gate * The taskq thread that kicks off the transport (BO and CB/CBI) 40080Sstevel@tonic-gate */ 40090Sstevel@tonic-gate static void 40100Sstevel@tonic-gate scsa2usb_work_thread(void *arg) 40110Sstevel@tonic-gate { 40120Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)arg; 40130Sstevel@tonic-gate uint_t lun; 40140Sstevel@tonic-gate uint_t count; 40150Sstevel@tonic-gate 4016189Sfrits mutex_enter(&scsa2usbp->scsa2usb_mutex); 40170Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 40186898Sfb209375 "scsa2usb_work_thread start: thread_id=0x%p", 40196898Sfb209375 (void *)scsa2usbp->scsa2usb_work_thread_id); 4020189Sfrits 40210Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_work_thread_id == (kthread_t *)1); 40220Sstevel@tonic-gate scsa2usbp->scsa2usb_work_thread_id = curthread; 40230Sstevel@tonic-gate 40240Sstevel@tonic-gate /* exclude ugen accesses */ 40250Sstevel@tonic-gate while (scsa2usbp->scsa2usb_transport_busy) { 40260Sstevel@tonic-gate cv_wait(&scsa2usbp->scsa2usb_transport_busy_cv, 40270Sstevel@tonic-gate &scsa2usbp->scsa2usb_mutex); 40280Sstevel@tonic-gate } 40290Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_ugen_open_count == 0); 40300Sstevel@tonic-gate scsa2usbp->scsa2usb_transport_busy++; 40310Sstevel@tonic-gate scsa2usbp->scsa2usb_busy_thread = curthread; 40320Sstevel@tonic-gate 40330Sstevel@tonic-gate scsa2usb_raise_power(scsa2usbp); 40340Sstevel@tonic-gate 40350Sstevel@tonic-gate /* reopen the pipes if necessary */ 40360Sstevel@tonic-gate (void) scsa2usb_open_usb_pipes(scsa2usbp); 40370Sstevel@tonic-gate 40380Sstevel@tonic-gate for (;;) { 40390Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_ugen_open_count == 0); 40400Sstevel@tonic-gate for (lun = 0; lun < scsa2usbp->scsa2usb_n_luns; lun++) { 40410Sstevel@tonic-gate scsa2usb_transport_request(scsa2usbp, lun); 40420Sstevel@tonic-gate } 40430Sstevel@tonic-gate count = 0; 40440Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 40450Sstevel@tonic-gate count += usba_list_entry_count( 40464700Sfb209375 &scsa2usbp->scsa2usb_waitQ[lun]); 40470Sstevel@tonic-gate } 40480Sstevel@tonic-gate 40490Sstevel@tonic-gate if (count == 0) { 40500Sstevel@tonic-gate 40510Sstevel@tonic-gate break; 40520Sstevel@tonic-gate } 40530Sstevel@tonic-gate } 40540Sstevel@tonic-gate 40550Sstevel@tonic-gate scsa2usbp->scsa2usb_work_thread_id = 0; 40560Sstevel@tonic-gate 40570Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_ugen_open_count == 0); 40580Sstevel@tonic-gate 40590Sstevel@tonic-gate scsa2usbp->scsa2usb_transport_busy--; 40600Sstevel@tonic-gate scsa2usbp->scsa2usb_busy_thread = NULL; 40610Sstevel@tonic-gate cv_signal(&scsa2usbp->scsa2usb_transport_busy_cv); 40620Sstevel@tonic-gate 40630Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 40640Sstevel@tonic-gate "scsa2usb_work_thread: exit"); 4065189Sfrits 4066189Sfrits mutex_exit(&scsa2usbp->scsa2usb_mutex); 4067189Sfrits 4068189Sfrits scsa2usb_pm_idle_component(scsa2usbp); 40690Sstevel@tonic-gate } 40700Sstevel@tonic-gate 40710Sstevel@tonic-gate 40720Sstevel@tonic-gate /* 40730Sstevel@tonic-gate * scsa2usb_flush_waitQ: 40740Sstevel@tonic-gate * empties the entire waitQ with errors asap. 40750Sstevel@tonic-gate * 40760Sstevel@tonic-gate * It is called from scsa2usb_scsi_reset and scsa2usb_panic_callb. 40770Sstevel@tonic-gate * If the device is reset; we should empty the waitQ right away. 40780Sstevel@tonic-gate * If the system has paniced; we should empty the waitQ right away. 40790Sstevel@tonic-gate * 40800Sstevel@tonic-gate * CPR suspend will only succeed if device is idle. No need to call 40810Sstevel@tonic-gate * this function for CPR suspend case. 40820Sstevel@tonic-gate */ 40830Sstevel@tonic-gate static void 40840Sstevel@tonic-gate scsa2usb_flush_waitQ(scsa2usb_state_t *scsa2usbp, uint_t lun, 40850Sstevel@tonic-gate uchar_t error) 40860Sstevel@tonic-gate { 40870Sstevel@tonic-gate struct scsi_pkt *pkt; 40880Sstevel@tonic-gate struct scsa2usb_cmd *cmd; 40890Sstevel@tonic-gate usba_list_entry_t head; 40900Sstevel@tonic-gate 40910Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 40920Sstevel@tonic-gate 40930Sstevel@tonic-gate usba_move_list(&scsa2usbp->scsa2usb_waitQ[lun], &head, 40940Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_data->dev_iblock_cookie); 40950Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 40960Sstevel@tonic-gate 40970Sstevel@tonic-gate while ((cmd = (scsa2usb_cmd_t *)usba_rm_first_pvt_from_list(&head)) != 40980Sstevel@tonic-gate NULL) { 40990Sstevel@tonic-gate pkt = cmd->cmd_pkt; 41000Sstevel@tonic-gate pkt->pkt_reason = error; /* set error */ 41010Sstevel@tonic-gate 41020Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 41030Sstevel@tonic-gate scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_DO_COMP; 41040Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usbp, pkt); 41050Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 41060Sstevel@tonic-gate } /* end of while */ 41070Sstevel@tonic-gate } 41080Sstevel@tonic-gate 41090Sstevel@tonic-gate 41100Sstevel@tonic-gate /* 41110Sstevel@tonic-gate * scsa2usb_do_inquiry is performed before INIT CHILD and we have 41120Sstevel@tonic-gate * to fake a few things normally done by SCSA 41130Sstevel@tonic-gate */ 41140Sstevel@tonic-gate static void 41150Sstevel@tonic-gate scsa2usb_do_inquiry(scsa2usb_state_t *scsa2usbp, uint_t target, uint_t lun) 41160Sstevel@tonic-gate { 41170Sstevel@tonic-gate struct buf *bp; 41180Sstevel@tonic-gate struct scsi_pkt *pkt; 41190Sstevel@tonic-gate struct scsi_address ap; 41200Sstevel@tonic-gate int len = SCSA2USB_MAX_INQ_LEN; 41210Sstevel@tonic-gate 41220Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 41230Sstevel@tonic-gate "scsa2usb_do_inquiry: %d bytes", len); 41240Sstevel@tonic-gate 41250Sstevel@tonic-gate /* is it inquiry-challenged? */ 41260Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_INQUIRY)) { 41270Sstevel@tonic-gate (void) scsa2usb_fake_inquiry(scsa2usbp, NULL, lun); 41280Sstevel@tonic-gate 41290Sstevel@tonic-gate return; 41300Sstevel@tonic-gate } 41310Sstevel@tonic-gate 41320Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 41330Sstevel@tonic-gate 41340Sstevel@tonic-gate bzero(&ap, sizeof (struct scsi_address)); 41350Sstevel@tonic-gate ap.a_hba_tran = scsa2usbp->scsa2usb_tran; 4136*7492SZhigang.Lu@Sun.COM ap.a_target = (ushort_t)target; 4137*7492SZhigang.Lu@Sun.COM ap.a_lun = (uchar_t)lun; 41380Sstevel@tonic-gate 41390Sstevel@tonic-gate /* limit inquiry to 36 bytes */ 41400Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 41410Sstevel@tonic-gate if ((bp = scsi_alloc_consistent_buf(&ap, (struct buf *)NULL, 41420Sstevel@tonic-gate len, B_READ, SLEEP_FUNC, NULL)) == NULL) { 41430Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 41440Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 41450Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 41460Sstevel@tonic-gate "scsa2usb_do_inquiry: failed"); 41470Sstevel@tonic-gate 41480Sstevel@tonic-gate return; 41490Sstevel@tonic-gate } 41500Sstevel@tonic-gate 41510Sstevel@tonic-gate pkt = scsi_init_pkt(&ap, NULL, bp, CDB_GROUP0, 1, 41520Sstevel@tonic-gate PKT_PRIV_LEN, PKT_CONSISTENT, SLEEP_FUNC, NULL); 41530Sstevel@tonic-gate 4154*7492SZhigang.Lu@Sun.COM RQ_MAKECOM_G0(pkt, FLAG_NOINTR, (char)SCMD_INQUIRY, 0, (char)len); 41550Sstevel@tonic-gate 41560Sstevel@tonic-gate pkt->pkt_comp = NULL; 41570Sstevel@tonic-gate pkt->pkt_time = 5; 41580Sstevel@tonic-gate bzero(bp->b_un.b_addr, len); 41590Sstevel@tonic-gate 41600Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 41610Sstevel@tonic-gate "scsa2usb_do_inquiry:INQUIRY"); 41620Sstevel@tonic-gate 41630Sstevel@tonic-gate (void) scsi_transport(pkt); 41640Sstevel@tonic-gate 41650Sstevel@tonic-gate if (pkt->pkt_reason) { 4166978Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, 41670Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 41680Sstevel@tonic-gate "INQUIRY failed, cannot determine device type, " 41690Sstevel@tonic-gate "pkt_reason=0x%x", pkt->pkt_reason); 41700Sstevel@tonic-gate 41710Sstevel@tonic-gate /* not much hope for other cmds, reduce */ 41720Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 41730Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= 41744700Sfb209375 ~SCSA2USB_ATTRS_REDUCED_CMD; 41750Sstevel@tonic-gate (void) scsa2usb_fake_inquiry(scsa2usbp, NULL, lun); 41760Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 41770Sstevel@tonic-gate } 41780Sstevel@tonic-gate 41790Sstevel@tonic-gate scsi_destroy_pkt(pkt); 41800Sstevel@tonic-gate scsi_free_consistent_buf(bp); 41810Sstevel@tonic-gate 41820Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 41830Sstevel@tonic-gate } 41840Sstevel@tonic-gate 41850Sstevel@tonic-gate 41860Sstevel@tonic-gate /* 41870Sstevel@tonic-gate * scsa2usb_fake_inquiry: 41880Sstevel@tonic-gate * build an inquiry for a given device that doesnt like inquiry 41890Sstevel@tonic-gate * commands. 41900Sstevel@tonic-gate */ 41910Sstevel@tonic-gate static int 41920Sstevel@tonic-gate scsa2usb_fake_inquiry(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd, 41930Sstevel@tonic-gate uint_t lun) 41940Sstevel@tonic-gate { 41950Sstevel@tonic-gate usb_client_dev_data_t *dev_data = scsa2usbp->scsa2usb_dev_data; 41960Sstevel@tonic-gate struct scsi_inquiry *inqp; 41970Sstevel@tonic-gate int len; 41980Sstevel@tonic-gate 41990Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 42000Sstevel@tonic-gate "scsa2usb_fake_inquiry:"); 42010Sstevel@tonic-gate 42020Sstevel@tonic-gate if (cmd) { 42030Sstevel@tonic-gate inqp = (struct scsi_inquiry *)cmd->cmd_bp->b_un.b_addr; 42040Sstevel@tonic-gate } else { 42050Sstevel@tonic-gate inqp = &scsa2usbp->scsa2usb_lun_inquiry[lun]; 42060Sstevel@tonic-gate } 42070Sstevel@tonic-gate bzero(inqp, sizeof (struct scsi_inquiry)); 42080Sstevel@tonic-gate for (len = 0; len < sizeof (inqp->inq_vid); len++) { 42090Sstevel@tonic-gate *(inqp->inq_vid + len) = ' '; 42100Sstevel@tonic-gate } 42110Sstevel@tonic-gate 42120Sstevel@tonic-gate for (len = 0; len < sizeof (inqp->inq_pid); len++) { 42130Sstevel@tonic-gate *(inqp->inq_pid + len) = ' '; 42140Sstevel@tonic-gate } 42150Sstevel@tonic-gate 42160Sstevel@tonic-gate inqp->inq_dtype = DTYPE_DIRECT; 42170Sstevel@tonic-gate inqp->inq_rmb = 1; 42180Sstevel@tonic-gate inqp->inq_ansi = 2; 42190Sstevel@tonic-gate inqp->inq_rdf = RDF_SCSI2; 42200Sstevel@tonic-gate inqp->inq_len = sizeof (struct scsi_inquiry)-4; 42210Sstevel@tonic-gate 42220Sstevel@tonic-gate /* Fill in the Vendor id/Product id strings */ 42230Sstevel@tonic-gate if (dev_data->dev_mfg) { 42240Sstevel@tonic-gate if ((len = strlen(dev_data->dev_mfg)) > 42250Sstevel@tonic-gate sizeof (inqp->inq_vid)) { 42260Sstevel@tonic-gate len = sizeof (inqp->inq_vid); 42270Sstevel@tonic-gate } 42280Sstevel@tonic-gate bcopy(dev_data->dev_mfg, inqp->inq_vid, len); 42290Sstevel@tonic-gate } 42300Sstevel@tonic-gate 42310Sstevel@tonic-gate if (dev_data->dev_product) { 42320Sstevel@tonic-gate if ((len = strlen(dev_data->dev_product)) > 42330Sstevel@tonic-gate sizeof (inqp->inq_pid)) { 42340Sstevel@tonic-gate len = sizeof (inqp->inq_pid); 42350Sstevel@tonic-gate } 42360Sstevel@tonic-gate bcopy(dev_data->dev_product, inqp->inq_pid, len); 42370Sstevel@tonic-gate } 42380Sstevel@tonic-gate 42390Sstevel@tonic-gate /* Set the Revision to the Device */ 42400Sstevel@tonic-gate inqp->inq_revision[0] = 0x30 + 42414700Sfb209375 ((dev_data->dev_descr->bcdDevice>>12) & 0xF); 42420Sstevel@tonic-gate inqp->inq_revision[1] = 0x30 + 42434700Sfb209375 ((dev_data->dev_descr->bcdDevice>>8) & 0xF); 42440Sstevel@tonic-gate inqp->inq_revision[2] = 0x30 + 42454700Sfb209375 ((dev_data->dev_descr->bcdDevice>>4) & 0xF); 42460Sstevel@tonic-gate inqp->inq_revision[3] = 0x30 + 42474700Sfb209375 ((dev_data->dev_descr->bcdDevice) & 0xF); 42480Sstevel@tonic-gate 42490Sstevel@tonic-gate /* Copy inquiry data in to soft state */ 42500Sstevel@tonic-gate bcopy(inqp, &scsa2usbp->scsa2usb_lun_inquiry[lun], 42510Sstevel@tonic-gate sizeof (struct scsi_inquiry)); 42520Sstevel@tonic-gate 42530Sstevel@tonic-gate return (sizeof (struct scsi_inquiry)); 42540Sstevel@tonic-gate } 42550Sstevel@tonic-gate 42560Sstevel@tonic-gate 42570Sstevel@tonic-gate /* 42580Sstevel@tonic-gate * scsa2usb_create_arq_pkt: 42590Sstevel@tonic-gate * Create and ARQ packet to get request sense data 42600Sstevel@tonic-gate */ 42610Sstevel@tonic-gate static int 42620Sstevel@tonic-gate scsa2usb_create_arq_pkt(scsa2usb_state_t *scsa2usbp, struct scsi_address *ap) 42630Sstevel@tonic-gate { 42640Sstevel@tonic-gate struct buf *bp; 42650Sstevel@tonic-gate scsa2usb_cmd_t *arq_cmd; 42660Sstevel@tonic-gate 42670Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 42686898Sfb209375 "scsa2usb_create_arq_pkt: scsa2usbp: %p, ap: %p", 42696898Sfb209375 (void *)scsa2usbp, (void *)ap); 42700Sstevel@tonic-gate 42710Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 42720Sstevel@tonic-gate 42730Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 42740Sstevel@tonic-gate if ((bp = scsi_alloc_consistent_buf(ap, (struct buf *)NULL, 42750Sstevel@tonic-gate SENSE_LENGTH, B_READ, SLEEP_FUNC, NULL)) == NULL) { 42760Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 42770Sstevel@tonic-gate 42780Sstevel@tonic-gate return (USB_FAILURE); 42790Sstevel@tonic-gate } 42800Sstevel@tonic-gate 42810Sstevel@tonic-gate arq_cmd = PKT2CMD(scsi_init_pkt(ap, NULL, bp, CDB_GROUP0, 1, 42820Sstevel@tonic-gate PKT_PRIV_LEN, PKT_CONSISTENT, SLEEP_FUNC, NULL)); 42830Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 42840Sstevel@tonic-gate 42850Sstevel@tonic-gate RQ_MAKECOM_G0(arq_cmd->cmd_pkt, 42860Sstevel@tonic-gate FLAG_SENSING | FLAG_HEAD | FLAG_NODISCON, 42870Sstevel@tonic-gate (char)SCMD_REQUEST_SENSE, 0, (char)SENSE_LENGTH); 42880Sstevel@tonic-gate 42890Sstevel@tonic-gate arq_cmd->cmd_pkt->pkt_ha_private = arq_cmd; 42900Sstevel@tonic-gate scsa2usbp->scsa2usb_arq_cmd = arq_cmd; 42910Sstevel@tonic-gate scsa2usbp->scsa2usb_arq_bp = bp; 42920Sstevel@tonic-gate arq_cmd->cmd_pkt->pkt_comp = NULL; 42930Sstevel@tonic-gate bzero(bp->b_un.b_addr, SENSE_LENGTH); 42940Sstevel@tonic-gate 42950Sstevel@tonic-gate return (USB_SUCCESS); 42960Sstevel@tonic-gate } 42970Sstevel@tonic-gate 42980Sstevel@tonic-gate 42990Sstevel@tonic-gate /* 43000Sstevel@tonic-gate * scsa2usb_delete_arq_pkt: 43010Sstevel@tonic-gate * Destroy the ARQ packet 43020Sstevel@tonic-gate */ 43030Sstevel@tonic-gate static void 43040Sstevel@tonic-gate scsa2usb_delete_arq_pkt(scsa2usb_state_t *scsa2usbp) 43050Sstevel@tonic-gate { 43060Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 43076898Sfb209375 "scsa2usb_delete_arq_pkt: cmd: 0x%p", 43086898Sfb209375 (void *)scsa2usbp->scsa2usb_arq_cmd); 43090Sstevel@tonic-gate 43100Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 43110Sstevel@tonic-gate 43120Sstevel@tonic-gate if (scsa2usbp->scsa2usb_arq_cmd != NULL) { 43130Sstevel@tonic-gate scsi_destroy_pkt(scsa2usbp->scsa2usb_arq_cmd->cmd_pkt); 43140Sstevel@tonic-gate scsi_free_consistent_buf(scsa2usbp->scsa2usb_arq_bp); 43150Sstevel@tonic-gate } 43160Sstevel@tonic-gate scsa2usbp->scsa2usb_arq_cmd = NULL; 43170Sstevel@tonic-gate scsa2usbp->scsa2usb_arq_bp = NULL; 43180Sstevel@tonic-gate } 43190Sstevel@tonic-gate 43200Sstevel@tonic-gate 43210Sstevel@tonic-gate /* 43220Sstevel@tonic-gate * scsa2usb_complete_arq_pkt: 43230Sstevel@tonic-gate * finish processing the arq packet 43240Sstevel@tonic-gate */ 43250Sstevel@tonic-gate static void 43260Sstevel@tonic-gate scsa2usb_complete_arq_pkt(scsa2usb_state_t *scsa2usbp, 43270Sstevel@tonic-gate struct scsi_pkt *pkt, scsa2usb_cmd_t *ssp, struct buf *bp) 43280Sstevel@tonic-gate { 43290Sstevel@tonic-gate scsa2usb_cmd_t *sp = pkt->pkt_ha_private; 43300Sstevel@tonic-gate struct scsi_arq_status *arqp; 43310Sstevel@tonic-gate 43320Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 43330Sstevel@tonic-gate 43340Sstevel@tonic-gate arqp = (struct scsi_arq_status *)(ssp->cmd_pkt->pkt_scbp); 43350Sstevel@tonic-gate arqp->sts_rqpkt_status = *((struct scsi_status *) 43364700Sfb209375 (sp->cmd_pkt->pkt_scbp)); 43370Sstevel@tonic-gate arqp->sts_rqpkt_reason = CMD_CMPLT; 43380Sstevel@tonic-gate arqp->sts_rqpkt_state |= STATE_XFERRED_DATA; 43390Sstevel@tonic-gate arqp->sts_rqpkt_statistics = arqp->sts_rqpkt_resid = 0; 43400Sstevel@tonic-gate 43410Sstevel@tonic-gate /* is this meaningful sense data */ 43420Sstevel@tonic-gate if (*(bp->b_un.b_addr) != 0) { 43435727Slh195018 bcopy(bp->b_un.b_addr, &arqp->sts_sensedata, SENSE_LENGTH); 43440Sstevel@tonic-gate ssp->cmd_pkt->pkt_state |= STATE_ARQ_DONE; 43450Sstevel@tonic-gate } 43460Sstevel@tonic-gate 43470Sstevel@tonic-gate /* we will not sense start cmd until we receive a NOT READY */ 43480Sstevel@tonic-gate if (arqp->sts_sensedata.es_key == KEY_NOT_READY) { 43490Sstevel@tonic-gate scsa2usbp->scsa2usb_rcvd_not_ready = B_TRUE; 43500Sstevel@tonic-gate } 43510Sstevel@tonic-gate } 43520Sstevel@tonic-gate 43530Sstevel@tonic-gate 43540Sstevel@tonic-gate /* 43550Sstevel@tonic-gate * Miscellaneous functions for any command/transport 43560Sstevel@tonic-gate */ 43570Sstevel@tonic-gate /* 43580Sstevel@tonic-gate * scsa2usb_open_usb_pipes: 43590Sstevel@tonic-gate * set up a pipe policy 43600Sstevel@tonic-gate * open usb bulk pipes (BO and CB/CBI) 43610Sstevel@tonic-gate * open usb interrupt pipe (CBI) 43620Sstevel@tonic-gate */ 43630Sstevel@tonic-gate static int 43640Sstevel@tonic-gate scsa2usb_open_usb_pipes(scsa2usb_state_t *scsa2usbp) 43650Sstevel@tonic-gate { 43660Sstevel@tonic-gate int rval; 43670Sstevel@tonic-gate usb_pipe_policy_t policy; /* bulk pipe policy */ 43680Sstevel@tonic-gate size_t sz; 43690Sstevel@tonic-gate 43700Sstevel@tonic-gate ASSERT(scsa2usbp); 43710Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 43720Sstevel@tonic-gate 43730Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 43740Sstevel@tonic-gate "scsa2usb_open_usb_pipes: dip = 0x%p flag = 0x%x", 43756898Sfb209375 (void *)scsa2usbp->scsa2usb_dip, scsa2usbp->scsa2usb_flags); 43760Sstevel@tonic-gate 43770Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_flags & SCSA2USB_FLAGS_PIPES_OPENED)) { 43780Sstevel@tonic-gate 43790Sstevel@tonic-gate /* 43800Sstevel@tonic-gate * one pipe policy for all bulk pipes 43810Sstevel@tonic-gate */ 43820Sstevel@tonic-gate bzero(&policy, sizeof (usb_pipe_policy_t)); 43830Sstevel@tonic-gate /* at least 2, for the normal and exceptional callbacks */ 43840Sstevel@tonic-gate policy.pp_max_async_reqs = 1; 43850Sstevel@tonic-gate 43860Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 43870Sstevel@tonic-gate "scsa2usb_open_usb_pipes: opening bulk pipes"); 43880Sstevel@tonic-gate 43890Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 43900Sstevel@tonic-gate 43910Sstevel@tonic-gate /* Open the USB bulk-in pipe */ 43920Sstevel@tonic-gate if ((rval = usb_pipe_open(scsa2usbp->scsa2usb_dip, 43930Sstevel@tonic-gate &scsa2usbp->scsa2usb_bulkin_ept, &policy, USB_FLAGS_SLEEP, 43940Sstevel@tonic-gate &scsa2usbp->scsa2usb_bulkin_pipe)) != USB_SUCCESS) { 43950Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 43960Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 43970Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 43980Sstevel@tonic-gate "scsa2usb_open_usb_pipes: bulk/in pipe open " 43990Sstevel@tonic-gate " failed rval = %d", rval); 44000Sstevel@tonic-gate 44010Sstevel@tonic-gate return (USB_FAILURE); 44020Sstevel@tonic-gate } 44030Sstevel@tonic-gate 44040Sstevel@tonic-gate /* Open the bulk-out pipe using the same policy */ 44050Sstevel@tonic-gate if ((rval = usb_pipe_open(scsa2usbp->scsa2usb_dip, 44060Sstevel@tonic-gate &scsa2usbp->scsa2usb_bulkout_ept, &policy, USB_FLAGS_SLEEP, 44070Sstevel@tonic-gate &scsa2usbp->scsa2usb_bulkout_pipe)) != USB_SUCCESS) { 44080Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 44090Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, 44100Sstevel@tonic-gate USB_FLAGS_SLEEP, NULL, NULL); 44110Sstevel@tonic-gate 44120Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 44130Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe = NULL; 44140Sstevel@tonic-gate 44150Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 44160Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 44170Sstevel@tonic-gate "scsa2usb_open_usb_pipes: bulk/out pipe open" 44180Sstevel@tonic-gate " failed rval = %d", rval); 44190Sstevel@tonic-gate 44200Sstevel@tonic-gate return (USB_FAILURE); 44210Sstevel@tonic-gate } 44220Sstevel@tonic-gate 44230Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 44240Sstevel@tonic-gate 44250Sstevel@tonic-gate /* open interrupt pipe for CBI protocol */ 44260Sstevel@tonic-gate if (SCSA2USB_IS_CBI(scsa2usbp)) { 44270Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 44280Sstevel@tonic-gate 44290Sstevel@tonic-gate if ((rval = usb_pipe_open(scsa2usbp->scsa2usb_dip, 44300Sstevel@tonic-gate &scsa2usbp->scsa2usb_intr_ept, &policy, 44310Sstevel@tonic-gate USB_FLAGS_SLEEP, &scsa2usbp->scsa2usb_intr_pipe)) != 44320Sstevel@tonic-gate USB_SUCCESS) { 44330Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 44340Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, 44350Sstevel@tonic-gate USB_FLAGS_SLEEP, NULL, NULL); 44360Sstevel@tonic-gate 44370Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 44380Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkout_pipe, 44390Sstevel@tonic-gate USB_FLAGS_SLEEP, NULL, NULL); 44400Sstevel@tonic-gate 44410Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 44420Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe = NULL; 44430Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkout_pipe = NULL; 44440Sstevel@tonic-gate 44450Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 44460Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 44470Sstevel@tonic-gate "scsa2usb_open_usb_pipes: intr pipe open" 44480Sstevel@tonic-gate " failed rval = %d", rval); 44490Sstevel@tonic-gate 44500Sstevel@tonic-gate return (USB_FAILURE); 44510Sstevel@tonic-gate } 44520Sstevel@tonic-gate 44530Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 44540Sstevel@tonic-gate } 44550Sstevel@tonic-gate 44560Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 44570Sstevel@tonic-gate 44580Sstevel@tonic-gate /* get the max transfer size of the bulk pipe */ 44590Sstevel@tonic-gate if (usb_pipe_get_max_bulk_transfer_size(scsa2usbp->scsa2usb_dip, 44600Sstevel@tonic-gate &sz) == USB_SUCCESS) { 44610Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 44620Sstevel@tonic-gate scsa2usbp->scsa2usb_max_bulk_xfer_size = sz; 44630Sstevel@tonic-gate } else { 44640Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 44650Sstevel@tonic-gate scsa2usbp->scsa2usb_max_bulk_xfer_size = DEV_BSIZE; 44660Sstevel@tonic-gate } 44670Sstevel@tonic-gate 44680Sstevel@tonic-gate /* limit the xfer size */ 44690Sstevel@tonic-gate scsa2usbp->scsa2usb_max_bulk_xfer_size = min( 44704700Sfb209375 scsa2usbp->scsa2usb_max_bulk_xfer_size, 44714700Sfb209375 scsa2usb_max_bulk_xfer_size); 44720Sstevel@tonic-gate 44730Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 44740Sstevel@tonic-gate "scsa2usb_open_usb_pipes: max bulk transfer size = %lx", 44750Sstevel@tonic-gate scsa2usbp->scsa2usb_max_bulk_xfer_size); 44760Sstevel@tonic-gate 44770Sstevel@tonic-gate /* Set the pipes opened flag */ 44780Sstevel@tonic-gate scsa2usbp->scsa2usb_flags |= SCSA2USB_FLAGS_PIPES_OPENED; 44790Sstevel@tonic-gate 44800Sstevel@tonic-gate scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_NORMAL; 44810Sstevel@tonic-gate 44820Sstevel@tonic-gate /* Set the state to NONE */ 44830Sstevel@tonic-gate scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_NONE; 44840Sstevel@tonic-gate } 44850Sstevel@tonic-gate 44860Sstevel@tonic-gate return (USB_SUCCESS); 44870Sstevel@tonic-gate } 44880Sstevel@tonic-gate 44890Sstevel@tonic-gate 44900Sstevel@tonic-gate /* 44910Sstevel@tonic-gate * scsa2usb_close_usb_pipes: 44920Sstevel@tonic-gate * close all pipes synchronously 44930Sstevel@tonic-gate */ 44940Sstevel@tonic-gate void 44950Sstevel@tonic-gate scsa2usb_close_usb_pipes(scsa2usb_state_t *scsa2usbp) 44960Sstevel@tonic-gate { 44970Sstevel@tonic-gate usb_flags_t flags = USB_FLAGS_SLEEP; 44980Sstevel@tonic-gate 44990Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 45006898Sfb209375 "scsa2usb_close_usb_pipes: scsa2usb_state = 0x%p", 45016898Sfb209375 (void *)scsa2usbp); 45020Sstevel@tonic-gate 45030Sstevel@tonic-gate ASSERT(scsa2usbp); 45040Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 45050Sstevel@tonic-gate 45060Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_flags & SCSA2USB_FLAGS_PIPES_OPENED) == 0) { 45070Sstevel@tonic-gate 45080Sstevel@tonic-gate return; 45090Sstevel@tonic-gate } 45100Sstevel@tonic-gate 45110Sstevel@tonic-gate scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_CLOSING; 45120Sstevel@tonic-gate /* to avoid races, reset the flag first */ 45130Sstevel@tonic-gate scsa2usbp->scsa2usb_flags &= ~SCSA2USB_FLAGS_PIPES_OPENED; 45140Sstevel@tonic-gate 45150Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 45160Sstevel@tonic-gate 45170Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 45180Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkout_pipe, flags, NULL, NULL); 45190Sstevel@tonic-gate 45200Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 45210Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, flags, NULL, NULL); 45220Sstevel@tonic-gate 45230Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 45240Sstevel@tonic-gate if (SCSA2USB_IS_CBI(scsa2usbp)) { 45250Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 45260Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 45270Sstevel@tonic-gate scsa2usbp->scsa2usb_intr_pipe, flags, NULL, NULL); 45280Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 45290Sstevel@tonic-gate } 45300Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkout_pipe = NULL; 45310Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe = NULL; 45320Sstevel@tonic-gate scsa2usbp->scsa2usb_intr_pipe = NULL; 45330Sstevel@tonic-gate 45340Sstevel@tonic-gate scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_NORMAL; 45350Sstevel@tonic-gate } 45360Sstevel@tonic-gate 45370Sstevel@tonic-gate 45380Sstevel@tonic-gate /* 45390Sstevel@tonic-gate * scsa2usb_fill_up_cdb_lba: 45400Sstevel@tonic-gate * fill up command CDBs' LBA part 45410Sstevel@tonic-gate */ 45420Sstevel@tonic-gate static void 45430Sstevel@tonic-gate scsa2usb_fill_up_cdb_lba(scsa2usb_cmd_t *cmd, int lba) 45440Sstevel@tonic-gate { 45450Sstevel@tonic-gate /* zero cdb1, lba bits so they won't get copied in the new cdb */ 45460Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LUN] &= 0xE0; 45470Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_0] = lba >> 24; 45480Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_1] = lba >> 16; 45490Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = lba >> 8; 45500Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_3] = (uchar_t)lba; 45510Sstevel@tonic-gate cmd->cmd_lba = lba; 45520Sstevel@tonic-gate } 45530Sstevel@tonic-gate 45540Sstevel@tonic-gate 45550Sstevel@tonic-gate /* 45560Sstevel@tonic-gate * scsa2usb_fill_up_ReadCD_cdb_len: 45570Sstevel@tonic-gate * fill up READ_CD command CDBs' len part 45580Sstevel@tonic-gate */ 45590Sstevel@tonic-gate static void 45600Sstevel@tonic-gate scsa2usb_fill_up_ReadCD_cdb_len(scsa2usb_cmd_t *cmd, int len, int actual_len) 45610Sstevel@tonic-gate { 45620Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_0] = len >> 16; 45630Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_1] = len >> 8; 45640Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_2] = (uchar_t)len; 45650Sstevel@tonic-gate cmd->cmd_actual_len = (uchar_t)actual_len; 45660Sstevel@tonic-gate } 45670Sstevel@tonic-gate 45680Sstevel@tonic-gate 45690Sstevel@tonic-gate /* 45700Sstevel@tonic-gate * scsa2usb_fill_up_12byte_cdb_len: 45710Sstevel@tonic-gate * fill up generic 12-byte command CDBs' len part 45720Sstevel@tonic-gate */ 45730Sstevel@tonic-gate static void 45740Sstevel@tonic-gate scsa2usb_fill_up_12byte_cdb_len(scsa2usb_cmd_t *cmd, int len, int actual_len) 45750Sstevel@tonic-gate { 45760Sstevel@tonic-gate cmd->cmd_cdb[6] = len >> 24; 45770Sstevel@tonic-gate cmd->cmd_cdb[7] = len >> 16; 45780Sstevel@tonic-gate cmd->cmd_cdb[8] = len >> 8; 45790Sstevel@tonic-gate cmd->cmd_cdb[9] = (uchar_t)len; 45800Sstevel@tonic-gate cmd->cmd_actual_len = (uchar_t)actual_len; 45810Sstevel@tonic-gate } 45820Sstevel@tonic-gate 45830Sstevel@tonic-gate 45840Sstevel@tonic-gate /* 45850Sstevel@tonic-gate * scsa2usb_fill_up_cdb_len: 45860Sstevel@tonic-gate * fill up generic 10-byte command CDBs' len part 45870Sstevel@tonic-gate */ 45880Sstevel@tonic-gate static void 45890Sstevel@tonic-gate scsa2usb_fill_up_cdb_len(scsa2usb_cmd_t *cmd, int len) 45900Sstevel@tonic-gate { 45910Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LEN_0] = len >> 8; 45920Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LEN_1] = (uchar_t)len; 45930Sstevel@tonic-gate } 45940Sstevel@tonic-gate 45950Sstevel@tonic-gate 45960Sstevel@tonic-gate /* 45970Sstevel@tonic-gate * scsa2usb_read_cd_blk_size: 45980Sstevel@tonic-gate * For SCMD_READ_CD opcode (0xbe). Figure out the 45990Sstevel@tonic-gate * block size based on expected sector type field 46000Sstevel@tonic-gate * definition. See MMC SCSI Specs section 6.1.15 46010Sstevel@tonic-gate * 46020Sstevel@tonic-gate * Based on the value of the "expected_sector_type" 46030Sstevel@tonic-gate * field, the block size could be different. 46040Sstevel@tonic-gate */ 46050Sstevel@tonic-gate static int 46060Sstevel@tonic-gate scsa2usb_read_cd_blk_size(uchar_t expected_sector_type) 46070Sstevel@tonic-gate { 46080Sstevel@tonic-gate int blk_size; 46090Sstevel@tonic-gate 46100Sstevel@tonic-gate switch (expected_sector_type) { 46110Sstevel@tonic-gate case READ_CD_EST_CDDA: 46120Sstevel@tonic-gate blk_size = CDROM_BLK_2352; 46130Sstevel@tonic-gate break; 46140Sstevel@tonic-gate case READ_CD_EST_MODE2: 46150Sstevel@tonic-gate blk_size = CDROM_BLK_2336; 46160Sstevel@tonic-gate break; 46170Sstevel@tonic-gate case READ_CD_EST_MODE2FORM2: 46180Sstevel@tonic-gate blk_size = CDROM_BLK_2324; 46190Sstevel@tonic-gate break; 46200Sstevel@tonic-gate case READ_CD_EST_MODE2FORM1: 46210Sstevel@tonic-gate case READ_CD_EST_ALLTYPE: 46220Sstevel@tonic-gate case READ_CD_EST_MODE1: 46230Sstevel@tonic-gate default: 46240Sstevel@tonic-gate blk_size = CDROM_BLK_2048; 46250Sstevel@tonic-gate } 46260Sstevel@tonic-gate 46270Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, NULL, "scsa2usb_read_cd_blk_size: " 46280Sstevel@tonic-gate "est = 0x%x blk_size = %d", expected_sector_type, blk_size); 46290Sstevel@tonic-gate 46300Sstevel@tonic-gate return (blk_size); 46310Sstevel@tonic-gate } 46320Sstevel@tonic-gate 46330Sstevel@tonic-gate 46340Sstevel@tonic-gate /* 46350Sstevel@tonic-gate * scsa2usb_bp_to_mblk: 46360Sstevel@tonic-gate * Convert a bp to mblk_t. USBA framework understands mblk_t. 46370Sstevel@tonic-gate */ 46380Sstevel@tonic-gate static mblk_t * 46390Sstevel@tonic-gate scsa2usb_bp_to_mblk(scsa2usb_state_t *scsa2usbp) 46400Sstevel@tonic-gate { 46410Sstevel@tonic-gate size_t size; 46420Sstevel@tonic-gate mblk_t *mp; 46430Sstevel@tonic-gate struct buf *bp; 46440Sstevel@tonic-gate scsa2usb_cmd_t *cmd = PKT2CMD(scsa2usbp->scsa2usb_cur_pkt); 46450Sstevel@tonic-gate 46460Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 46470Sstevel@tonic-gate "scsa2usb_bp_to_mblk: "); 46480Sstevel@tonic-gate 46490Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_cur_pkt); 46500Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 46510Sstevel@tonic-gate 46520Sstevel@tonic-gate bp = cmd->cmd_bp; 46530Sstevel@tonic-gate 46540Sstevel@tonic-gate if (bp && (bp->b_bcount > 0)) { 46550Sstevel@tonic-gate size = ((bp->b_bcount > cmd->cmd_xfercount) ? 46564700Sfb209375 cmd->cmd_xfercount : bp->b_bcount); 46570Sstevel@tonic-gate } else { 46580Sstevel@tonic-gate 46590Sstevel@tonic-gate return (NULL); 46600Sstevel@tonic-gate } 46610Sstevel@tonic-gate 46620Sstevel@tonic-gate mp = esballoc_wait((uchar_t *)bp->b_un.b_addr + cmd->cmd_offset, 46637062Szl227052 size, BPRI_LO, &frnop); 46640Sstevel@tonic-gate 46650Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 46660Sstevel@tonic-gate "scsa2usb_bp_to_mblk: " 46676898Sfb209375 "mp=0x%p bp=0x%p pkt=0x%p off=0x%lx sz=%lu add=0x%p", 46686898Sfb209375 (void *)mp, (void *)bp, (void *)scsa2usbp->scsa2usb_cur_pkt, 46696898Sfb209375 cmd->cmd_offset, bp->b_bcount - cmd->cmd_offset, 46706898Sfb209375 (void *)bp->b_un.b_addr); 46710Sstevel@tonic-gate 46720Sstevel@tonic-gate mp->b_wptr += size; 46730Sstevel@tonic-gate cmd->cmd_offset += size; 46740Sstevel@tonic-gate 46750Sstevel@tonic-gate return (mp); 46760Sstevel@tonic-gate } 46770Sstevel@tonic-gate 46780Sstevel@tonic-gate 46790Sstevel@tonic-gate /* 46800Sstevel@tonic-gate * scsa2usb_handle_data_start: 46810Sstevel@tonic-gate * Initiate the data xfer. It could be IN/OUT direction. 46820Sstevel@tonic-gate * 46830Sstevel@tonic-gate * Data IN: 46840Sstevel@tonic-gate * Send out the bulk-xfer request 46850Sstevel@tonic-gate * if rval implies STALL 46860Sstevel@tonic-gate * clear endpoint stall and reset bulk-in pipe 46870Sstevel@tonic-gate * handle data read in so far; set cmd->cmd_done 46880Sstevel@tonic-gate * also adjust data xfer length accordingly 46890Sstevel@tonic-gate * else other error 46900Sstevel@tonic-gate * report back to transport 46910Sstevel@tonic-gate * typically transport will call reset recovery 46920Sstevel@tonic-gate * else (no error) 46930Sstevel@tonic-gate * return success 46940Sstevel@tonic-gate * 46950Sstevel@tonic-gate * Data OUT: 46960Sstevel@tonic-gate * Send out the bulk-xfer request 46970Sstevel@tonic-gate * if rval implies STALL 46980Sstevel@tonic-gate * clear endpoint stall and reset bulk-in pipe 46990Sstevel@tonic-gate * adjust data xfer length 47000Sstevel@tonic-gate * else other error 47010Sstevel@tonic-gate * report back to transport 47020Sstevel@tonic-gate * typically transport will call reset recovery 47030Sstevel@tonic-gate * else (no error) 47040Sstevel@tonic-gate * return success 47050Sstevel@tonic-gate * 47060Sstevel@tonic-gate * NOTE: We call this function only if there is xfercount. 47070Sstevel@tonic-gate */ 47080Sstevel@tonic-gate int 47090Sstevel@tonic-gate scsa2usb_handle_data_start(scsa2usb_state_t *scsa2usbp, 47100Sstevel@tonic-gate scsa2usb_cmd_t *cmd, usb_bulk_req_t *req) 47110Sstevel@tonic-gate { 47120Sstevel@tonic-gate int rval = USB_SUCCESS; 47130Sstevel@tonic-gate uint_t ept_addr; 47140Sstevel@tonic-gate usb_flags_t flags = USB_FLAGS_SLEEP; 47150Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 47160Sstevel@tonic-gate usb_req_attrs_t attrs = 0; 47170Sstevel@tonic-gate #else 47180Sstevel@tonic-gate usb_req_attrs_t attrs = USB_ATTRS_SHORT_XFER_OK; 47190Sstevel@tonic-gate #endif 47200Sstevel@tonic-gate 47210Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 47226898Sfb209375 "scsa2usb_handle_data_start: BEGIN cmd = %p, req = %p", 47236898Sfb209375 (void *)cmd, (void *)req); 47240Sstevel@tonic-gate 47250Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 47260Sstevel@tonic-gate 47270Sstevel@tonic-gate switch (cmd->cmd_dir) { 47280Sstevel@tonic-gate case USB_EP_DIR_IN: 47290Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 47300Sstevel@tonic-gate /* 47310Sstevel@tonic-gate * This case occurs when the host expects to receive 47320Sstevel@tonic-gate * more data than the device actually transfers. Hi > Di 47330Sstevel@tonic-gate */ 47340Sstevel@tonic-gate if (scsa2usb_test_case_5) { 47350Sstevel@tonic-gate usb_bulk_req_t *req2; 47360Sstevel@tonic-gate 47370Sstevel@tonic-gate req->bulk_len = cmd->cmd_xfercount - 1; 47380Sstevel@tonic-gate req->bulk_attributes = 0; 47390Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 47400Sstevel@tonic-gate SCSA2USB_FREE_MSG(req->bulk_data); 47410Sstevel@tonic-gate req->bulk_data = allocb_wait(req->bulk_len, BPRI_LO, 47420Sstevel@tonic-gate STR_NOSIG, NULL); 47430Sstevel@tonic-gate 47440Sstevel@tonic-gate ASSERT(req->bulk_timeout); 47450Sstevel@tonic-gate rval = usb_pipe_bulk_xfer( 47460Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, req, flags); 47470Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 47480Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, 47490Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, "rval = %x", rval); 47500Sstevel@tonic-gate 47510Sstevel@tonic-gate req2 = scsa2usb_init_bulk_req(scsa2usbp, 47520Sstevel@tonic-gate cmd->cmd_xfercount + 2, 47530Sstevel@tonic-gate cmd->cmd_timeout, 0, flags); 47540Sstevel@tonic-gate req2->bulk_len = cmd->cmd_xfercount + 2; 47550Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 47560Sstevel@tonic-gate 47570Sstevel@tonic-gate ASSERT(req2->bulk_timeout); 47580Sstevel@tonic-gate rval = usb_pipe_bulk_xfer( 47590Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, req2, flags); 47600Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 47610Sstevel@tonic-gate 47620Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, 47630Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 47640Sstevel@tonic-gate "TEST 5: Hi > Di: rval = 0x%x", rval); 47650Sstevel@tonic-gate scsa2usb_test_case_5 = 0; 47660Sstevel@tonic-gate usb_free_bulk_req(req2); 47670Sstevel@tonic-gate 47680Sstevel@tonic-gate return (rval); 47690Sstevel@tonic-gate } 47700Sstevel@tonic-gate 47710Sstevel@tonic-gate /* 47720Sstevel@tonic-gate * This happens when the host expects to send data to the 47730Sstevel@tonic-gate * device while the device intends to send data to the host. 47740Sstevel@tonic-gate */ 47750Sstevel@tonic-gate if (scsa2usb_test_case_8 && (cmd->cmd_cdb[0] == SCMD_READ_G1)) { 47760Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, 47770Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 47780Sstevel@tonic-gate "TEST 8: Hi <> Do: Step 2"); 47790Sstevel@tonic-gate scsa2usb_test_mblk(scsa2usbp, B_TRUE); 47800Sstevel@tonic-gate scsa2usb_test_case_8 = 0; 47810Sstevel@tonic-gate 47820Sstevel@tonic-gate return (rval); 47830Sstevel@tonic-gate } 47840Sstevel@tonic-gate #endif /* SCSA2USB_BULK_ONLY_TEST */ 47850Sstevel@tonic-gate 47860Sstevel@tonic-gate ept_addr = scsa2usbp->scsa2usb_bulkin_ept.bEndpointAddress; 47870Sstevel@tonic-gate req->bulk_len = cmd->cmd_xfercount; 47880Sstevel@tonic-gate req->bulk_attributes = attrs; 47890Sstevel@tonic-gate SCSA2USB_FREE_MSG(req->bulk_data); 47900Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 47910Sstevel@tonic-gate 47920Sstevel@tonic-gate req->bulk_data = esballoc_wait( 47934700Sfb209375 (uchar_t *)cmd->cmd_bp->b_un.b_addr + 47944700Sfb209375 cmd->cmd_offset, 47957062Szl227052 req->bulk_len, BPRI_LO, &frnop); 47960Sstevel@tonic-gate 47970Sstevel@tonic-gate ASSERT(req->bulk_timeout); 47980Sstevel@tonic-gate rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkin_pipe, 47994700Sfb209375 req, flags); 48000Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 48010Sstevel@tonic-gate 48020Sstevel@tonic-gate break; 48030Sstevel@tonic-gate 48040Sstevel@tonic-gate case USB_EP_DIR_OUT: 48050Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 48060Sstevel@tonic-gate /* 48070Sstevel@tonic-gate * This happens when the host expects to receive data 48080Sstevel@tonic-gate * from the device while the device intends to receive 48090Sstevel@tonic-gate * data from the host. 48100Sstevel@tonic-gate */ 48110Sstevel@tonic-gate if (scsa2usb_test_case_10 && 48120Sstevel@tonic-gate (cmd->cmd_cdb[0] == SCMD_WRITE_G1)) { 48130Sstevel@tonic-gate req->bulk_len = CSW_LEN; 48140Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 48150Sstevel@tonic-gate 48160Sstevel@tonic-gate ASSERT(req->bulk_timeout); 48170Sstevel@tonic-gate rval = usb_pipe_bulk_xfer( 48180Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, req, flags); 48190Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 48200Sstevel@tonic-gate 48210Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, 48220Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 48230Sstevel@tonic-gate "TEST 10: Ho <> Di: done rval = 0x%x", rval); 48240Sstevel@tonic-gate scsa2usb_test_case_10 = 0; 48250Sstevel@tonic-gate 48260Sstevel@tonic-gate return (rval); 48270Sstevel@tonic-gate } 48280Sstevel@tonic-gate #endif /* SCSA2USB_BULK_ONLY_TEST */ 48290Sstevel@tonic-gate 48300Sstevel@tonic-gate req->bulk_data = scsa2usb_bp_to_mblk(scsa2usbp); 48310Sstevel@tonic-gate if (req->bulk_data == NULL) { 48320Sstevel@tonic-gate 48330Sstevel@tonic-gate return (USB_FAILURE); 48340Sstevel@tonic-gate } 48350Sstevel@tonic-gate 48360Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 48370Sstevel@tonic-gate if (scsa2usb_test_case_11) { 48380Sstevel@tonic-gate /* 48390Sstevel@tonic-gate * Host expects to send data to the device and 48400Sstevel@tonic-gate * device doesn't expect to receive any data 48410Sstevel@tonic-gate */ 48420Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, 48430Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, "TEST 11: Ho > Do"); 48440Sstevel@tonic-gate 48450Sstevel@tonic-gate scsa2usb_test_mblk(scsa2usbp, B_FALSE); 48460Sstevel@tonic-gate scsa2usb_test_case_11 = 0; 48470Sstevel@tonic-gate } 48480Sstevel@tonic-gate #endif /* SCSA2USB_BULK_ONLY_TEST */ 48490Sstevel@tonic-gate 48500Sstevel@tonic-gate ept_addr = scsa2usbp->scsa2usb_bulkout_ept.bEndpointAddress; 4851*7492SZhigang.Lu@Sun.COM req->bulk_len = MBLKL(req->bulk_data); 48520Sstevel@tonic-gate req->bulk_timeout = scsa2usb_bulk_timeout(cmd->cmd_timeout); 48530Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 48540Sstevel@tonic-gate 48550Sstevel@tonic-gate ASSERT(req->bulk_timeout); 48560Sstevel@tonic-gate rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkout_pipe, 48574700Sfb209375 req, flags); 48580Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 48590Sstevel@tonic-gate break; 48600Sstevel@tonic-gate } 48610Sstevel@tonic-gate 48620Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 48630Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 48640Sstevel@tonic-gate "scsa2usb_handle_data_start: rval=%d cr=%d", rval, 48650Sstevel@tonic-gate req->bulk_completion_reason); 48660Sstevel@tonic-gate 48670Sstevel@tonic-gate if (rval != USB_SUCCESS) { 48680Sstevel@tonic-gate /* Handle Errors now */ 48690Sstevel@tonic-gate if (req->bulk_completion_reason == USB_CR_STALL) { 48700Sstevel@tonic-gate if (cmd->cmd_dir == USB_EP_DIR_IN) { 48710Sstevel@tonic-gate (void) scsa2usb_clear_ept_stall( 48720Sstevel@tonic-gate scsa2usbp, ept_addr, 48730Sstevel@tonic-gate scsa2usbp-> scsa2usb_bulkin_pipe, 48740Sstevel@tonic-gate "bulk-in"); 48750Sstevel@tonic-gate } else { 48760Sstevel@tonic-gate (void) scsa2usb_clear_ept_stall( 48770Sstevel@tonic-gate scsa2usbp, ept_addr, 48780Sstevel@tonic-gate scsa2usbp-> scsa2usb_bulkout_pipe, 48790Sstevel@tonic-gate "bulk-out"); 48800Sstevel@tonic-gate } 48810Sstevel@tonic-gate } 48820Sstevel@tonic-gate 48830Sstevel@tonic-gate /* no more data to transfer after this */ 48840Sstevel@tonic-gate cmd->cmd_done = 1; 48850Sstevel@tonic-gate } 48860Sstevel@tonic-gate 48870Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 48880Sstevel@tonic-gate "scsa2usb_handle_data_start: END %s data rval = %d", 48890Sstevel@tonic-gate (cmd->cmd_dir == USB_EP_DIR_IN) ? "bulk-in" : "bulk-out", rval); 48900Sstevel@tonic-gate 48910Sstevel@tonic-gate return (rval); 48920Sstevel@tonic-gate } 48930Sstevel@tonic-gate 48940Sstevel@tonic-gate 48950Sstevel@tonic-gate /* 48960Sstevel@tonic-gate * scsa2usb_handle_data_done: 48970Sstevel@tonic-gate * This function handles the completion of the data xfer. 48980Sstevel@tonic-gate * It also massages the inquiry data. This function may 48990Sstevel@tonic-gate * also be called after a stall. 49000Sstevel@tonic-gate */ 49010Sstevel@tonic-gate void 49020Sstevel@tonic-gate scsa2usb_handle_data_done(scsa2usb_state_t *scsa2usbp, 49030Sstevel@tonic-gate scsa2usb_cmd_t *cmd, usb_bulk_req_t *req) 49040Sstevel@tonic-gate { 49050Sstevel@tonic-gate struct buf *bp = cmd->cmd_bp; 49060Sstevel@tonic-gate struct scsi_pkt *pkt = scsa2usbp->scsa2usb_cur_pkt; 49070Sstevel@tonic-gate mblk_t *data = req->bulk_data; 4908*7492SZhigang.Lu@Sun.COM int len = data ? MBLKL(data) : 0; 49094834Sfb209375 uint32_t max_lba; 49100Sstevel@tonic-gate 49110Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 49120Sstevel@tonic-gate 49130Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 49140Sstevel@tonic-gate "scsa2usb_handle_data_done:\n\tcmd = 0x%p data = 0x%p len = 0x%x", 49156898Sfb209375 (void *)cmd, (void *)data, len); 49160Sstevel@tonic-gate 49170Sstevel@tonic-gate cmd->cmd_resid_xfercount = cmd->cmd_xfercount - len; 49180Sstevel@tonic-gate 49190Sstevel@tonic-gate if (len) { 49200Sstevel@tonic-gate uchar_t *p; 49215652Slg150142 uchar_t dtype; 49220Sstevel@tonic-gate scsa2usb_read_cap_t *cap; 49235652Slg150142 struct scsi_inquiry *inq; 49240Sstevel@tonic-gate 49250Sstevel@tonic-gate switch (cmd->cmd_cdb[SCSA2USB_OPCODE]) { 49260Sstevel@tonic-gate case SCMD_INQUIRY: 49270Sstevel@tonic-gate /* 49280Sstevel@tonic-gate * cache a copy of the inquiry data for our own use 49290Sstevel@tonic-gate * but ensure that we have at least up to 49300Sstevel@tonic-gate * inq_revision, inq_serial is not required. 49310Sstevel@tonic-gate * ignore inquiry data returned for inquiry commands 49320Sstevel@tonic-gate * with SCSI-3 EVPD, CmdDt bits set. 49330Sstevel@tonic-gate */ 49340Sstevel@tonic-gate if (((cmd->cmd_cdb[SCSA2USB_LUN] & 0x1f) == 0) && 49350Sstevel@tonic-gate (len >= SCSA2USB_MAX_INQ_LEN)) { 49365652Slg150142 inq = (struct scsi_inquiry *)data->b_rptr; 49375652Slg150142 dtype = inq->inq_dtype & DTYPE_MASK; 49385652Slg150142 /* 49395652Slg150142 * scsi framework sends zero byte write(10) cmd 49405652Slg150142 * to (Simplified) direct-access devices with 49415652Slg150142 * inquiry version > 2 for reservation changes. 49425652Slg150142 * But some USB devices don't support zero byte 49435652Slg150142 * write(10) even though they have inquiry 49445652Slg150142 * version > 2. Considering scsa2usb driver 49455652Slg150142 * doesn't support reservation and all the 49465652Slg150142 * reservation cmds are being faked, we fake 49475652Slg150142 * the inquiry version to 0 to make scsi 49485652Slg150142 * framework send test unit ready cmd which is 49495652Slg150142 * supported by all the usb devices. 49505652Slg150142 */ 49515652Slg150142 if (((dtype == DTYPE_DIRECT) || 49525652Slg150142 (dtype == DTYPE_RBC)) && 49535652Slg150142 (inq->inq_ansi > 2)) { 49545652Slg150142 inq->inq_ansi = 0; 49555652Slg150142 } 49565652Slg150142 49570Sstevel@tonic-gate bzero(&scsa2usbp->scsa2usb_lun_inquiry 49580Sstevel@tonic-gate [pkt->pkt_address.a_lun], 49590Sstevel@tonic-gate sizeof (struct scsi_inquiry)); 49600Sstevel@tonic-gate bcopy(data->b_rptr, 49610Sstevel@tonic-gate &scsa2usbp->scsa2usb_lun_inquiry 49620Sstevel@tonic-gate [pkt->pkt_address.a_lun], len); 49630Sstevel@tonic-gate } 49640Sstevel@tonic-gate 49650Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 49660Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 49670Sstevel@tonic-gate "scsi inquiry type = 0x%x", 49680Sstevel@tonic-gate scsa2usbp->scsa2usb_lun_inquiry 49690Sstevel@tonic-gate [pkt->pkt_address.a_lun].inq_dtype); 49700Sstevel@tonic-gate 49710Sstevel@tonic-gate cmd->cmd_done = 1; 49720Sstevel@tonic-gate goto handle_data; 49730Sstevel@tonic-gate 49740Sstevel@tonic-gate case SCMD_READ_CAPACITY: 49750Sstevel@tonic-gate cap = (scsa2usb_read_cap_t *)data->b_rptr; 49760Sstevel@tonic-gate 49770Sstevel@tonic-gate /* Figure out the logical block size */ 49780Sstevel@tonic-gate if ((len >= sizeof (struct scsa2usb_read_cap)) && 49790Sstevel@tonic-gate (req->bulk_completion_reason == USB_CR_OK)) { 49800Sstevel@tonic-gate scsa2usbp-> 49810Sstevel@tonic-gate scsa2usb_lbasize[pkt->pkt_address.a_lun] = 49820Sstevel@tonic-gate SCSA2USB_MK_32BIT( 49834700Sfb209375 cap->scsa2usb_read_cap_blen3, 49844700Sfb209375 cap->scsa2usb_read_cap_blen2, 49854700Sfb209375 cap->scsa2usb_read_cap_blen1, 49864700Sfb209375 cap->scsa2usb_read_cap_blen0); 49870Sstevel@tonic-gate 49884834Sfb209375 max_lba = SCSA2USB_MK_32BIT( 49894834Sfb209375 cap->scsa2usb_read_cap_lba3, 49904834Sfb209375 cap->scsa2usb_read_cap_lba2, 49914834Sfb209375 cap->scsa2usb_read_cap_lba1, 49924834Sfb209375 cap->scsa2usb_read_cap_lba0); 49934834Sfb209375 49944834Sfb209375 /* 49954834Sfb209375 * Some devices return total logical block 49964834Sfb209375 * number instead of highest logical block 49974834Sfb209375 * address. Adjust the value by minus 1. 49984834Sfb209375 */ 49994834Sfb209375 if (max_lba > 0 && (scsa2usbp->scsa2usb_attrs & 50004834Sfb209375 SCSA2USB_ATTRS_NO_CAP_ADJUST) == 0) { 50014834Sfb209375 max_lba -= 1; 50024834Sfb209375 cap->scsa2usb_read_cap_lba0 = 50034834Sfb209375 (uchar_t)(max_lba & 0xFF); 50044834Sfb209375 cap->scsa2usb_read_cap_lba1 = 50054834Sfb209375 (uchar_t)(max_lba >> 8 & 0xFF); 50064834Sfb209375 cap->scsa2usb_read_cap_lba2 = 50074834Sfb209375 (uchar_t)(max_lba >> 16 & 0xFF); 50084834Sfb209375 cap->scsa2usb_read_cap_lba3 = 50094834Sfb209375 (uchar_t)(max_lba >> 24 & 0xFF); 50104834Sfb209375 } 50114834Sfb209375 50124834Sfb209375 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 50130Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 50146898Sfb209375 "bytes in each logical block=0x%lx," 50154834Sfb209375 "number of total logical blocks=0x%x", 50164834Sfb209375 scsa2usbp-> 50174834Sfb209375 scsa2usb_lbasize[pkt->pkt_address.a_lun], 50184834Sfb209375 max_lba + 1); 50190Sstevel@tonic-gate } 50200Sstevel@tonic-gate cmd->cmd_done = 1; 50210Sstevel@tonic-gate goto handle_data; 50220Sstevel@tonic-gate 50230Sstevel@tonic-gate case SCMD_REQUEST_SENSE: 50240Sstevel@tonic-gate p = data->b_rptr; 50250Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 50260Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 50270Sstevel@tonic-gate "cdb: %x rqsense: " 50280Sstevel@tonic-gate "%x %x %x %x %x %x %x %x %x %x\n\t" 50290Sstevel@tonic-gate "%x %x %x %x %x %x %x %x %x %x", 50300Sstevel@tonic-gate cmd->cmd_cdb[0], 50310Sstevel@tonic-gate p[0], p[1], p[2], p[3], p[4], 50320Sstevel@tonic-gate p[5], p[6], p[7], p[8], p[9], 50330Sstevel@tonic-gate p[10], p[11], p[12], p[13], p[14], 50340Sstevel@tonic-gate p[15], p[16], p[17], p[18], p[19]); 50350Sstevel@tonic-gate 50360Sstevel@tonic-gate scsa2usbp->scsa2usb_last_cmd.status = p[2]; 50370Sstevel@tonic-gate cmd->cmd_done = 1; 50380Sstevel@tonic-gate /* FALLTHROUGH */ 50390Sstevel@tonic-gate 50405789Ssl147100 default: 50410Sstevel@tonic-gate handle_data: 50420Sstevel@tonic-gate if (bp && len && (cmd->cmd_dir == USB_EP_DIR_IN)) { 50430Sstevel@tonic-gate /* 50440Sstevel@tonic-gate * we don't have to copy the data, the 50450Sstevel@tonic-gate * data pointers for the mblk_t for 50460Sstevel@tonic-gate * the bulk-in xfer points to the 50470Sstevel@tonic-gate * struct buf * data. 50480Sstevel@tonic-gate */ 50490Sstevel@tonic-gate cmd->cmd_offset += len; 50500Sstevel@tonic-gate } 50510Sstevel@tonic-gate 50520Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 50530Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 50545789Ssl147100 "len = 0x%x total = 0x%lx offset = 0x%lx", 50555789Ssl147100 len, cmd->cmd_total_xfercount, cmd->cmd_offset); 50560Sstevel@tonic-gate 50570Sstevel@tonic-gate /* 50580Sstevel@tonic-gate * update total_xfercount now but it may be 50590Sstevel@tonic-gate * adjusted after receiving the residue 50600Sstevel@tonic-gate */ 50610Sstevel@tonic-gate cmd->cmd_total_xfercount -= len; 50620Sstevel@tonic-gate 50630Sstevel@tonic-gate if ((req->bulk_completion_reason != USB_CR_OK) || 50640Sstevel@tonic-gate (cmd->cmd_resid_xfercount != 0) || 50650Sstevel@tonic-gate (cmd->cmd_total_xfercount == 0)) { 50660Sstevel@tonic-gate /* set pkt_resid to total to be sure */ 50670Sstevel@tonic-gate pkt->pkt_resid = cmd->cmd_total_xfercount; 50680Sstevel@tonic-gate cmd->cmd_done = 1; 50690Sstevel@tonic-gate } 50700Sstevel@tonic-gate 50710Sstevel@tonic-gate break; 50720Sstevel@tonic-gate } 50730Sstevel@tonic-gate } else { 50740Sstevel@tonic-gate if (cmd->cmd_dir == USB_EP_DIR_OUT) { 50750Sstevel@tonic-gate if (cmd->cmd_total_xfercount == 0) { 50760Sstevel@tonic-gate cmd->cmd_done = 1; 50770Sstevel@tonic-gate } 50780Sstevel@tonic-gate } 50790Sstevel@tonic-gate } 50800Sstevel@tonic-gate } 50810Sstevel@tonic-gate 50820Sstevel@tonic-gate 50830Sstevel@tonic-gate /* 50840Sstevel@tonic-gate * scsa2usb_init_bulk_req: 50850Sstevel@tonic-gate * Allocate (synchronously) and fill in a bulk-request 50860Sstevel@tonic-gate */ 50870Sstevel@tonic-gate usb_bulk_req_t * 50880Sstevel@tonic-gate scsa2usb_init_bulk_req(scsa2usb_state_t *scsa2usbp, size_t length, 50890Sstevel@tonic-gate uint_t timeout, usb_req_attrs_t attrs, usb_flags_t flags) 50900Sstevel@tonic-gate { 50910Sstevel@tonic-gate usb_bulk_req_t *req; 50920Sstevel@tonic-gate 50930Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 50940Sstevel@tonic-gate 50950Sstevel@tonic-gate req = usb_alloc_bulk_req(scsa2usbp->scsa2usb_dip, length, 50960Sstevel@tonic-gate flags | USB_FLAGS_SLEEP); 50970Sstevel@tonic-gate 5098*7492SZhigang.Lu@Sun.COM req->bulk_len = (uint_t)length; /* xfer length */ 50990Sstevel@tonic-gate req->bulk_timeout = scsa2usb_bulk_timeout(timeout); /* xfer timeout */ 51000Sstevel@tonic-gate req->bulk_attributes = attrs; /* xfer attrs */ 51010Sstevel@tonic-gate req->bulk_client_private = (usb_opaque_t)scsa2usbp; /* statep */ 51020Sstevel@tonic-gate 51030Sstevel@tonic-gate return (req); 51040Sstevel@tonic-gate } 51050Sstevel@tonic-gate 51060Sstevel@tonic-gate 51070Sstevel@tonic-gate /* 51080Sstevel@tonic-gate * scsa2usb_bulk_timeout: 51090Sstevel@tonic-gate * ensure that bulk requests do not have infinite timeout values 51100Sstevel@tonic-gate */ 51110Sstevel@tonic-gate int 51120Sstevel@tonic-gate scsa2usb_bulk_timeout(int timeout) 51130Sstevel@tonic-gate { 51140Sstevel@tonic-gate return ((timeout == 0) ? scsa2usb_long_timeout : timeout); 51150Sstevel@tonic-gate } 51160Sstevel@tonic-gate 51170Sstevel@tonic-gate 51180Sstevel@tonic-gate /* 51190Sstevel@tonic-gate * scsa2usb_clear_ept_stall: 51200Sstevel@tonic-gate * clear endpoint stall and reset pipes 51210Sstevel@tonic-gate */ 51220Sstevel@tonic-gate int 51230Sstevel@tonic-gate scsa2usb_clear_ept_stall(scsa2usb_state_t *scsa2usbp, uint_t ept_addr, 51240Sstevel@tonic-gate usb_pipe_handle_t ph, char *what) 51250Sstevel@tonic-gate { 51260Sstevel@tonic-gate int rval; 51270Sstevel@tonic-gate dev_info_t *dip = scsa2usbp->scsa2usb_dip; 51280Sstevel@tonic-gate 51290Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 51300Sstevel@tonic-gate if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 51310Sstevel@tonic-gate 51320Sstevel@tonic-gate return (USB_FAILURE); 51330Sstevel@tonic-gate } 51340Sstevel@tonic-gate 51350Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 51360Sstevel@tonic-gate rval = usb_clr_feature(dip, USB_DEV_REQ_RCPT_EP, 0, ept_addr, 51370Sstevel@tonic-gate USB_FLAGS_SLEEP, NULL, NULL); 51380Sstevel@tonic-gate 51390Sstevel@tonic-gate usb_pipe_reset(dip, ph, USB_FLAGS_SLEEP, NULL, NULL); 51400Sstevel@tonic-gate 51410Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 51420Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 51430Sstevel@tonic-gate "scsa2usb_clear_ept_stall: on %s: ept = 0x%x rval = %d", 51440Sstevel@tonic-gate what, ept_addr, rval); 51450Sstevel@tonic-gate 51460Sstevel@tonic-gate return (rval); 51470Sstevel@tonic-gate } 51480Sstevel@tonic-gate 51490Sstevel@tonic-gate 51500Sstevel@tonic-gate /* 51510Sstevel@tonic-gate * scsa2usb_pkt_completion: 51520Sstevel@tonic-gate * Handle pkt completion. 51530Sstevel@tonic-gate */ 51540Sstevel@tonic-gate static void 51550Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usb_state_t *scsa2usbp, struct scsi_pkt *pkt) 51560Sstevel@tonic-gate { 51570Sstevel@tonic-gate scsa2usb_cmd_t *cmd = PKT2CMD(pkt); 51584700Sfb209375 size_t len; 51590Sstevel@tonic-gate 51600Sstevel@tonic-gate ASSERT(pkt); 51610Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 51620Sstevel@tonic-gate 51630Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 51640Sstevel@tonic-gate "scsa2usb_pkt_completion:\n\tscsa2usbp = 0x%p " 51650Sstevel@tonic-gate "reason=%d, status=%d state=0x%x stats=0x%x resid=0x%lx", 51666898Sfb209375 (void *)scsa2usbp, pkt->pkt_reason, *(pkt->pkt_scbp), 51670Sstevel@tonic-gate pkt->pkt_state, pkt->pkt_statistics, pkt->pkt_resid); 51680Sstevel@tonic-gate 51690Sstevel@tonic-gate if (pkt->pkt_reason == CMD_CMPLT) { 51700Sstevel@tonic-gate pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | 51714700Sfb209375 STATE_SENT_CMD | STATE_GOT_STATUS; 51720Sstevel@tonic-gate if (cmd->cmd_xfercount) { 51730Sstevel@tonic-gate pkt->pkt_state |= STATE_XFERRED_DATA; 51740Sstevel@tonic-gate } 51750Sstevel@tonic-gate } else { 51760Sstevel@tonic-gate pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | 51774700Sfb209375 STATE_SENT_CMD; 51780Sstevel@tonic-gate } 51790Sstevel@tonic-gate 51800Sstevel@tonic-gate /* 51810Sstevel@tonic-gate * don't zap the current state when in panic as this will 51820Sstevel@tonic-gate * make debugging harder 51830Sstevel@tonic-gate */ 51840Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_cur_pkt == pkt) && !ddi_in_panic()) { 51850Sstevel@tonic-gate SCSA2USB_RESET_CUR_PKT(scsa2usbp); 51860Sstevel@tonic-gate 51874700Sfb209375 len = sizeof (scsa2usbp->scsa2usb_last_cmd.cdb); 51884700Sfb209375 bzero(scsa2usbp->scsa2usb_last_cmd.cdb, len); 51894700Sfb209375 51904700Sfb209375 len = (len < cmd->cmd_cdblen) ? len : cmd->cmd_cdblen; 51914700Sfb209375 USB_DPRINTF_L3(DPRINT_MASK_SCSA, 51924700Sfb209375 scsa2usbp->scsa2usb_log_handle, 51936898Sfb209375 "scsa2usb_pkt_completion: save last cmd, len=%ld", len); 51944700Sfb209375 51950Sstevel@tonic-gate /* save the last command */ 51964700Sfb209375 bcopy(pkt->pkt_cdbp, scsa2usbp->scsa2usb_last_cmd.cdb, len); 51970Sstevel@tonic-gate 51980Sstevel@tonic-gate /* reset the scsa2usb_last_cmd.status value */ 51990Sstevel@tonic-gate if ((pkt->pkt_cdbp[0] != SCMD_REQUEST_SENSE) && 52000Sstevel@tonic-gate (pkt->pkt_cdbp[0] != SCMD_INQUIRY)) { 52010Sstevel@tonic-gate scsa2usbp->scsa2usb_last_cmd.status = 0; 52020Sstevel@tonic-gate } 52030Sstevel@tonic-gate 52040Sstevel@tonic-gate /* 52050Sstevel@tonic-gate * set pkt state to NONE *before* calling back as the target 52060Sstevel@tonic-gate * driver will immediately submit the next packet 52070Sstevel@tonic-gate */ 52080Sstevel@tonic-gate scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_NONE; 52090Sstevel@tonic-gate } 52100Sstevel@tonic-gate 52110Sstevel@tonic-gate if (pkt->pkt_comp) { 52120Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 52130Sstevel@tonic-gate pkt->pkt_comp(pkt); 52140Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 52150Sstevel@tonic-gate 52160Sstevel@tonic-gate } 52170Sstevel@tonic-gate } 52180Sstevel@tonic-gate 52190Sstevel@tonic-gate 52200Sstevel@tonic-gate /* 52210Sstevel@tonic-gate * Even handling functions: 52220Sstevel@tonic-gate * 52230Sstevel@tonic-gate * scsa2usb_reconnect_event_cb: 52240Sstevel@tonic-gate * event handling 52250Sstevel@tonic-gate */ 52260Sstevel@tonic-gate static int 52270Sstevel@tonic-gate scsa2usb_reconnect_event_cb(dev_info_t *dip) 52280Sstevel@tonic-gate { 52290Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = 52300Sstevel@tonic-gate ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 52310Sstevel@tonic-gate dev_info_t *cdip; 52320Sstevel@tonic-gate int circ; 52330Sstevel@tonic-gate int rval = USB_SUCCESS; 52340Sstevel@tonic-gate 52350Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 52360Sstevel@tonic-gate 52370Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 52386898Sfb209375 "scsa2usb_reconnect_event_cb: dip = 0x%p", (void *)dip); 52390Sstevel@tonic-gate 52400Sstevel@tonic-gate scsa2usb_restore_device_state(dip, scsa2usbp); 52410Sstevel@tonic-gate 5242880Sfrits USB_DPRINTF_L0(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 5243880Sfrits "Reinserted device is accessible again."); 5244880Sfrits 52450Sstevel@tonic-gate ndi_devi_enter(dip, &circ); 52460Sstevel@tonic-gate for (cdip = ddi_get_child(dip); cdip; ) { 52470Sstevel@tonic-gate dev_info_t *next = ddi_get_next_sibling(cdip); 52480Sstevel@tonic-gate 52490Sstevel@tonic-gate mutex_enter(&DEVI(cdip)->devi_lock); 52500Sstevel@tonic-gate DEVI_SET_DEVICE_REINSERTED(cdip); 52510Sstevel@tonic-gate mutex_exit(&DEVI(cdip)->devi_lock); 52520Sstevel@tonic-gate 52530Sstevel@tonic-gate cdip = next; 52540Sstevel@tonic-gate } 52550Sstevel@tonic-gate ndi_devi_exit(dip, circ); 52560Sstevel@tonic-gate 52570Sstevel@tonic-gate /* stop suppressing warnings */ 52580Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 52590Sstevel@tonic-gate scsa2usbp->scsa2usb_warning_given = B_FALSE; 52600Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 52610Sstevel@tonic-gate 52620Sstevel@tonic-gate if (scsa2usbp->scsa2usb_ugen_hdl) { 52630Sstevel@tonic-gate rval = usb_ugen_reconnect_ev_cb( 52644700Sfb209375 scsa2usbp->scsa2usb_ugen_hdl); 52650Sstevel@tonic-gate } 52660Sstevel@tonic-gate 52670Sstevel@tonic-gate return (rval); 52680Sstevel@tonic-gate } 52690Sstevel@tonic-gate 52700Sstevel@tonic-gate 52710Sstevel@tonic-gate /* 52720Sstevel@tonic-gate * scsa2usb_all_waitQs_empty: 52730Sstevel@tonic-gate * check if all waitQs empty 52740Sstevel@tonic-gate */ 52750Sstevel@tonic-gate static int 52760Sstevel@tonic-gate scsa2usb_all_waitQs_empty(scsa2usb_state_t *scsa2usbp) 52770Sstevel@tonic-gate { 52780Sstevel@tonic-gate uint_t lun; 52790Sstevel@tonic-gate 52800Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 52810Sstevel@tonic-gate if (usba_list_entry_count( 52820Sstevel@tonic-gate &scsa2usbp->scsa2usb_waitQ[lun])) { 52830Sstevel@tonic-gate 52840Sstevel@tonic-gate return (USB_FAILURE); 52850Sstevel@tonic-gate } 52860Sstevel@tonic-gate } 52870Sstevel@tonic-gate 52880Sstevel@tonic-gate return (USB_SUCCESS); 52890Sstevel@tonic-gate } 52900Sstevel@tonic-gate 52910Sstevel@tonic-gate 52920Sstevel@tonic-gate /* 52930Sstevel@tonic-gate * scsa2usb_disconnect_event_cb: 52940Sstevel@tonic-gate * callback for disconnect events 52950Sstevel@tonic-gate */ 52960Sstevel@tonic-gate static int 52970Sstevel@tonic-gate scsa2usb_disconnect_event_cb(dev_info_t *dip) 52980Sstevel@tonic-gate { 52990Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = 53000Sstevel@tonic-gate ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 53010Sstevel@tonic-gate dev_info_t *cdip; 53020Sstevel@tonic-gate int circ, i; 53030Sstevel@tonic-gate int rval = USB_SUCCESS; 53040Sstevel@tonic-gate 53050Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 53060Sstevel@tonic-gate 53070Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 53086898Sfb209375 "scsa2usb_disconnect_event_cb: dip = 0x%p", (void *)dip); 53090Sstevel@tonic-gate 53100Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 53110Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_DISCONNECTED; 53120Sstevel@tonic-gate 53130Sstevel@tonic-gate /* 53140Sstevel@tonic-gate * wait till the work thread is done, carry on regardless 53150Sstevel@tonic-gate * if not. 53160Sstevel@tonic-gate */ 53170Sstevel@tonic-gate for (i = 0; i < SCSA2USB_DRAIN_TIMEOUT; i++) { 53180Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_work_thread_id == NULL) && 53190Sstevel@tonic-gate (scsa2usbp->scsa2usb_cur_pkt == NULL) && 53200Sstevel@tonic-gate (scsa2usb_all_waitQs_empty(scsa2usbp) == 53210Sstevel@tonic-gate USB_SUCCESS)) { 53220Sstevel@tonic-gate 53230Sstevel@tonic-gate break; 53240Sstevel@tonic-gate } 53250Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 53260Sstevel@tonic-gate delay(drv_usectohz(1000000)); 53270Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 53280Sstevel@tonic-gate } 53290Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 53300Sstevel@tonic-gate 53310Sstevel@tonic-gate ndi_devi_enter(dip, &circ); 53320Sstevel@tonic-gate for (cdip = ddi_get_child(dip); cdip; ) { 53330Sstevel@tonic-gate dev_info_t *next = ddi_get_next_sibling(cdip); 53340Sstevel@tonic-gate 53350Sstevel@tonic-gate mutex_enter(&DEVI(cdip)->devi_lock); 53360Sstevel@tonic-gate DEVI_SET_DEVICE_REMOVED(cdip); 53370Sstevel@tonic-gate mutex_exit(&DEVI(cdip)->devi_lock); 53380Sstevel@tonic-gate 53390Sstevel@tonic-gate cdip = next; 53400Sstevel@tonic-gate } 53410Sstevel@tonic-gate ndi_devi_exit(dip, circ); 53420Sstevel@tonic-gate 53430Sstevel@tonic-gate if (scsa2usbp->scsa2usb_ugen_hdl) { 53440Sstevel@tonic-gate rval = usb_ugen_disconnect_ev_cb( 53454700Sfb209375 scsa2usbp->scsa2usb_ugen_hdl); 53460Sstevel@tonic-gate } 53470Sstevel@tonic-gate 53480Sstevel@tonic-gate return (rval); 53490Sstevel@tonic-gate } 53500Sstevel@tonic-gate 53510Sstevel@tonic-gate 53520Sstevel@tonic-gate /* 53530Sstevel@tonic-gate * PM support 53540Sstevel@tonic-gate * 53550Sstevel@tonic-gate * scsa2usb_create_pm_components: 53560Sstevel@tonic-gate * create the pm components required for power management 53570Sstevel@tonic-gate * no mutex is need when calling USBA interfaces 53580Sstevel@tonic-gate */ 53590Sstevel@tonic-gate static void 53600Sstevel@tonic-gate scsa2usb_create_pm_components(dev_info_t *dip, scsa2usb_state_t *scsa2usbp) 53610Sstevel@tonic-gate { 53620Sstevel@tonic-gate scsa2usb_power_t *pm; 53630Sstevel@tonic-gate uint_t pwr_states; 53640Sstevel@tonic-gate 53650Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 53660Sstevel@tonic-gate 53670Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 53680Sstevel@tonic-gate "scsa2usb_create_pm_components: dip = 0x%p, scsa2usbp = 0x%p", 53696898Sfb209375 (void *)dip, (void *)scsa2usbp); 53700Sstevel@tonic-gate 53710Sstevel@tonic-gate /* 53720Sstevel@tonic-gate * determine if this device is on the blacklist 53730Sstevel@tonic-gate * or if a conf file entry has disabled PM 53740Sstevel@tonic-gate */ 53750Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_PM) == 0) { 53760Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 53770Sstevel@tonic-gate "device cannot be power managed"); 53780Sstevel@tonic-gate 53790Sstevel@tonic-gate return; 53800Sstevel@tonic-gate } 53810Sstevel@tonic-gate 53820Sstevel@tonic-gate /* Allocate the PM state structure */ 53830Sstevel@tonic-gate pm = kmem_zalloc(sizeof (scsa2usb_power_t), KM_SLEEP); 53840Sstevel@tonic-gate 53850Sstevel@tonic-gate scsa2usbp->scsa2usb_pm = pm; 53860Sstevel@tonic-gate pm->scsa2usb_current_power = USB_DEV_OS_FULL_PWR; 53870Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 53880Sstevel@tonic-gate 53890Sstevel@tonic-gate if (usb_create_pm_components(dip, &pwr_states) == 53900Sstevel@tonic-gate USB_SUCCESS) { 53910Sstevel@tonic-gate if (usb_handle_remote_wakeup(dip, 53920Sstevel@tonic-gate USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) { 53930Sstevel@tonic-gate pm->scsa2usb_wakeup_enabled = 1; 53940Sstevel@tonic-gate } 53950Sstevel@tonic-gate 53960Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 53970Sstevel@tonic-gate pm->scsa2usb_pwr_states = (uint8_t)pwr_states; 5398189Sfrits scsa2usb_raise_power(scsa2usbp); 53990Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 54000Sstevel@tonic-gate } 54010Sstevel@tonic-gate 54020Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 54030Sstevel@tonic-gate } 54040Sstevel@tonic-gate 54050Sstevel@tonic-gate 54060Sstevel@tonic-gate /* 54070Sstevel@tonic-gate * scsa2usb_raise_power: 54080Sstevel@tonic-gate * check if the device is using full power or not 54090Sstevel@tonic-gate */ 54100Sstevel@tonic-gate static void 54110Sstevel@tonic-gate scsa2usb_raise_power(scsa2usb_state_t *scsa2usbp) 54120Sstevel@tonic-gate { 54130Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 54140Sstevel@tonic-gate "scsa2usb_raise_power:"); 54150Sstevel@tonic-gate 54160Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 54170Sstevel@tonic-gate 54180Sstevel@tonic-gate if (scsa2usbp->scsa2usb_pm) { 54190Sstevel@tonic-gate scsa2usb_pm_busy_component(scsa2usbp); 5420189Sfrits if (scsa2usbp->scsa2usb_pm->scsa2usb_current_power != 5421189Sfrits USB_DEV_OS_FULL_PWR) { 54220Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 54230Sstevel@tonic-gate (void) pm_raise_power(scsa2usbp->scsa2usb_dip, 54240Sstevel@tonic-gate 0, USB_DEV_OS_FULL_PWR); 54250Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 54260Sstevel@tonic-gate } 54270Sstevel@tonic-gate } 54280Sstevel@tonic-gate } 54290Sstevel@tonic-gate 54300Sstevel@tonic-gate 54310Sstevel@tonic-gate /* 54320Sstevel@tonic-gate * functions to handle power transition for OS levels 0 -> 3 54330Sstevel@tonic-gate */ 54340Sstevel@tonic-gate static int 54350Sstevel@tonic-gate scsa2usb_pwrlvl0(scsa2usb_state_t *scsa2usbp) 54360Sstevel@tonic-gate { 54370Sstevel@tonic-gate int rval; 54380Sstevel@tonic-gate 54390Sstevel@tonic-gate switch (scsa2usbp->scsa2usb_dev_state) { 54400Sstevel@tonic-gate case USB_DEV_ONLINE: 54410Sstevel@tonic-gate /* Deny the powerdown request if the device is busy */ 54420Sstevel@tonic-gate if (scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy != 0) { 54430Sstevel@tonic-gate 54440Sstevel@tonic-gate return (USB_FAILURE); 54450Sstevel@tonic-gate } 54460Sstevel@tonic-gate 54470Sstevel@tonic-gate /* 54480Sstevel@tonic-gate * stop polling on interrupt pipe 54490Sstevel@tonic-gate */ 54500Sstevel@tonic-gate scsa2usb_cbi_stop_intr_polling(scsa2usbp); 54510Sstevel@tonic-gate 54520Sstevel@tonic-gate /* Issue USB D3 command to the device here */ 54530Sstevel@tonic-gate rval = usb_set_device_pwrlvl3(scsa2usbp->scsa2usb_dip); 54540Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS); 54550Sstevel@tonic-gate 54560Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_PWRED_DOWN; 54570Sstevel@tonic-gate 54580Sstevel@tonic-gate /* FALLTHRU */ 54590Sstevel@tonic-gate case USB_DEV_DISCONNECTED: 54600Sstevel@tonic-gate case USB_DEV_SUSPENDED: 54610Sstevel@tonic-gate case USB_DEV_PWRED_DOWN: 54620Sstevel@tonic-gate default: 54630Sstevel@tonic-gate scsa2usbp->scsa2usb_pm->scsa2usb_current_power = 54644700Sfb209375 USB_DEV_OS_PWR_OFF; 54650Sstevel@tonic-gate 54660Sstevel@tonic-gate return (USB_SUCCESS); 54670Sstevel@tonic-gate } 54680Sstevel@tonic-gate } 54690Sstevel@tonic-gate 54700Sstevel@tonic-gate 54710Sstevel@tonic-gate static int 54720Sstevel@tonic-gate scsa2usb_pwrlvl1(scsa2usb_state_t *scsa2usbp) 54730Sstevel@tonic-gate { 54740Sstevel@tonic-gate int rval; 54750Sstevel@tonic-gate 54760Sstevel@tonic-gate /* Issue USB D2 command to the device here */ 54770Sstevel@tonic-gate rval = usb_set_device_pwrlvl2(scsa2usbp->scsa2usb_dip); 54780Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS); 54790Sstevel@tonic-gate 54800Sstevel@tonic-gate return (DDI_FAILURE); 54810Sstevel@tonic-gate } 54820Sstevel@tonic-gate 54830Sstevel@tonic-gate 54840Sstevel@tonic-gate static int 54850Sstevel@tonic-gate scsa2usb_pwrlvl2(scsa2usb_state_t *scsa2usbp) 54860Sstevel@tonic-gate { 54870Sstevel@tonic-gate int rval; 54880Sstevel@tonic-gate 54890Sstevel@tonic-gate /* Issue USB D1 command to the device here */ 54900Sstevel@tonic-gate rval = usb_set_device_pwrlvl1(scsa2usbp->scsa2usb_dip); 54910Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS); 54920Sstevel@tonic-gate 54930Sstevel@tonic-gate return (DDI_FAILURE); 54940Sstevel@tonic-gate } 54950Sstevel@tonic-gate 54960Sstevel@tonic-gate 54970Sstevel@tonic-gate static int 54980Sstevel@tonic-gate scsa2usb_pwrlvl3(scsa2usb_state_t *scsa2usbp) 54990Sstevel@tonic-gate { 55000Sstevel@tonic-gate int rval; 55010Sstevel@tonic-gate 55020Sstevel@tonic-gate /* 55030Sstevel@tonic-gate * PM framework tries to put us in full power 55040Sstevel@tonic-gate * during system shutdown. If we are disconnected 55050Sstevel@tonic-gate * return success anyways 55060Sstevel@tonic-gate */ 55070Sstevel@tonic-gate if (scsa2usbp->scsa2usb_dev_state != USB_DEV_DISCONNECTED) { 55080Sstevel@tonic-gate /* Issue USB D0 command to the device here */ 55090Sstevel@tonic-gate rval = usb_set_device_pwrlvl0(scsa2usbp->scsa2usb_dip); 55100Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS); 55110Sstevel@tonic-gate 55120Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_ONLINE; 55130Sstevel@tonic-gate } 55140Sstevel@tonic-gate scsa2usbp->scsa2usb_pm->scsa2usb_current_power = USB_DEV_OS_FULL_PWR; 55150Sstevel@tonic-gate 55160Sstevel@tonic-gate return (DDI_SUCCESS); 55170Sstevel@tonic-gate } 55180Sstevel@tonic-gate 55190Sstevel@tonic-gate 55200Sstevel@tonic-gate /* 55210Sstevel@tonic-gate * scsa2usb_power: 55220Sstevel@tonic-gate * power entry point 55230Sstevel@tonic-gate */ 55240Sstevel@tonic-gate /* ARGSUSED */ 55250Sstevel@tonic-gate static int 55260Sstevel@tonic-gate scsa2usb_power(dev_info_t *dip, int comp, int level) 55270Sstevel@tonic-gate { 55280Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 55290Sstevel@tonic-gate scsa2usb_power_t *pm; 55300Sstevel@tonic-gate int rval = DDI_FAILURE; 55310Sstevel@tonic-gate 55320Sstevel@tonic-gate scsa2usbp = ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 55330Sstevel@tonic-gate 55340Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 55350Sstevel@tonic-gate "scsa2usb_power: Begin scsa2usbp (%p): level = %d", 55366898Sfb209375 (void *)scsa2usbp, level); 55370Sstevel@tonic-gate 55380Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 55390Sstevel@tonic-gate if (SCSA2USB_BUSY(scsa2usbp)) { 55400Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 55410Sstevel@tonic-gate "scsa2usb_power: busy"); 55420Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 55430Sstevel@tonic-gate 55440Sstevel@tonic-gate return (rval); 55450Sstevel@tonic-gate } 55460Sstevel@tonic-gate 55470Sstevel@tonic-gate pm = scsa2usbp->scsa2usb_pm; 55480Sstevel@tonic-gate if (pm == NULL) { 55490Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 55500Sstevel@tonic-gate "scsa2usb_power: pm NULL"); 55510Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 55520Sstevel@tonic-gate 55530Sstevel@tonic-gate return (rval); 55540Sstevel@tonic-gate } 55550Sstevel@tonic-gate 55560Sstevel@tonic-gate /* check if we are transitioning to a legal power level */ 55570Sstevel@tonic-gate if (USB_DEV_PWRSTATE_OK(pm->scsa2usb_pwr_states, level)) { 55580Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 55590Sstevel@tonic-gate "scsa2usb_power: illegal power level = %d " 55600Sstevel@tonic-gate "pwr_states: %x", level, pm->scsa2usb_pwr_states); 55610Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 55620Sstevel@tonic-gate 55630Sstevel@tonic-gate return (rval); 55640Sstevel@tonic-gate } 55650Sstevel@tonic-gate 55660Sstevel@tonic-gate switch (level) { 55670Sstevel@tonic-gate case USB_DEV_OS_PWR_OFF : 55680Sstevel@tonic-gate rval = scsa2usb_pwrlvl0(scsa2usbp); 55690Sstevel@tonic-gate break; 55700Sstevel@tonic-gate case USB_DEV_OS_PWR_1 : 55710Sstevel@tonic-gate rval = scsa2usb_pwrlvl1(scsa2usbp); 55720Sstevel@tonic-gate break; 55730Sstevel@tonic-gate case USB_DEV_OS_PWR_2 : 55740Sstevel@tonic-gate rval = scsa2usb_pwrlvl2(scsa2usbp); 55750Sstevel@tonic-gate break; 55760Sstevel@tonic-gate case USB_DEV_OS_FULL_PWR : 55770Sstevel@tonic-gate rval = scsa2usb_pwrlvl3(scsa2usbp); 55780Sstevel@tonic-gate break; 55790Sstevel@tonic-gate } 55800Sstevel@tonic-gate 55810Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 55820Sstevel@tonic-gate 55830Sstevel@tonic-gate return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 55840Sstevel@tonic-gate } 55850Sstevel@tonic-gate 55860Sstevel@tonic-gate 55870Sstevel@tonic-gate static void 5588189Sfrits scsa2usb_pm_busy_component(scsa2usb_state_t *scsa2usbp) 55890Sstevel@tonic-gate { 5590189Sfrits ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 5591189Sfrits 5592189Sfrits if (scsa2usbp->scsa2usb_pm) { 5593189Sfrits scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy++; 5594189Sfrits 5595189Sfrits USB_DPRINTF_L4(DPRINT_MASK_PM, 5596189Sfrits scsa2usbp->scsa2usb_log_handle, 5597189Sfrits "scsa2usb_pm_busy_component: %d", 5598189Sfrits scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy); 5599189Sfrits 5600189Sfrits mutex_exit(&scsa2usbp->scsa2usb_mutex); 5601189Sfrits 5602189Sfrits if (pm_busy_component(scsa2usbp->scsa2usb_dip, 0) != 5603189Sfrits DDI_SUCCESS) { 5604189Sfrits mutex_enter(&scsa2usbp->scsa2usb_mutex); 5605189Sfrits ASSERT(scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy > 0); 5606189Sfrits scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy--; 5607189Sfrits 5608189Sfrits USB_DPRINTF_L2(DPRINT_MASK_PM, 5609189Sfrits scsa2usbp->scsa2usb_log_handle, 5610189Sfrits "scsa2usb_pm_busy_component failed: %d", 5611189Sfrits scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy); 5612189Sfrits 5613189Sfrits return; 5614189Sfrits } 5615189Sfrits mutex_enter(&scsa2usbp->scsa2usb_mutex); 56160Sstevel@tonic-gate } 56170Sstevel@tonic-gate } 56180Sstevel@tonic-gate 56190Sstevel@tonic-gate 56200Sstevel@tonic-gate /* 56210Sstevel@tonic-gate * scsa2usb_pm_idle_component: 56220Sstevel@tonic-gate * idles the device 56230Sstevel@tonic-gate */ 56240Sstevel@tonic-gate static void 56250Sstevel@tonic-gate scsa2usb_pm_idle_component(scsa2usb_state_t *scsa2usbp) 56260Sstevel@tonic-gate { 5627189Sfrits ASSERT(!mutex_owned(&scsa2usbp->scsa2usb_mutex)); 5628189Sfrits 56290Sstevel@tonic-gate if (scsa2usbp->scsa2usb_pm) { 56300Sstevel@tonic-gate if (pm_idle_component(scsa2usbp->scsa2usb_dip, 0) == 56310Sstevel@tonic-gate DDI_SUCCESS) { 56320Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 56330Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy > 0); 56340Sstevel@tonic-gate scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy--; 5635189Sfrits 5636189Sfrits USB_DPRINTF_L4(DPRINT_MASK_PM, 5637189Sfrits scsa2usbp->scsa2usb_log_handle, 5638189Sfrits "scsa2usb_pm_idle_component: %d", 5639189Sfrits scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy); 5640189Sfrits 56410Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 56420Sstevel@tonic-gate } 56430Sstevel@tonic-gate } 56440Sstevel@tonic-gate } 56450Sstevel@tonic-gate 56460Sstevel@tonic-gate 56470Sstevel@tonic-gate #ifdef DEBUG 56480Sstevel@tonic-gate /* 56490Sstevel@tonic-gate * scsa2usb_print_cdb: 56500Sstevel@tonic-gate * prints CDB 56510Sstevel@tonic-gate */ 56520Sstevel@tonic-gate void 56530Sstevel@tonic-gate scsa2usb_print_cdb(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) 56540Sstevel@tonic-gate { 56550Sstevel@tonic-gate uchar_t *c = (uchar_t *)&cmd->cmd_cdb; 56560Sstevel@tonic-gate 56570Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 56580Sstevel@tonic-gate "cmd = 0x%p opcode=%s " 56590Sstevel@tonic-gate "cdb: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", 56606898Sfb209375 (void *)cmd, 56616898Sfb209375 scsi_cname(cmd->cmd_cdb[SCSA2USB_OPCODE], scsa2usb_cmds), 56620Sstevel@tonic-gate c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], 56630Sstevel@tonic-gate c[9], c[10], c[11], c[12], c[13], c[14], c[15]); 56640Sstevel@tonic-gate } 56650Sstevel@tonic-gate #endif /* DEBUG */ 56660Sstevel@tonic-gate 56670Sstevel@tonic-gate 56680Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 56690Sstevel@tonic-gate /* 56700Sstevel@tonic-gate * scsa2usb_test_mblk: 56710Sstevel@tonic-gate * This function sends a dummy data mblk_t to simulate 56720Sstevel@tonic-gate * the following test cases: 5 and 11. 56730Sstevel@tonic-gate */ 56740Sstevel@tonic-gate static void 56750Sstevel@tonic-gate scsa2usb_test_mblk(scsa2usb_state_t *scsa2usbp, boolean_t large) 56760Sstevel@tonic-gate { 56770Sstevel@tonic-gate int i, rval; 56780Sstevel@tonic-gate size_t len; 56790Sstevel@tonic-gate usb_flags_t flags = USB_FLAGS_SLEEP; 56800Sstevel@tonic-gate usb_bulk_req_t *req; 56810Sstevel@tonic-gate 56820Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 56830Sstevel@tonic-gate 56840Sstevel@tonic-gate /* should we create a larger mblk? */ 56850Sstevel@tonic-gate len = (large == B_TRUE) ? DEV_BSIZE : USB_BULK_CBWCMD_LEN; 56860Sstevel@tonic-gate 56870Sstevel@tonic-gate req = scsa2usb_init_bulk_req(scsa2usbp, len, 56884700Sfb209375 SCSA2USB_BULK_PIPE_TIMEOUT, 0, flags); 56890Sstevel@tonic-gate 56900Sstevel@tonic-gate /* fill up the data mblk */ 56910Sstevel@tonic-gate for (i = 0; i < len; i++) { 56920Sstevel@tonic-gate *req->bulk_data->b_wptr++ = (uchar_t)i; 56930Sstevel@tonic-gate } 56940Sstevel@tonic-gate 56950Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 56960Sstevel@tonic-gate ASSERT(req->bulk_timeout); 56970Sstevel@tonic-gate rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkout_pipe, req, flags); 56980Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 56990Sstevel@tonic-gate 57000Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 57010Sstevel@tonic-gate "scsa2usb_test_mblk: Sent Data Out rval = 0x%x", rval); 57020Sstevel@tonic-gate 57030Sstevel@tonic-gate usb_free_bulk_req(req); 57040Sstevel@tonic-gate } 57050Sstevel@tonic-gate #endif /* SCSA2USB_BULK_ONLY_TEST */ 5706