17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5910cba4fScg149915 * Common Development and Distribution License (the "License"). 6910cba4fScg149915 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*42cac157SVincent Wang * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * scsa2usb bridge nexus driver: 297c478bd9Sstevel@tonic-gate * 307c478bd9Sstevel@tonic-gate * This driver supports the following wire transports: 317c478bd9Sstevel@tonic-gate * a. Bulk Only transport (see usb_ms_bulkonly.c) 327c478bd9Sstevel@tonic-gate * b. CB transport (see usb_ms_cbi.c) 337c478bd9Sstevel@tonic-gate * c. CBI transport with interrupt status completion (see usb_ms_cbi.c) 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate * It handles the following command sets: 367c478bd9Sstevel@tonic-gate * a. SCSI 377c478bd9Sstevel@tonic-gate * b. ATAPI command set (subset of SCSI command set) 387c478bd9Sstevel@tonic-gate * c. UFI command set ( 397c478bd9Sstevel@tonic-gate * http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf) 407c478bd9Sstevel@tonic-gate * 417c478bd9Sstevel@tonic-gate * For details on USB Mass Storage Class overview: 427c478bd9Sstevel@tonic-gate * http://www.usb.org/developers/devclass_docs/usbmassover_11.pdf 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate #if defined(lint) && !defined(DEBUG) 457c478bd9Sstevel@tonic-gate #define DEBUG 1 467c478bd9Sstevel@tonic-gate #endif 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #include <sys/usb/usba/usbai_version.h> 497c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h> 507c478bd9Sstevel@tonic-gate #include <sys/cdio.h> 517c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 527c478bd9Sstevel@tonic-gate #include <sys/esunddi.h> 537c478bd9Sstevel@tonic-gate #include <sys/callb.h> 547c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 557c478bd9Sstevel@tonic-gate #include <sys/kobj_lex.h> 567c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 57d29f5a71Szhigang lu - Sun Microsystems - Beijing China #include <sys/strsun.h> 587c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate #include <sys/usb/usba.h> 61*42cac157SVincent Wang #include <sys/usb/clients/ugen/usb_ugen.h> 627c478bd9Sstevel@tonic-gate #include <sys/usb/usba/usba_ugen.h> 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #include <sys/usb/usba/usba_private.h> 65*42cac157SVincent Wang #include <sys/usb/usba/usba_ugend.h> 667c478bd9Sstevel@tonic-gate #include <sys/usb/clients/mass_storage/usb_bulkonly.h> 677c478bd9Sstevel@tonic-gate #include <sys/usb/scsa2usb/scsa2usb.h> 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate /* 707c478bd9Sstevel@tonic-gate * Function Prototypes 717c478bd9Sstevel@tonic-gate */ 727c478bd9Sstevel@tonic-gate static int scsa2usb_attach(dev_info_t *, ddi_attach_cmd_t); 737c478bd9Sstevel@tonic-gate static int scsa2usb_info(dev_info_t *, ddi_info_cmd_t, void *, 747c478bd9Sstevel@tonic-gate void **); 757c478bd9Sstevel@tonic-gate static int scsa2usb_detach(dev_info_t *, ddi_detach_cmd_t); 767c478bd9Sstevel@tonic-gate static int scsa2usb_cleanup(dev_info_t *, scsa2usb_state_t *); 777c478bd9Sstevel@tonic-gate static void scsa2usb_validate_attrs(scsa2usb_state_t *); 787c478bd9Sstevel@tonic-gate static void scsa2usb_create_luns(scsa2usb_state_t *); 797c478bd9Sstevel@tonic-gate static int scsa2usb_is_usb(dev_info_t *); 803fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic static void scsa2usb_fake_inquiry(scsa2usb_state_t *, 813fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic struct scsi_inquiry *); 827c478bd9Sstevel@tonic-gate static void scsa2usb_do_inquiry(scsa2usb_state_t *, 837c478bd9Sstevel@tonic-gate uint_t, uint_t); 84df4cb6e0Ssl147100 static int scsa2usb_do_tur(scsa2usb_state_t *, struct scsi_address *); 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate /* override property handling */ 877c478bd9Sstevel@tonic-gate static void scsa2usb_override(scsa2usb_state_t *); 887c478bd9Sstevel@tonic-gate static int scsa2usb_parse_input_str(char *, scsa2usb_ov_t *, 897c478bd9Sstevel@tonic-gate scsa2usb_state_t *); 907c478bd9Sstevel@tonic-gate static void scsa2usb_override_error(char *, scsa2usb_state_t *); 917c478bd9Sstevel@tonic-gate static char *scsa2usb_strtok_r(char *, char *, char **); 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /* PANIC callback handling */ 957c478bd9Sstevel@tonic-gate static void scsa2usb_panic_callb_init(scsa2usb_state_t *); 967c478bd9Sstevel@tonic-gate static void scsa2usb_panic_callb_fini(scsa2usb_state_t *); 977c478bd9Sstevel@tonic-gate static boolean_t scsa2usb_panic_callb(void *, int); 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* SCSA support */ 1007c478bd9Sstevel@tonic-gate static int scsa2usb_scsi_tgt_probe(struct scsi_device *, int (*)(void)); 1017c478bd9Sstevel@tonic-gate static int scsa2usb_scsi_tgt_init(dev_info_t *, dev_info_t *, 1027c478bd9Sstevel@tonic-gate scsi_hba_tran_t *, struct scsi_device *); 1037c478bd9Sstevel@tonic-gate static void scsa2usb_scsi_tgt_free(dev_info_t *, dev_info_t *, 1047c478bd9Sstevel@tonic-gate scsi_hba_tran_t *, struct scsi_device *); 1057c478bd9Sstevel@tonic-gate static struct scsi_pkt *scsa2usb_scsi_init_pkt(struct scsi_address *, 1067c478bd9Sstevel@tonic-gate struct scsi_pkt *, struct buf *, int, int, 1077c478bd9Sstevel@tonic-gate int, int, int (*)(), caddr_t); 1087c478bd9Sstevel@tonic-gate static void scsa2usb_scsi_destroy_pkt(struct scsi_address *, 1097c478bd9Sstevel@tonic-gate struct scsi_pkt *); 1107c478bd9Sstevel@tonic-gate static int scsa2usb_scsi_start(struct scsi_address *, struct scsi_pkt *); 1117c478bd9Sstevel@tonic-gate static int scsa2usb_scsi_abort(struct scsi_address *, struct scsi_pkt *); 1127c478bd9Sstevel@tonic-gate static int scsa2usb_scsi_reset(struct scsi_address *, int); 1137c478bd9Sstevel@tonic-gate static int scsa2usb_scsi_getcap(struct scsi_address *, char *, int); 1147c478bd9Sstevel@tonic-gate static int scsa2usb_scsi_setcap(struct scsi_address *, char *, int, int); 1157c478bd9Sstevel@tonic-gate static int scsa2usb_scsi_bus_config(dev_info_t *, uint_t, 1167c478bd9Sstevel@tonic-gate ddi_bus_config_op_t, void *, dev_info_t **); 1177c478bd9Sstevel@tonic-gate static int scsa2usb_scsi_bus_unconfig(dev_info_t *, uint_t, 1187c478bd9Sstevel@tonic-gate ddi_bus_config_op_t, void *); 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* functions for command and transport support */ 1217c478bd9Sstevel@tonic-gate static void scsa2usb_prepare_pkt(scsa2usb_state_t *, struct scsi_pkt *); 1227c478bd9Sstevel@tonic-gate static int scsa2usb_cmd_transport(scsa2usb_state_t *, scsa2usb_cmd_t *); 1237c478bd9Sstevel@tonic-gate static int scsa2usb_check_bulkonly_blacklist_attrs(scsa2usb_state_t *, 1247c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *, uchar_t); 1257c478bd9Sstevel@tonic-gate static int scsa2usb_check_ufi_blacklist_attrs(scsa2usb_state_t *, uchar_t, 1267c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *); 1277c478bd9Sstevel@tonic-gate static int scsa2usb_handle_scsi_cmd_sub_class(scsa2usb_state_t *, 1287c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *, struct scsi_pkt *); 1297c478bd9Sstevel@tonic-gate static int scsa2usb_handle_ufi_subclass_cmd(scsa2usb_state_t *, 1307c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *, struct scsi_pkt *); 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* waitQ handling */ 1337c478bd9Sstevel@tonic-gate static void scsa2usb_work_thread(void *); 1347c478bd9Sstevel@tonic-gate static void scsa2usb_transport_request(scsa2usb_state_t *, uint_t); 1357c478bd9Sstevel@tonic-gate static void scsa2usb_flush_waitQ(scsa2usb_state_t *, uint_t, uchar_t); 1367c478bd9Sstevel@tonic-gate static int scsa2usb_all_waitQs_empty(scsa2usb_state_t *); 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* auto request sense handling */ 1397c478bd9Sstevel@tonic-gate static int scsa2usb_create_arq_pkt(scsa2usb_state_t *, 1407c478bd9Sstevel@tonic-gate struct scsi_address *); 1417c478bd9Sstevel@tonic-gate static void scsa2usb_delete_arq_pkt(scsa2usb_state_t *); 1427c478bd9Sstevel@tonic-gate static void scsa2usb_complete_arq_pkt(scsa2usb_state_t *, struct scsi_pkt *, 1437c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *, struct buf *); 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /* utility functions for any transport */ 1467c478bd9Sstevel@tonic-gate static int scsa2usb_open_usb_pipes(scsa2usb_state_t *); 1477c478bd9Sstevel@tonic-gate void scsa2usb_close_usb_pipes(scsa2usb_state_t *); 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate static void scsa2usb_fill_up_cdb_len(scsa2usb_cmd_t *, int); 1507c478bd9Sstevel@tonic-gate static void scsa2usb_fill_up_cdb_lba(scsa2usb_cmd_t *, int); 1517c478bd9Sstevel@tonic-gate static void scsa2usb_fill_up_ReadCD_cdb_len(scsa2usb_cmd_t *, int, int); 1527c478bd9Sstevel@tonic-gate static void scsa2usb_fill_up_12byte_cdb_len(scsa2usb_cmd_t *, int, int); 1537c478bd9Sstevel@tonic-gate static int scsa2usb_read_cd_blk_size(uchar_t); 1547c478bd9Sstevel@tonic-gate int scsa2usb_rw_transport(scsa2usb_state_t *, struct scsi_pkt *); 1557c478bd9Sstevel@tonic-gate void scsa2usb_setup_next_xfer(scsa2usb_state_t *, scsa2usb_cmd_t *); 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate static mblk_t *scsa2usb_bp_to_mblk(scsa2usb_state_t *); 1587c478bd9Sstevel@tonic-gate int scsa2usb_handle_data_start(scsa2usb_state_t *, 1597c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *, usb_bulk_req_t *); 1607c478bd9Sstevel@tonic-gate void scsa2usb_handle_data_done(scsa2usb_state_t *, 1617c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd, usb_bulk_req_t *); 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate usb_bulk_req_t *scsa2usb_init_bulk_req(scsa2usb_state_t *, 1647c478bd9Sstevel@tonic-gate size_t, uint_t, usb_req_attrs_t, usb_flags_t); 1657c478bd9Sstevel@tonic-gate int scsa2usb_bulk_timeout(int); 1667c478bd9Sstevel@tonic-gate int scsa2usb_clear_ept_stall(scsa2usb_state_t *, uint_t, 1677c478bd9Sstevel@tonic-gate usb_pipe_handle_t, char *); 1687c478bd9Sstevel@tonic-gate static void scsa2usb_pkt_completion(scsa2usb_state_t *, struct scsi_pkt *); 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* event handling */ 1717c478bd9Sstevel@tonic-gate static int scsa2usb_reconnect_event_cb(dev_info_t *); 1727c478bd9Sstevel@tonic-gate static int scsa2usb_disconnect_event_cb(dev_info_t *); 1737c478bd9Sstevel@tonic-gate static int scsa2usb_cpr_suspend(dev_info_t *); 1747c478bd9Sstevel@tonic-gate static void scsa2usb_cpr_resume(dev_info_t *); 1757c478bd9Sstevel@tonic-gate static void scsa2usb_restore_device_state(dev_info_t *, scsa2usb_state_t *); 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* PM handling */ 1787c478bd9Sstevel@tonic-gate static void scsa2usb_create_pm_components(dev_info_t *, scsa2usb_state_t *); 1797c478bd9Sstevel@tonic-gate static void scsa2usb_raise_power(scsa2usb_state_t *); 1807c478bd9Sstevel@tonic-gate static int scsa2usb_pwrlvl0(scsa2usb_state_t *); 1817c478bd9Sstevel@tonic-gate static int scsa2usb_pwrlvl1(scsa2usb_state_t *); 1827c478bd9Sstevel@tonic-gate static int scsa2usb_pwrlvl2(scsa2usb_state_t *); 1837c478bd9Sstevel@tonic-gate static int scsa2usb_pwrlvl3(scsa2usb_state_t *); 1847c478bd9Sstevel@tonic-gate static int scsa2usb_power(dev_info_t *, int comp, int level); 1857c478bd9Sstevel@tonic-gate static void scsa2usb_pm_busy_component(scsa2usb_state_t *); 1867c478bd9Sstevel@tonic-gate static void scsa2usb_pm_idle_component(scsa2usb_state_t *); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* external functions for Bulk only (BO) support */ 1897c478bd9Sstevel@tonic-gate extern int scsa2usb_bulk_only_transport(scsa2usb_state_t *, 1907c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *); 1917c478bd9Sstevel@tonic-gate extern int scsa2usb_bulk_only_get_max_lun(scsa2usb_state_t *); 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate /* external functions for CB/CBI support */ 1947c478bd9Sstevel@tonic-gate extern int scsa2usb_cbi_transport(scsa2usb_state_t *, scsa2usb_cmd_t *); 1957c478bd9Sstevel@tonic-gate extern void scsa2usb_cbi_stop_intr_polling(scsa2usb_state_t *); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate /* cmd decoding */ 1997c478bd9Sstevel@tonic-gate static char *scsa2usb_cmds[] = { 2007c478bd9Sstevel@tonic-gate "\000tur", 2017c478bd9Sstevel@tonic-gate "\001rezero", 2027c478bd9Sstevel@tonic-gate "\003rqsense", 2037c478bd9Sstevel@tonic-gate "\004format", 2047c478bd9Sstevel@tonic-gate "\014cartprot", 2057c478bd9Sstevel@tonic-gate "\022inquiry", 2067c478bd9Sstevel@tonic-gate "\026tranlba", 2077c478bd9Sstevel@tonic-gate "\030fmtverify", 2087c478bd9Sstevel@tonic-gate "\032modesense", 2097c478bd9Sstevel@tonic-gate "\033start", 2107c478bd9Sstevel@tonic-gate "\035snddiag", 2117c478bd9Sstevel@tonic-gate "\036doorlock", 2127c478bd9Sstevel@tonic-gate "\043formatcap", 2137c478bd9Sstevel@tonic-gate "\045readcap", 2147c478bd9Sstevel@tonic-gate "\050read10", 2157c478bd9Sstevel@tonic-gate "\052write10", 2167c478bd9Sstevel@tonic-gate "\053seek10", 2177c478bd9Sstevel@tonic-gate "\056writeverify", 2187c478bd9Sstevel@tonic-gate "\057verify", 2197c478bd9Sstevel@tonic-gate "\065synchcache", 2207c478bd9Sstevel@tonic-gate "\076readlong", 2217c478bd9Sstevel@tonic-gate "\077writelong", 2227c478bd9Sstevel@tonic-gate "\102readsubchan", 2237c478bd9Sstevel@tonic-gate "\103readtoc", 2247c478bd9Sstevel@tonic-gate "\104readhdr", 2257c478bd9Sstevel@tonic-gate "\105playaudio10", 2267c478bd9Sstevel@tonic-gate "\107playaudio_msf", 2277c478bd9Sstevel@tonic-gate "\110playaudio_ti", 2287c478bd9Sstevel@tonic-gate "\111playtrk_r10", 2297c478bd9Sstevel@tonic-gate "\112geteventnotify", 2307c478bd9Sstevel@tonic-gate "\113pause_resume", 2317c478bd9Sstevel@tonic-gate "\116stop/play_scan", 2327c478bd9Sstevel@tonic-gate "\121readdiscinfo", 2337c478bd9Sstevel@tonic-gate "\122readtrkinfo", 2347c478bd9Sstevel@tonic-gate "\123reservedtrk", 2357c478bd9Sstevel@tonic-gate "\124sendopcinfo", 2367c478bd9Sstevel@tonic-gate "\125modeselect", 2377c478bd9Sstevel@tonic-gate "\132modesense", 2387c478bd9Sstevel@tonic-gate "\133closetrksession", 2397c478bd9Sstevel@tonic-gate "\135sendcuesheet", 2407c478bd9Sstevel@tonic-gate "\136prin", 2417c478bd9Sstevel@tonic-gate "\137prout", 2427c478bd9Sstevel@tonic-gate "\241blankcd", 2437c478bd9Sstevel@tonic-gate "\245playaudio12", 2447c478bd9Sstevel@tonic-gate "\250read12", 2457c478bd9Sstevel@tonic-gate "\251playtrk12", 2467c478bd9Sstevel@tonic-gate "\252write12", 2477c478bd9Sstevel@tonic-gate "\254getperf", 2487c478bd9Sstevel@tonic-gate "\271readcdmsf", 2497c478bd9Sstevel@tonic-gate "\273setcdspeed", 2507c478bd9Sstevel@tonic-gate "\275mechanism_sts", 2517c478bd9Sstevel@tonic-gate "\276readcd", 2527c478bd9Sstevel@tonic-gate NULL 2537c478bd9Sstevel@tonic-gate }; 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * Mass-Storage devices masquerade as "sd" disks. 2587c478bd9Sstevel@tonic-gate * 2597c478bd9Sstevel@tonic-gate * These devices may not support all SCSI CDBs in their 2607c478bd9Sstevel@tonic-gate * entirety due to their hardware implementation limitations. 2617c478bd9Sstevel@tonic-gate * 2627c478bd9Sstevel@tonic-gate * As such, following is a list of some of the black-listed 2637c478bd9Sstevel@tonic-gate * devices w/ the attributes that they do not support. 2647c478bd9Sstevel@tonic-gate * (See scsa2usb.h for description on each attribute) 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate #define X ((uint16_t)(-1)) 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate static struct blacklist { 2697c478bd9Sstevel@tonic-gate uint16_t idVendor; /* vendor ID */ 2707c478bd9Sstevel@tonic-gate uint16_t idProduct; /* product ID */ 2717c478bd9Sstevel@tonic-gate uint16_t bcdDevice; /* device release number in bcd */ 2727c478bd9Sstevel@tonic-gate uint16_t attributes; /* attributes to blacklist */ 2737c478bd9Sstevel@tonic-gate } scsa2usb_blacklist[] = { 2747c478bd9Sstevel@tonic-gate /* Iomega Zip100 drive (prototype) with flaky bridge */ 2757c478bd9Sstevel@tonic-gate {MS_IOMEGA_VID, MS_IOMEGA_PID1_ZIP100, 0, 2767c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM}, 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate /* Iomega Zip100 drive (newer model) with flaky bridge */ 2797c478bd9Sstevel@tonic-gate {MS_IOMEGA_VID, MS_IOMEGA_PID2_ZIP100, 0, 2807c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM}, 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate /* Iomega Zip100 drive (newer model) with flaky bridge */ 2837c478bd9Sstevel@tonic-gate {MS_IOMEGA_VID, MS_IOMEGA_PID3_ZIP100, 0, 2847c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_PM}, 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* Iomega Zip250 drive */ 2877c478bd9Sstevel@tonic-gate {MS_IOMEGA_VID, MS_IOMEGA_PID_ZIP250, 0, SCSA2USB_ATTRS_GET_LUN}, 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* Iomega Clik! drive */ 2907c478bd9Sstevel@tonic-gate {MS_IOMEGA_VID, MS_IOMEGA_PID_CLIK, 0, 2917c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, 2927c478bd9Sstevel@tonic-gate 2935547f1d8SBinzi Cao - Sun Microsystems - Beijing China /* Kingston DataTraveler Stick / PNY Attache Stick */ 2945547f1d8SBinzi Cao - Sun Microsystems - Beijing China {MS_TOSHIBA_VID, MS_TOSHIBA_PID0, 0, 2955547f1d8SBinzi Cao - Sun Microsystems - Beijing China SCSA2USB_ATTRS_GET_LUN}, 2965547f1d8SBinzi Cao - Sun Microsystems - Beijing China 2975547f1d8SBinzi Cao - Sun Microsystems - Beijing China /* PNY Floppy drive */ 2985547f1d8SBinzi Cao - Sun Microsystems - Beijing China {MS_PNY_VID, MS_PNY_PID0, 0, 2995547f1d8SBinzi Cao - Sun Microsystems - Beijing China SCSA2USB_ATTRS_GET_LUN}, 3005547f1d8SBinzi Cao - Sun Microsystems - Beijing China 3017c478bd9Sstevel@tonic-gate /* SMSC floppy Device - and its clones */ 3027c478bd9Sstevel@tonic-gate {MS_SMSC_VID, X, 0, SCSA2USB_ATTRS_START_STOP}, 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate /* Hagiwara SmartMedia Device */ 3057c478bd9Sstevel@tonic-gate {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID1, 0, 3067c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate /* Hagiwara CompactFlash Device */ 3097c478bd9Sstevel@tonic-gate {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID2, 0, 3107c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate /* Hagiwara SmartMedia/CompactFlash Combo Device */ 3137c478bd9Sstevel@tonic-gate {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID3, 0, 3147c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_START_STOP}, 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* Hagiwara new SM Device */ 3177c478bd9Sstevel@tonic-gate {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID4, 0, 3187c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* Hagiwara new CF Device */ 3217c478bd9Sstevel@tonic-gate {MS_HAGIWARA_SYS_COM_VID, MS_HAGIWARA_SYSCOM_PID5, 0, 3227c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_START_STOP}, 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /* Mitsumi CD-RW Device(s) */ 3257c478bd9Sstevel@tonic-gate {MS_MITSUMI_VID, X, X, SCSA2USB_ATTRS_BIG_TIMEOUT | 3267c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_GET_CONF | SCSA2USB_ATTRS_GET_PERF}, 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate /* Neodio Technologies Corporation SM/CF/MS/SD Combo Device */ 3297c478bd9Sstevel@tonic-gate {MS_NEODIO_VID, MS_NEODIO_DEVICE_3050, 0, 3307c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_MODE_SENSE }, 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /* dumb flash devices */ 3337c478bd9Sstevel@tonic-gate {MS_SONY_FLASH_VID, MS_SONY_FLASH_PID, 0, 3347c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_REDUCED_CMD}, 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate {MS_TREK_FLASH_VID, MS_TREK_FLASH_PID, 0, 3377c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_REDUCED_CMD}, 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate {MS_PENN_FLASH_VID, MS_PENN_FLASH_PID, 0, 3407c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_REDUCED_CMD}, 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* SimpleTech UCF-100 CF Device */ 3437c478bd9Sstevel@tonic-gate {MS_SIMPLETECH_VID, MS_SIMPLETECH_PID1, 0, 3447c478bd9Sstevel@tonic-gate SCSA2USB_ATTRS_REDUCED_CMD}, 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate {MS_ADDONICS_CARD_READER_VID, MS_ADDONICS_CARD_READER_PID, 3477c478bd9Sstevel@tonic-gate 0, SCSA2USB_ATTRS_REDUCED_CMD}, 3482115f0c6Ssl147100 3492115f0c6Ssl147100 /* Acomdata 80GB USB/1394 Hard Disk */ 3502115f0c6Ssl147100 {MS_ACOMDATA_VID, MS_ACOMDATA_PID1, 0, 3512115f0c6Ssl147100 SCSA2USB_ATTRS_USE_CSW_RESIDUE}, 3522115f0c6Ssl147100 3532115f0c6Ssl147100 /* OTi6828 Flash Disk */ 3542115f0c6Ssl147100 {MS_OTI_VID, MS_OTI_DEVICE_6828, 0, 3552115f0c6Ssl147100 SCSA2USB_ATTRS_USE_CSW_RESIDUE}, 356df4cb6e0Ssl147100 357df4cb6e0Ssl147100 /* AMI Virtual Floppy */ 358df4cb6e0Ssl147100 {MS_AMI_VID, MS_AMI_VIRTUAL_FLOPPY, 0, 359df4cb6e0Ssl147100 SCSA2USB_ATTRS_NO_MEDIA_CHECK}, 36063602c90Sfb209375 36163602c90Sfb209375 /* ScanLogic USB Storage Device */ 36263602c90Sfb209375 {MS_SCANLOGIC_VID, MS_SCANLOGIC_PID1, 0, 3633fbbb872Ssl147100 SCSA2USB_ATTRS_NO_CAP_ADJUST}, 3643fbbb872Ssl147100 3653fbbb872Ssl147100 /* Super Top USB 2.0 IDE Device */ 3663fbbb872Ssl147100 {MS_SUPERTOP_VID, MS_SUPERTOP_DEVICE_6600, 0, 36767318e4aSlg150142 SCSA2USB_ATTRS_USE_CSW_RESIDUE}, 36867318e4aSlg150142 36967318e4aSlg150142 /* Aigo Miniking Device NEHFSP14 */ 37067318e4aSlg150142 {MS_AIGO_VID, MS_AIGO_DEVICE_6981, 0, 371f0e30896Sguoqing zhu - Sun Microsystems - Beijing China SCSA2USB_ATTRS_USE_CSW_RESIDUE}, 372f0e30896Sguoqing zhu - Sun Microsystems - Beijing China 373f0e30896Sguoqing zhu - Sun Microsystems - Beijing China /* Alcor Micro Corp 6387 flash disk */ 374f0e30896Sguoqing zhu - Sun Microsystems - Beijing China {MS_ALCOR_VID, MS_ALCOR_PID0, 0, 3758f588c83Sguoqing zhu - Sun Microsystems - Beijing China SCSA2USB_ATTRS_GET_LUN | SCSA2USB_ATTRS_USE_CSW_RESIDUE}, 376f0e30896Sguoqing zhu - Sun Microsystems - Beijing China 3778f588c83Sguoqing zhu - Sun Microsystems - Beijing China /* Western Digital External HDD */ 3788f588c83Sguoqing zhu - Sun Microsystems - Beijing China {MS_WD_VID, MS_WD_PID, 0, 3798f588c83Sguoqing zhu - Sun Microsystems - Beijing China SCSA2USB_ATTRS_INQUIRY_EVPD} 3807c478bd9Sstevel@tonic-gate }; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate #define N_SCSA2USB_BLACKLIST (sizeof (scsa2usb_blacklist))/ \ 3847c478bd9Sstevel@tonic-gate sizeof (struct blacklist) 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate /* 3877c478bd9Sstevel@tonic-gate * Attribute values can be overridden by values 3887c478bd9Sstevel@tonic-gate * contained in the scsa2usb.conf file. 3897c478bd9Sstevel@tonic-gate * These arrays define possible user input values. 3907c478bd9Sstevel@tonic-gate */ 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate struct scsa2usb_subclass_protocol_override { 3937c478bd9Sstevel@tonic-gate char *name; 3947c478bd9Sstevel@tonic-gate int value; 3957c478bd9Sstevel@tonic-gate }; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate static struct scsa2usb_subclass_protocol_override scsa2usb_protocol[] = { 3987c478bd9Sstevel@tonic-gate {"CB", SCSA2USB_CB_PROTOCOL}, 3997c478bd9Sstevel@tonic-gate {"CBI", SCSA2USB_CBI_PROTOCOL}, 4007c478bd9Sstevel@tonic-gate {"BO", SCSA2USB_BULK_ONLY_PROTOCOL} 4017c478bd9Sstevel@tonic-gate }; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate static struct scsa2usb_subclass_protocol_override scsa2usb_subclass[] = { 4047c478bd9Sstevel@tonic-gate {"SCSI", SCSA2USB_SCSI_CMDSET}, 4057c478bd9Sstevel@tonic-gate {"ATAPI", SCSA2USB_ATAPI_CMDSET}, 4067c478bd9Sstevel@tonic-gate {"UFI", SCSA2USB_UFI_CMDSET} 4077c478bd9Sstevel@tonic-gate }; 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate #define N_SCSA2USB_SUBC_OVERRIDE (sizeof (scsa2usb_subclass))/ \ 4117c478bd9Sstevel@tonic-gate sizeof (struct scsa2usb_subclass_protocol_override) 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate #define N_SCSA2USB_PROT_OVERRIDE (sizeof (scsa2usb_protocol))/ \ 4147c478bd9Sstevel@tonic-gate sizeof (struct scsa2usb_subclass_protocol_override) 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate /* global variables */ 4177c478bd9Sstevel@tonic-gate static void *scsa2usb_statep; /* for soft state */ 4187c478bd9Sstevel@tonic-gate static boolean_t scsa2usb_sync_message = B_TRUE; /* for syncing */ 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate /* for debug messages */ 4214610e4a0Sfrits uint_t scsa2usb_errmask = (uint_t)DPRINT_MASK_ALL; 4224610e4a0Sfrits uint_t scsa2usb_errlevel = USB_LOG_L4; 4234610e4a0Sfrits uint_t scsa2usb_instance_debug = (uint_t)-1; 4244610e4a0Sfrits uint_t scsa2usb_scsi_bus_config_debug = 0; 4254610e4a0Sfrits uint_t scsa2usb_long_timeout = 50 * SCSA2USB_BULK_PIPE_TIMEOUT; 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate /* 4297c478bd9Sstevel@tonic-gate * Some devices have problems with big bulk transfers, 4307c478bd9Sstevel@tonic-gate * transfers >= 128kbytes hang the device. This tunable allows to 4317c478bd9Sstevel@tonic-gate * limit the maximum bulk transfers rate. 4327c478bd9Sstevel@tonic-gate */ 4334610e4a0Sfrits uint_t scsa2usb_max_bulk_xfer_size = SCSA2USB_MAX_BULK_XFER_SIZE; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 4377c478bd9Sstevel@tonic-gate /* 4387c478bd9Sstevel@tonic-gate * Test BO 13 cases. (See USB Mass Storage Class - Bulk Only Transport). 4397c478bd9Sstevel@tonic-gate * We are not covering test cases 1, 6, and 12 as these are the "good" 4407c478bd9Sstevel@tonic-gate * test cases and are tested as part of the normal drive access operations. 4417c478bd9Sstevel@tonic-gate * 4427c478bd9Sstevel@tonic-gate * NOTE: This is for testing only. It will be replaced by a uscsi test. 4437c478bd9Sstevel@tonic-gate * Some are listed here while; other test cases are moved to usb_bulkonly.c 4447c478bd9Sstevel@tonic-gate */ 4457c478bd9Sstevel@tonic-gate static int scsa2usb_test_case_5 = 0; 4467c478bd9Sstevel@tonic-gate int scsa2usb_test_case_8 = 0; 4477c478bd9Sstevel@tonic-gate int scsa2usb_test_case_10 = 0; 4487c478bd9Sstevel@tonic-gate static int scsa2usb_test_case_11 = 0; 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate static void scsa2usb_test_mblk(scsa2usb_state_t *, boolean_t); 4517c478bd9Sstevel@tonic-gate #endif /* SCSA2USB_BULK_ONLY_TEST */ 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate static int scsa2usb_ugen_open(dev_t *, int, int, cred_t *); 4547c478bd9Sstevel@tonic-gate static int scsa2usb_ugen_close(dev_t, int, int, cred_t *); 4557c478bd9Sstevel@tonic-gate static int scsa2usb_ugen_read(dev_t, struct uio *, cred_t *); 4567c478bd9Sstevel@tonic-gate static int scsa2usb_ugen_write(dev_t, struct uio *, cred_t *); 4577c478bd9Sstevel@tonic-gate static int scsa2usb_ugen_poll(dev_t, short, int, short *, 4587c478bd9Sstevel@tonic-gate struct pollhead **); 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate /* scsa2usb cb_ops */ 4617c478bd9Sstevel@tonic-gate static struct cb_ops scsa2usb_cbops = { 4627c478bd9Sstevel@tonic-gate scsa2usb_ugen_open, /* open */ 4637c478bd9Sstevel@tonic-gate scsa2usb_ugen_close, /* close */ 4647c478bd9Sstevel@tonic-gate nodev, /* strategy */ 4657c478bd9Sstevel@tonic-gate nodev, /* print */ 4667c478bd9Sstevel@tonic-gate nodev, /* dump */ 4677c478bd9Sstevel@tonic-gate scsa2usb_ugen_read, /* read */ 4687c478bd9Sstevel@tonic-gate scsa2usb_ugen_write, /* write */ 4690e7b3271Svb160487 nodev, /* ioctl */ 4707c478bd9Sstevel@tonic-gate nodev, /* devmap */ 4717c478bd9Sstevel@tonic-gate nodev, /* mmap */ 4727c478bd9Sstevel@tonic-gate nodev, /* segmap */ 4737c478bd9Sstevel@tonic-gate scsa2usb_ugen_poll, /* poll */ 4747c478bd9Sstevel@tonic-gate ddi_prop_op, /* prop_op */ 4757c478bd9Sstevel@tonic-gate NULL, /* stream */ 4767c478bd9Sstevel@tonic-gate D_MP, /* cb_flag */ 4777c478bd9Sstevel@tonic-gate CB_REV, /* rev */ 4787c478bd9Sstevel@tonic-gate nodev, /* int (*cb_aread)() */ 4797c478bd9Sstevel@tonic-gate nodev /* int (*cb_awrite)() */ 4807c478bd9Sstevel@tonic-gate }; 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* modloading support */ 4837c478bd9Sstevel@tonic-gate static struct dev_ops scsa2usb_ops = { 4847c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 4857c478bd9Sstevel@tonic-gate 0, /* refcnt */ 4867c478bd9Sstevel@tonic-gate scsa2usb_info, /* info */ 4877c478bd9Sstevel@tonic-gate nulldev, /* identify */ 4887c478bd9Sstevel@tonic-gate nulldev, /* probe */ 4897c478bd9Sstevel@tonic-gate scsa2usb_attach, /* attach */ 4907c478bd9Sstevel@tonic-gate scsa2usb_detach, /* detach */ 4917c478bd9Sstevel@tonic-gate nodev, /* reset */ 4927c478bd9Sstevel@tonic-gate &scsa2usb_cbops, /* driver operations */ 4937c478bd9Sstevel@tonic-gate NULL, /* bus operations */ 49419397407SSherry Moore scsa2usb_power, /* power */ 49519397407SSherry Moore ddi_quiesce_not_needed, /* quiesce */ 4967c478bd9Sstevel@tonic-gate }; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 4997c478bd9Sstevel@tonic-gate &mod_driverops, /* Module type. This one is a driver */ 500e7cc2e17Sbc224572 "SCSA to USB Driver", /* Name of the module. */ 5017c478bd9Sstevel@tonic-gate &scsa2usb_ops, /* driver ops */ 5027c478bd9Sstevel@tonic-gate }; 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 5057c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modldrv, NULL 5067c478bd9Sstevel@tonic-gate }; 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate /* event support */ 5097c478bd9Sstevel@tonic-gate static usb_event_t scsa2usb_events = { 5107c478bd9Sstevel@tonic-gate scsa2usb_disconnect_event_cb, 5117c478bd9Sstevel@tonic-gate scsa2usb_reconnect_event_cb, 5127c478bd9Sstevel@tonic-gate NULL, NULL 5137c478bd9Sstevel@tonic-gate }; 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate int 5167c478bd9Sstevel@tonic-gate _init(void) 5177c478bd9Sstevel@tonic-gate { 5187c478bd9Sstevel@tonic-gate int rval; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if (((rval = ddi_soft_state_init(&scsa2usb_statep, 5217c478bd9Sstevel@tonic-gate sizeof (scsa2usb_state_t), SCSA2USB_INITIAL_ALLOC)) != 0)) { 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate return (rval); 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate if ((rval = scsi_hba_init(&modlinkage)) != 0) { 5277c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&scsa2usb_statep); 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate return (rval); 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate if ((rval = mod_install(&modlinkage)) != 0) { 5337c478bd9Sstevel@tonic-gate scsi_hba_fini(&modlinkage); 5347c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&scsa2usb_statep); 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate return (rval); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate return (rval); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate int 5447c478bd9Sstevel@tonic-gate _fini(void) 5457c478bd9Sstevel@tonic-gate { 5467c478bd9Sstevel@tonic-gate int rval; 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate if ((rval = mod_remove(&modlinkage)) == 0) { 5497c478bd9Sstevel@tonic-gate scsi_hba_fini(&modlinkage); 5507c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&scsa2usb_statep); 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate return (rval); 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate int 5587c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 5597c478bd9Sstevel@tonic-gate { 5607c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate /* 5657c478bd9Sstevel@tonic-gate * scsa2usb_info : 5667c478bd9Sstevel@tonic-gate * Get minor number, soft state structure etc. 5677c478bd9Sstevel@tonic-gate */ 5687c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 5697c478bd9Sstevel@tonic-gate static int 5707c478bd9Sstevel@tonic-gate scsa2usb_info(dev_info_t *dip, ddi_info_cmd_t infocmd, 5717c478bd9Sstevel@tonic-gate void *arg, void **result) 5727c478bd9Sstevel@tonic-gate { 5737c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = NULL; 5747c478bd9Sstevel@tonic-gate int error = DDI_FAILURE; 5757c478bd9Sstevel@tonic-gate int instance = SCSA2USB_MINOR_TO_INSTANCE(getminor((dev_t)arg)); 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate switch (infocmd) { 5787c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 5797c478bd9Sstevel@tonic-gate if (((scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 5807c478bd9Sstevel@tonic-gate instance)) != NULL) && 5817c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dip) { 5827c478bd9Sstevel@tonic-gate *result = scsa2usbp->scsa2usb_dip; 5837c478bd9Sstevel@tonic-gate error = DDI_SUCCESS; 5847c478bd9Sstevel@tonic-gate } else { 5857c478bd9Sstevel@tonic-gate *result = NULL; 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate break; 5887c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 5897c478bd9Sstevel@tonic-gate *result = (void *)(uintptr_t)instance; 5907c478bd9Sstevel@tonic-gate error = DDI_SUCCESS; 5917c478bd9Sstevel@tonic-gate break; 5927c478bd9Sstevel@tonic-gate default: 5937c478bd9Sstevel@tonic-gate break; 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate return (error); 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate /* 6017c478bd9Sstevel@tonic-gate * scsa2usb_attach: 6027c478bd9Sstevel@tonic-gate * Attach driver 6037c478bd9Sstevel@tonic-gate * Allocate a "scsi_hba_tran" - call scsi_hba_tran_alloc() 6047c478bd9Sstevel@tonic-gate * Invoke scsi_hba_attach_setup 6057c478bd9Sstevel@tonic-gate * Get the serialno of the device 6067c478bd9Sstevel@tonic-gate * Open bulk pipes 6077c478bd9Sstevel@tonic-gate * Create disk child(ren) 6087c478bd9Sstevel@tonic-gate * Register events 6097c478bd9Sstevel@tonic-gate * Create and register panic callback 6107c478bd9Sstevel@tonic-gate * 6117c478bd9Sstevel@tonic-gate * NOTE: Replaced CBW_DIR_OUT with USB_EP_DIR_OUT and CBW_DIR_IN with 6127c478bd9Sstevel@tonic-gate * USB_EP_DIR_IN as they are the same #defines. 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate static int 6157c478bd9Sstevel@tonic-gate scsa2usb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 6167c478bd9Sstevel@tonic-gate { 6177c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip); 6187c478bd9Sstevel@tonic-gate int interface; 6197c478bd9Sstevel@tonic-gate uint_t lun; 6207c478bd9Sstevel@tonic-gate boolean_t ept_check = B_TRUE; 6217c478bd9Sstevel@tonic-gate scsi_hba_tran_t *tran; /* scsi transport */ 6227c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 6237c478bd9Sstevel@tonic-gate usb_log_handle_t log_handle; 6247c478bd9Sstevel@tonic-gate usb_ep_data_t *ep_data; 6257c478bd9Sstevel@tonic-gate usb_client_dev_data_t *dev_data; 6267c478bd9Sstevel@tonic-gate usb_alt_if_data_t *altif_data; 6277c478bd9Sstevel@tonic-gate usb_ugen_info_t usb_ugen_info; 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, NULL, 630112116d8Sfb209375 "scsa2usb_attach: dip = 0x%p", (void *)dip); 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate switch (cmd) { 6337c478bd9Sstevel@tonic-gate case DDI_ATTACH: 6347c478bd9Sstevel@tonic-gate break; 6357c478bd9Sstevel@tonic-gate case DDI_RESUME: 6367c478bd9Sstevel@tonic-gate scsa2usb_cpr_resume(dip); 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 6397c478bd9Sstevel@tonic-gate default: 6407c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, NULL, 6417c478bd9Sstevel@tonic-gate "scsa2usb_attach: failed"); 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate /* Allocate softc information */ 6477c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(scsa2usb_statep, instance) != DDI_SUCCESS) { 6487c478bd9Sstevel@tonic-gate ddi_prop_remove_all(dip); 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate /* get soft state space and initialize */ 6547c478bd9Sstevel@tonic-gate if ((scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 6557c478bd9Sstevel@tonic-gate instance)) == NULL) { 6567c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, NULL, 6577c478bd9Sstevel@tonic-gate "scsa2usb%d: bad soft state", instance); 6587c478bd9Sstevel@tonic-gate ddi_prop_remove_all(dip); 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dip = dip; 6647c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_instance = instance; 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate /* allocate a log handle for debug/error messages */ 6677c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle = log_handle = 6687c478bd9Sstevel@tonic-gate usb_alloc_log_hdl(dip, "s2u", 6697c478bd9Sstevel@tonic-gate &scsa2usb_errlevel, 6707c478bd9Sstevel@tonic-gate &scsa2usb_errmask, &scsa2usb_instance_debug, 6717c478bd9Sstevel@tonic-gate 0); 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* attach to USBA */ 6747c478bd9Sstevel@tonic-gate if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) { 6757c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 6767c478bd9Sstevel@tonic-gate "usb_client_attach failed"); 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate goto fail; 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate if (usb_get_dev_data(dip, &dev_data, USB_PARSE_LVL_IF, 0) != 6817c478bd9Sstevel@tonic-gate USB_SUCCESS) { 6827c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 6837c478bd9Sstevel@tonic-gate "usb_get_dev_data failed"); 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate goto fail; 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate /* initialize the mutex with the right cookie */ 6897c478bd9Sstevel@tonic-gate mutex_init(&scsa2usbp->scsa2usb_mutex, NULL, MUTEX_DRIVER, 6907c478bd9Sstevel@tonic-gate dev_data->dev_iblock_cookie); 6917c478bd9Sstevel@tonic-gate cv_init(&scsa2usbp->scsa2usb_transport_busy_cv, NULL, CV_DRIVER, NULL); 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 6947c478bd9Sstevel@tonic-gate usba_init_list(&scsa2usbp->scsa2usb_waitQ[lun], NULL, 6957c478bd9Sstevel@tonic-gate dev_data->dev_iblock_cookie); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 6987c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dip = dip; 6997c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_instance = instance; 7007c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs = SCSA2USB_ALL_ATTRS; 7017c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_data = dev_data; 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate /* save the default pipe handle */ 7057c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_default_pipe = dev_data->dev_default_ph; 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate /* basic inits are done */ 7087c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_flags |= SCSA2USB_FLAGS_LOCKS_INIT; 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, log_handle, 711112116d8Sfb209375 "curr_cfg=%ld, curr_if=%d", 712112116d8Sfb209375 (long)(dev_data->dev_curr_cfg - &dev_data->dev_cfg[0]), 7137c478bd9Sstevel@tonic-gate dev_data->dev_curr_if); 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate interface = dev_data->dev_curr_if; 7167c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_num = dev_data->dev_curr_if; 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate /* now find out relevant descriptors for alternate 0 */ 7197c478bd9Sstevel@tonic-gate altif_data = &dev_data->dev_curr_cfg->cfg_if[interface].if_alt[0]; 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate if (altif_data->altif_n_ep == 0) { 722d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 7237c478bd9Sstevel@tonic-gate "invalid alt 0 for interface %d", interface); 7247c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate goto fail; 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate /* All CB/CBI, BO devices should have this value set */ 7307c478bd9Sstevel@tonic-gate if (altif_data->altif_descr.bInterfaceClass != 7317c478bd9Sstevel@tonic-gate USB_CLASS_MASS_STORAGE) { 732d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 7337c478bd9Sstevel@tonic-gate "invalid interface class (0x%x)", 7347c478bd9Sstevel@tonic-gate altif_data->altif_descr.bInterfaceClass); 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr = altif_data->altif_descr; 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate /* figure out the endpoints and copy the descr */ 7397c478bd9Sstevel@tonic-gate if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, 0, 0, 7407c478bd9Sstevel@tonic-gate USB_EP_ATTR_BULK, USB_EP_DIR_OUT)) != NULL) { 7417c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkout_ept = ep_data->ep_descr; 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, 0, 0, 7447c478bd9Sstevel@tonic-gate USB_EP_ATTR_BULK, USB_EP_DIR_IN)) != NULL) { 7457c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_ept = ep_data->ep_descr; 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, 0, 0, 7487c478bd9Sstevel@tonic-gate USB_EP_ATTR_INTR, USB_EP_DIR_IN)) != NULL) { 7497c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_intr_ept = ep_data->ep_descr; 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate /* 7537c478bd9Sstevel@tonic-gate * check here for protocol and subclass supported by this driver 7547c478bd9Sstevel@tonic-gate * 7557c478bd9Sstevel@tonic-gate * first check if conf file has override values 7567c478bd9Sstevel@tonic-gate * Note: override values are not used if supplied values are legal 7577c478bd9Sstevel@tonic-gate */ 7587c478bd9Sstevel@tonic-gate scsa2usb_override(scsa2usbp); 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, log_handle, 7617c478bd9Sstevel@tonic-gate "protocol=0x%x override=0x%x subclass=0x%x override=0x%x", 7627c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol, 7637c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_protocol_override, 7647c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass, 7657c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_subclass_override); 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate switch (scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol) { 7687c478bd9Sstevel@tonic-gate case USB_PROTO_MS_CBI: 7697c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_CB_PROTOCOL; 7707c478bd9Sstevel@tonic-gate break; 7717c478bd9Sstevel@tonic-gate case USB_PROTO_MS_CBI_WC: 7727c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_CBI_PROTOCOL; 7737c478bd9Sstevel@tonic-gate break; 7747c478bd9Sstevel@tonic-gate case USB_PROTO_MS_ISD_1999_SILICN: 7757c478bd9Sstevel@tonic-gate case USB_PROTO_MS_BULK_ONLY: 7767c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_BULK_ONLY_PROTOCOL; 7777c478bd9Sstevel@tonic-gate break; 7787c478bd9Sstevel@tonic-gate default: 7797c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_protocol_override) { 7807c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= 7817c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_protocol_override; 782d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 7837c478bd9Sstevel@tonic-gate "overriding protocol %x", 7847c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol); 7857c478bd9Sstevel@tonic-gate break; 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 7897c478bd9Sstevel@tonic-gate "unsupported protocol = %x", 7907c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceProtocol); 7917c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate goto fail; 7947c478bd9Sstevel@tonic-gate } 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate switch (scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass) { 7977c478bd9Sstevel@tonic-gate case USB_SUBCLS_MS_SCSI: /* transparent SCSI */ 7987c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_SCSI_CMDSET; 7997c478bd9Sstevel@tonic-gate break; 8007c478bd9Sstevel@tonic-gate case USB_SUBCLS_MS_SFF8020I: 8017c478bd9Sstevel@tonic-gate case USB_SUBCLS_MS_SFF8070I: 8027c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_ATAPI_CMDSET; 8037c478bd9Sstevel@tonic-gate break; 8047c478bd9Sstevel@tonic-gate case USB_SUBCLS_MS_UFI: /* UFI */ 8057c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_UFI_CMDSET; 8067c478bd9Sstevel@tonic-gate break; 8077c478bd9Sstevel@tonic-gate default: 8087c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_subclass_override) { 8097c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= 8107c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_subclass_override; 811d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 8127c478bd9Sstevel@tonic-gate "overriding subclass %x", 8137c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass); 8147c478bd9Sstevel@tonic-gate break; 8157c478bd9Sstevel@tonic-gate } 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 8187c478bd9Sstevel@tonic-gate "unsupported subclass = %x", 8197c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_intfc_descr.bInterfaceSubClass); 8207c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate goto fail; 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate /* check that we have the right set of endpoint descriptors */ 8267c478bd9Sstevel@tonic-gate if (SCSA2USB_IS_BULK_ONLY(scsa2usbp) || SCSA2USB_IS_CB(scsa2usbp)) { 8277c478bd9Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_bulkout_ept.bLength == 0) || 8287c478bd9Sstevel@tonic-gate (scsa2usbp->scsa2usb_bulkin_ept.bLength == 0)) { 8297c478bd9Sstevel@tonic-gate ept_check = B_FALSE; 8307c478bd9Sstevel@tonic-gate } 8317c478bd9Sstevel@tonic-gate } else if (SCSA2USB_IS_CBI(scsa2usbp)) { 8327c478bd9Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_bulkout_ept.bLength == 0) || 8337c478bd9Sstevel@tonic-gate (scsa2usbp->scsa2usb_bulkin_ept.bLength == 0) || 8347c478bd9Sstevel@tonic-gate (scsa2usbp->scsa2usb_intr_ept.bLength == 0)) { 8357c478bd9Sstevel@tonic-gate ept_check = B_FALSE; 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate if (ept_check == B_FALSE) { 840d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 8417c478bd9Sstevel@tonic-gate "scsa2usb%d doesn't support minimum required endpoints", 8427c478bd9Sstevel@tonic-gate instance); 8437c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate goto fail; 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate /* 8497c478bd9Sstevel@tonic-gate * Validate the black-listed attributes 8507c478bd9Sstevel@tonic-gate */ 8517c478bd9Sstevel@tonic-gate scsa2usb_validate_attrs(scsa2usbp); 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate /* Print the serial number from the registration data */ 8547c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_dev_data->dev_serial) { 8557c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, 8567c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, "Serial Number = %s", 8577c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_data->dev_serial); 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate /* 8617c478bd9Sstevel@tonic-gate * Allocate a SCSA transport structure 8627c478bd9Sstevel@tonic-gate */ 8637c478bd9Sstevel@tonic-gate tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP); 8647c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_tran = tran; 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate /* 8677c478bd9Sstevel@tonic-gate * initialize transport structure 8687c478bd9Sstevel@tonic-gate */ 8697c478bd9Sstevel@tonic-gate tran->tran_hba_private = scsa2usbp; 8707c478bd9Sstevel@tonic-gate tran->tran_tgt_private = NULL; 8717c478bd9Sstevel@tonic-gate tran->tran_tgt_init = scsa2usb_scsi_tgt_init; 8727c478bd9Sstevel@tonic-gate tran->tran_tgt_probe = scsa2usb_scsi_tgt_probe; 8737c478bd9Sstevel@tonic-gate tran->tran_tgt_free = scsa2usb_scsi_tgt_free; 8747c478bd9Sstevel@tonic-gate tran->tran_start = scsa2usb_scsi_start; 8757c478bd9Sstevel@tonic-gate tran->tran_abort = scsa2usb_scsi_abort; 8767c478bd9Sstevel@tonic-gate tran->tran_reset = scsa2usb_scsi_reset; 8777c478bd9Sstevel@tonic-gate tran->tran_getcap = scsa2usb_scsi_getcap; 8787c478bd9Sstevel@tonic-gate tran->tran_setcap = scsa2usb_scsi_setcap; 8797c478bd9Sstevel@tonic-gate tran->tran_init_pkt = scsa2usb_scsi_init_pkt; 8807c478bd9Sstevel@tonic-gate tran->tran_destroy_pkt = scsa2usb_scsi_destroy_pkt; 8817c478bd9Sstevel@tonic-gate tran->tran_dmafree = NULL; 8827c478bd9Sstevel@tonic-gate tran->tran_sync_pkt = NULL; 8837c478bd9Sstevel@tonic-gate tran->tran_reset_notify = NULL; 8847c478bd9Sstevel@tonic-gate tran->tran_get_bus_addr = NULL; 8857c478bd9Sstevel@tonic-gate tran->tran_get_name = NULL; 8867c478bd9Sstevel@tonic-gate tran->tran_quiesce = NULL; 8877c478bd9Sstevel@tonic-gate tran->tran_unquiesce = NULL; 8887c478bd9Sstevel@tonic-gate tran->tran_bus_reset = NULL; 8897c478bd9Sstevel@tonic-gate tran->tran_add_eventcall = NULL; 8907c478bd9Sstevel@tonic-gate tran->tran_get_eventcookie = NULL; 8917c478bd9Sstevel@tonic-gate tran->tran_post_event = NULL; 8927c478bd9Sstevel@tonic-gate tran->tran_remove_eventcall = NULL; 8937c478bd9Sstevel@tonic-gate tran->tran_bus_config = scsa2usb_scsi_bus_config; 8947c478bd9Sstevel@tonic-gate tran->tran_bus_unconfig = scsa2usb_scsi_bus_unconfig; 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate /* 8977c478bd9Sstevel@tonic-gate * register with SCSA as an HBA 8987c478bd9Sstevel@tonic-gate * Note that the dma attributes are from parent nexus 8997c478bd9Sstevel@tonic-gate */ 9007c478bd9Sstevel@tonic-gate if (scsi_hba_attach_setup(dip, usba_get_hc_dma_attr(dip), tran, 0)) { 9017c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 9027c478bd9Sstevel@tonic-gate "scsi_hba_attach_setup failed"); 9037c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate goto fail; 9067c478bd9Sstevel@tonic-gate } 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_flags |= SCSA2USB_FLAGS_HBA_ATTACH_SETUP; 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate /* create minor node */ 9117c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, "scsa2usb", S_IFCHR, 9127c478bd9Sstevel@tonic-gate instance << SCSA2USB_MINOR_INSTANCE_SHIFT, 9137c478bd9Sstevel@tonic-gate DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) { 9147c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 9157c478bd9Sstevel@tonic-gate "scsi_attach: ddi_create_minor_node failed"); 9167c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate goto fail; 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate /* open pipes and set scsa2usb_flags */ 9227c478bd9Sstevel@tonic-gate if (scsa2usb_open_usb_pipes(scsa2usbp) == USB_FAILURE) { 9237c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 9247c478bd9Sstevel@tonic-gate "error opening pipes"); 9257c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate goto fail; 9287c478bd9Sstevel@tonic-gate } 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate /* set default block size. updated after read cap cmd */ 9317c478bd9Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 9327c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_lbasize[lun] = DEV_BSIZE; 9337c478bd9Sstevel@tonic-gate } 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate /* initialize PANIC callback */ 9387c478bd9Sstevel@tonic-gate scsa2usb_panic_callb_init(scsa2usbp); 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate /* finally we are all done 'initializing' the device */ 9417c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 9427c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_ONLINE; 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate /* enable PM, mutex needs to be held across this */ 9457c478bd9Sstevel@tonic-gate scsa2usb_create_pm_components(dip, scsa2usbp); 9467c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate /* register for connect/disconnect events */ 9497c478bd9Sstevel@tonic-gate if (usb_register_event_cbs(scsa2usbp->scsa2usb_dip, &scsa2usb_events, 9507c478bd9Sstevel@tonic-gate 0) != USB_SUCCESS) { 9517c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, log_handle, 9527c478bd9Sstevel@tonic-gate "error cb registering"); 9537c478bd9Sstevel@tonic-gate goto fail; 9547c478bd9Sstevel@tonic-gate } 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate /* free the dev_data tree, we no longer need it */ 9577c478bd9Sstevel@tonic-gate usb_free_descr_tree(dip, dev_data); 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate scsa2usb_pm_idle_component(scsa2usbp); 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate /* log the conf file override string if there is one */ 9627c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_override_str) { 963d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 9647c478bd9Sstevel@tonic-gate "scsa2usb.conf override: %s", 9657c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_override_str); 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate if (usb_owns_device(dip)) { 9697c478bd9Sstevel@tonic-gate /* get a ugen handle */ 9707c478bd9Sstevel@tonic-gate bzero(&usb_ugen_info, sizeof (usb_ugen_info)); 9717c478bd9Sstevel@tonic-gate usb_ugen_info.usb_ugen_flags = 0; 9727c478bd9Sstevel@tonic-gate usb_ugen_info.usb_ugen_minor_node_ugen_bits_mask = 9737c478bd9Sstevel@tonic-gate (dev_t)SCSA2USB_MINOR_UGEN_BITS_MASK; 9747c478bd9Sstevel@tonic-gate usb_ugen_info.usb_ugen_minor_node_instance_mask = 9757c478bd9Sstevel@tonic-gate (dev_t)~SCSA2USB_MINOR_UGEN_BITS_MASK; 9767c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_ugen_hdl = 9777c478bd9Sstevel@tonic-gate usb_ugen_get_hdl(dip, &usb_ugen_info); 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate if (usb_ugen_attach(scsa2usbp->scsa2usb_ugen_hdl, cmd) != 9807c478bd9Sstevel@tonic-gate USB_SUCCESS) { 9817c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 9827c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 9837c478bd9Sstevel@tonic-gate "usb_ugen_attach failed"); 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate usb_ugen_release_hdl(scsa2usbp->scsa2usb_ugen_hdl); 9867c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_ugen_hdl = NULL; 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate } 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate /* report device */ 9917c478bd9Sstevel@tonic-gate ddi_report_dev(dip); 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate fail: 9967c478bd9Sstevel@tonic-gate if (scsa2usbp) { 9977c478bd9Sstevel@tonic-gate (void) scsa2usb_cleanup(dip, scsa2usbp); 9987c478bd9Sstevel@tonic-gate } 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 10017c478bd9Sstevel@tonic-gate } 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate /* 10057c478bd9Sstevel@tonic-gate * scsa2usb_detach: 10067c478bd9Sstevel@tonic-gate * detach or suspend driver instance 10077c478bd9Sstevel@tonic-gate */ 10087c478bd9Sstevel@tonic-gate static int 10097c478bd9Sstevel@tonic-gate scsa2usb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 10107c478bd9Sstevel@tonic-gate { 10117c478bd9Sstevel@tonic-gate scsi_hba_tran_t *tran; 10127c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 10137c478bd9Sstevel@tonic-gate int rval; 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate tran = ddi_get_driver_private(dip); 10167c478bd9Sstevel@tonic-gate ASSERT(tran != NULL); 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate scsa2usbp = (scsa2usb_state_t *)tran->tran_hba_private; 10197c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp); 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 1022112116d8Sfb209375 "scsa2usb_detach: dip = 0x%p, cmd = %d", (void *)dip, cmd); 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate switch (cmd) { 10257c478bd9Sstevel@tonic-gate case DDI_DETACH: 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate if (scsa2usb_cleanup(dip, scsa2usbp) != USB_SUCCESS) { 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 10307c478bd9Sstevel@tonic-gate } 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 10337c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 10347c478bd9Sstevel@tonic-gate rval = scsa2usb_cpr_suspend(dip); 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 10377c478bd9Sstevel@tonic-gate default: 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate /* 10447c478bd9Sstevel@tonic-gate * ugen support 10457c478bd9Sstevel@tonic-gate */ 10467c478bd9Sstevel@tonic-gate /* 10477c478bd9Sstevel@tonic-gate * scsa2usb_ugen_open() 10487c478bd9Sstevel@tonic-gate * (all ugen opens and pipe opens are by definition exclusive so it is OK 10497c478bd9Sstevel@tonic-gate * to count opens) 10507c478bd9Sstevel@tonic-gate */ 10517c478bd9Sstevel@tonic-gate static int 10527c478bd9Sstevel@tonic-gate scsa2usb_ugen_open(dev_t *devp, int flag, int sflag, cred_t *cr) 10537c478bd9Sstevel@tonic-gate { 10547c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 10557c478bd9Sstevel@tonic-gate int rval; 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate if ((scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 10587c478bd9Sstevel@tonic-gate SCSA2USB_MINOR_TO_INSTANCE(getminor(*devp)))) == NULL) { 10597c478bd9Sstevel@tonic-gate /* deferred detach */ 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate return (ENXIO); 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 10657c478bd9Sstevel@tonic-gate "scsa2usb_ugen_open: dev_t=0x%lx", *devp); 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate /* if this is the first ugen open, check on transport busy */ 1070*42cac157SVincent Wang if (scsa2usbp->scsa2usb_busy_proc != curproc) { 10717c478bd9Sstevel@tonic-gate while (scsa2usbp->scsa2usb_transport_busy || 10727c478bd9Sstevel@tonic-gate (scsa2usb_all_waitQs_empty(scsa2usbp) != 10737c478bd9Sstevel@tonic-gate USB_SUCCESS)) { 10747c478bd9Sstevel@tonic-gate rval = cv_wait_sig( 10757c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_transport_busy_cv, 10767c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_mutex); 10777c478bd9Sstevel@tonic-gate if (rval == 0) { 10787c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate return (EINTR); 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_transport_busy++; 1084*42cac157SVincent Wang scsa2usbp->scsa2usb_busy_proc = curproc; 10857c478bd9Sstevel@tonic-gate } 1086*42cac157SVincent Wang 10877c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_ugen_open_count++; 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate scsa2usb_raise_power(scsa2usbp); 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate scsa2usb_close_usb_pipes(scsa2usbp); 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate rval = usb_ugen_open(scsa2usbp->scsa2usb_ugen_hdl, devp, flag, 10967c478bd9Sstevel@tonic-gate sflag, cr); 1097*42cac157SVincent Wang if (!rval) { 1098*42cac157SVincent Wang /* 1099*42cac157SVincent Wang * if usb_ugen_open() succeeded, we'll change the minor number 1100*42cac157SVincent Wang * so that we can keep track of every open()/close() issued by 1101*42cac157SVincent Wang * the userland processes. We need to pick a minor number that 1102*42cac157SVincent Wang * is not used by the ugen framework 1103*42cac157SVincent Wang */ 1104*42cac157SVincent Wang 1105*42cac157SVincent Wang usb_ugen_hdl_impl_t *usb_ugen_hdl_impl; 1106*42cac157SVincent Wang ugen_state_t *ugenp; 1107*42cac157SVincent Wang int ugen_minor, clone; 1108*42cac157SVincent Wang 1109*42cac157SVincent Wang mutex_enter(&scsa2usbp->scsa2usb_mutex); 1110*42cac157SVincent Wang 1111*42cac157SVincent Wang usb_ugen_hdl_impl = 1112*42cac157SVincent Wang (usb_ugen_hdl_impl_t *)scsa2usbp->scsa2usb_ugen_hdl; 1113*42cac157SVincent Wang ugenp = usb_ugen_hdl_impl->hdl_ugenp; 1114*42cac157SVincent Wang 1115*42cac157SVincent Wang /* 'clone' is bigger than any ugen minor in use */ 1116*42cac157SVincent Wang for (clone = ugenp->ug_minor_node_table_index + 1; 1117*42cac157SVincent Wang clone < SCSA2USB_MAX_CLONE; clone++) { 1118*42cac157SVincent Wang if (!scsa2usbp->scsa2usb_clones[clone]) 1119*42cac157SVincent Wang break; 1120*42cac157SVincent Wang } 1121*42cac157SVincent Wang 1122*42cac157SVincent Wang if (clone >= SCSA2USB_MAX_CLONE) { 1123*42cac157SVincent Wang cmn_err(CE_WARN, "scsa2usb_ugen_open: too many clones"); 1124*42cac157SVincent Wang rval = EBUSY; 1125*42cac157SVincent Wang mutex_exit(&scsa2usbp->scsa2usb_mutex); 1126*42cac157SVincent Wang goto open_done; 1127*42cac157SVincent Wang } 1128*42cac157SVincent Wang 1129*42cac157SVincent Wang ugen_minor = getminor(*devp) & SCSA2USB_MINOR_UGEN_BITS_MASK; 1130*42cac157SVincent Wang *devp = makedevice(getmajor(*devp), 1131*42cac157SVincent Wang (scsa2usbp->scsa2usb_instance 1132*42cac157SVincent Wang << SCSA2USB_MINOR_INSTANCE_SHIFT) 1133*42cac157SVincent Wang + clone); 1134*42cac157SVincent Wang 1135*42cac157SVincent Wang /* save the ugen minor */ 1136*42cac157SVincent Wang scsa2usbp->scsa2usb_clones[clone] = (uint8_t)ugen_minor; 1137*42cac157SVincent Wang USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 1138*42cac157SVincent Wang "scsa2usb_ugen_open: new dev=%lx, old minor=%x", 1139*42cac157SVincent Wang *devp, ugen_minor); 1140*42cac157SVincent Wang 1141*42cac157SVincent Wang mutex_exit(&scsa2usbp->scsa2usb_mutex); 1142*42cac157SVincent Wang } 1143*42cac157SVincent Wang 1144*42cac157SVincent Wang open_done: 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate if (rval) { 11477c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate /* reopen the pipes */ 11507c478bd9Sstevel@tonic-gate if (--scsa2usbp->scsa2usb_ugen_open_count == 0) { 11517c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_transport_busy--; 1152*42cac157SVincent Wang scsa2usbp->scsa2usb_busy_proc = NULL; 11537c478bd9Sstevel@tonic-gate cv_signal(&scsa2usbp->scsa2usb_transport_busy_cv); 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 1156496d8c83Sfrits 1157496d8c83Sfrits scsa2usb_pm_idle_component(scsa2usbp); 11587c478bd9Sstevel@tonic-gate } 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate return (rval); 11617c478bd9Sstevel@tonic-gate } 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate /* 11657c478bd9Sstevel@tonic-gate * scsa2usb_ugen_close() 11667c478bd9Sstevel@tonic-gate */ 11677c478bd9Sstevel@tonic-gate static int 11687c478bd9Sstevel@tonic-gate scsa2usb_ugen_close(dev_t dev, int flag, int otype, cred_t *cr) 11697c478bd9Sstevel@tonic-gate { 11707c478bd9Sstevel@tonic-gate int rval; 1171*42cac157SVincent Wang int ugen_minor, clone; 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 11747c478bd9Sstevel@tonic-gate SCSA2USB_MINOR_TO_INSTANCE(getminor(dev))); 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate if (scsa2usbp == NULL) { 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate return (ENXIO); 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 11827c478bd9Sstevel@tonic-gate "scsa2usb_ugen_close: dev_t=0x%lx", dev); 11837c478bd9Sstevel@tonic-gate 1184*42cac157SVincent Wang clone = getminor(dev) & SCSA2USB_MINOR_UGEN_BITS_MASK; 1185*42cac157SVincent Wang ugen_minor = scsa2usbp->scsa2usb_clones[clone]; 1186*42cac157SVincent Wang dev = makedevice(getmajor(dev), 1187*42cac157SVincent Wang (scsa2usbp->scsa2usb_instance << SCSA2USB_MINOR_INSTANCE_SHIFT) 1188*42cac157SVincent Wang + ugen_minor); 1189*42cac157SVincent Wang USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 1190*42cac157SVincent Wang "scsa2usb_ugen_close: old dev=%lx", dev); 11917c478bd9Sstevel@tonic-gate rval = usb_ugen_close(scsa2usbp->scsa2usb_ugen_hdl, dev, flag, 11927c478bd9Sstevel@tonic-gate otype, cr); 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate if (rval == 0) { 11957c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 11967c478bd9Sstevel@tonic-gate 1197*42cac157SVincent Wang scsa2usbp->scsa2usb_clones[clone] = 0; 11987c478bd9Sstevel@tonic-gate /* reopen the pipes */ 11997c478bd9Sstevel@tonic-gate if (--scsa2usbp->scsa2usb_ugen_open_count == 0) { 12007c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_transport_busy--; 1201*42cac157SVincent Wang scsa2usbp->scsa2usb_busy_proc = NULL; 12027c478bd9Sstevel@tonic-gate cv_signal(&scsa2usbp->scsa2usb_transport_busy_cv); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 1205496d8c83Sfrits 1206496d8c83Sfrits scsa2usb_pm_idle_component(scsa2usbp); 12077c478bd9Sstevel@tonic-gate } 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate return (rval); 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate /* 12147c478bd9Sstevel@tonic-gate * scsa2usb_ugen_read/write() 12157c478bd9Sstevel@tonic-gate */ 12167c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 12177c478bd9Sstevel@tonic-gate static int 12187c478bd9Sstevel@tonic-gate scsa2usb_ugen_read(dev_t dev, struct uio *uiop, cred_t *credp) 12197c478bd9Sstevel@tonic-gate { 1220*42cac157SVincent Wang int clone, ugen_minor; 12217c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 12227c478bd9Sstevel@tonic-gate SCSA2USB_MINOR_TO_INSTANCE(getminor(dev))); 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate if (scsa2usbp == NULL) { 12257c478bd9Sstevel@tonic-gate 12267c478bd9Sstevel@tonic-gate return (ENXIO); 12277c478bd9Sstevel@tonic-gate } 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 12307c478bd9Sstevel@tonic-gate "scsa2usb_ugen_read: dev_t=0x%lx", dev); 12317c478bd9Sstevel@tonic-gate 1232*42cac157SVincent Wang clone = getminor(dev) & SCSA2USB_MINOR_UGEN_BITS_MASK; 1233*42cac157SVincent Wang ugen_minor = scsa2usbp->scsa2usb_clones[clone]; 1234*42cac157SVincent Wang dev = makedevice(getmajor(dev), 1235*42cac157SVincent Wang (scsa2usbp->scsa2usb_instance << SCSA2USB_MINOR_INSTANCE_SHIFT) 1236*42cac157SVincent Wang + ugen_minor); 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate return (usb_ugen_read(scsa2usbp->scsa2usb_ugen_hdl, dev, 12397c478bd9Sstevel@tonic-gate uiop, credp)); 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 12447c478bd9Sstevel@tonic-gate static int 12457c478bd9Sstevel@tonic-gate scsa2usb_ugen_write(dev_t dev, struct uio *uiop, cred_t *credp) 12467c478bd9Sstevel@tonic-gate { 1247*42cac157SVincent Wang int clone, ugen_minor; 12487c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 12497c478bd9Sstevel@tonic-gate SCSA2USB_MINOR_TO_INSTANCE(getminor(dev))); 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate if (scsa2usbp == NULL) { 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate return (ENXIO); 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 12577c478bd9Sstevel@tonic-gate "scsa2usb_ugen_write: dev_t=0x%lx", dev); 12587c478bd9Sstevel@tonic-gate 1259*42cac157SVincent Wang clone = getminor(dev) & SCSA2USB_MINOR_UGEN_BITS_MASK; 1260*42cac157SVincent Wang ugen_minor = scsa2usbp->scsa2usb_clones[clone]; 1261*42cac157SVincent Wang dev = makedevice(getmajor(dev), 1262*42cac157SVincent Wang (scsa2usbp->scsa2usb_instance << SCSA2USB_MINOR_INSTANCE_SHIFT) 1263*42cac157SVincent Wang + ugen_minor); 1264*42cac157SVincent Wang 12657c478bd9Sstevel@tonic-gate return (usb_ugen_write(scsa2usbp->scsa2usb_ugen_hdl, 12667c478bd9Sstevel@tonic-gate dev, uiop, credp)); 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate /* 12717c478bd9Sstevel@tonic-gate * scsa2usb_ugen_poll 12727c478bd9Sstevel@tonic-gate */ 12737c478bd9Sstevel@tonic-gate static int 12747c478bd9Sstevel@tonic-gate scsa2usb_ugen_poll(dev_t dev, short events, 12757c478bd9Sstevel@tonic-gate int anyyet, short *reventsp, struct pollhead **phpp) 12767c478bd9Sstevel@tonic-gate { 1277*42cac157SVincent Wang int clone, ugen_minor; 12787c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ddi_get_soft_state(scsa2usb_statep, 12797c478bd9Sstevel@tonic-gate SCSA2USB_MINOR_TO_INSTANCE(getminor(dev))); 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate if (scsa2usbp == NULL) { 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate return (ENXIO); 12847c478bd9Sstevel@tonic-gate } 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 12877c478bd9Sstevel@tonic-gate "scsa2usb_ugen_poll: dev_t=0x%lx", dev); 12887c478bd9Sstevel@tonic-gate 1289*42cac157SVincent Wang clone = getminor(dev) & SCSA2USB_MINOR_UGEN_BITS_MASK; 1290*42cac157SVincent Wang ugen_minor = scsa2usbp->scsa2usb_clones[clone]; 1291*42cac157SVincent Wang dev = makedevice(getmajor(dev), 1292*42cac157SVincent Wang (scsa2usbp->scsa2usb_instance << SCSA2USB_MINOR_INSTANCE_SHIFT) 1293*42cac157SVincent Wang + ugen_minor); 1294*42cac157SVincent Wang 12957c478bd9Sstevel@tonic-gate return (usb_ugen_poll(scsa2usbp->scsa2usb_ugen_hdl, dev, events, 12967c478bd9Sstevel@tonic-gate anyyet, reventsp, phpp)); 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate /* 13017c478bd9Sstevel@tonic-gate * scsa2usb_cleanup: 13027c478bd9Sstevel@tonic-gate * cleanup whatever attach has setup 13037c478bd9Sstevel@tonic-gate */ 13047c478bd9Sstevel@tonic-gate static int 13057c478bd9Sstevel@tonic-gate scsa2usb_cleanup(dev_info_t *dip, scsa2usb_state_t *scsa2usbp) 13067c478bd9Sstevel@tonic-gate { 13077c478bd9Sstevel@tonic-gate int rval, i; 13087c478bd9Sstevel@tonic-gate scsa2usb_power_t *pm; 13097c478bd9Sstevel@tonic-gate uint_t lun; 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 13127c478bd9Sstevel@tonic-gate "scsa2usb_cleanup:"); 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate /* wait till the work thread is done */ 13157c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 13167c478bd9Sstevel@tonic-gate for (i = 0; i < SCSA2USB_DRAIN_TIMEOUT; i++) { 13177c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_work_thread_id == NULL) { 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate break; 13207c478bd9Sstevel@tonic-gate } 13217c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 13227c478bd9Sstevel@tonic-gate delay(drv_usectohz(1000000)); 13237c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate if (i >= SCSA2USB_DRAIN_TIMEOUT) { 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate return (USB_FAILURE); 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate /* 13337c478bd9Sstevel@tonic-gate * Disable the event callbacks first, after this point, event 13347c478bd9Sstevel@tonic-gate * callbacks will never get called. Note we shouldn't hold 13357c478bd9Sstevel@tonic-gate * mutex while unregistering events because there may be a 13367c478bd9Sstevel@tonic-gate * competing event callback thread. Event callbacks are done 13377c478bd9Sstevel@tonic-gate * with ndi mutex held and this can cause a potential deadlock. 13387c478bd9Sstevel@tonic-gate */ 13397c478bd9Sstevel@tonic-gate usb_unregister_event_cbs(scsa2usbp->scsa2usb_dip, &scsa2usb_events); 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_flags & SCSA2USB_FLAGS_LOCKS_INIT) { 13427c478bd9Sstevel@tonic-gate /* 13437c478bd9Sstevel@tonic-gate * if a waitQ exists, get rid of it before destroying it 13447c478bd9Sstevel@tonic-gate */ 13457c478bd9Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 13467c478bd9Sstevel@tonic-gate scsa2usb_flush_waitQ(scsa2usbp, lun, CMD_TRAN_ERR); 13477c478bd9Sstevel@tonic-gate usba_destroy_list(&scsa2usbp->scsa2usb_waitQ[lun]); 13487c478bd9Sstevel@tonic-gate } 13497c478bd9Sstevel@tonic-gate 13507c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 13517c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_flags & 13527c478bd9Sstevel@tonic-gate SCSA2USB_FLAGS_HBA_ATTACH_SETUP) { 13537c478bd9Sstevel@tonic-gate (void) scsi_hba_detach(dip); 13547c478bd9Sstevel@tonic-gate scsi_hba_tran_free(scsa2usbp->scsa2usb_tran); 13557c478bd9Sstevel@tonic-gate } 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_flags & 13587c478bd9Sstevel@tonic-gate SCSA2USB_FLAGS_PIPES_OPENED) { 13597c478bd9Sstevel@tonic-gate scsa2usb_close_usb_pipes(scsa2usbp); 13607c478bd9Sstevel@tonic-gate } 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate /* Lower the power */ 13637c478bd9Sstevel@tonic-gate pm = scsa2usbp->scsa2usb_pm; 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate if (pm && (scsa2usbp->scsa2usb_dev_state != 13667c478bd9Sstevel@tonic-gate USB_DEV_DISCONNECTED)) { 13677c478bd9Sstevel@tonic-gate if (pm->scsa2usb_wakeup_enabled) { 13687c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 13697c478bd9Sstevel@tonic-gate (void) pm_raise_power(dip, 0, 13707c478bd9Sstevel@tonic-gate USB_DEV_OS_FULL_PWR); 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate if ((rval = usb_handle_remote_wakeup(dip, 13737c478bd9Sstevel@tonic-gate USB_REMOTE_WAKEUP_DISABLE)) != 13747c478bd9Sstevel@tonic-gate USB_SUCCESS) { 1375d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, 13767c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 13777c478bd9Sstevel@tonic-gate "disable remote wakeup failed " 13787c478bd9Sstevel@tonic-gate "(%d)", rval); 13797c478bd9Sstevel@tonic-gate } 13807c478bd9Sstevel@tonic-gate } else { 13817c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF); 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 13877c478bd9Sstevel@tonic-gate } 13887c478bd9Sstevel@tonic-gate 13897c478bd9Sstevel@tonic-gate if (pm) { 13907c478bd9Sstevel@tonic-gate kmem_free(pm, sizeof (scsa2usb_power_t)); 13917c478bd9Sstevel@tonic-gate } 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_override_str) { 13947c478bd9Sstevel@tonic-gate kmem_free(scsa2usbp->scsa2usb_override_str, 13957c478bd9Sstevel@tonic-gate strlen(scsa2usbp->scsa2usb_override_str) + 1); 13967c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_override_str = NULL; 13977c478bd9Sstevel@tonic-gate } 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate /* remove the minor nodes */ 14007c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 14017c478bd9Sstevel@tonic-gate 14027c478bd9Sstevel@tonic-gate /* Cancel the registered panic callback */ 14037c478bd9Sstevel@tonic-gate scsa2usb_panic_callb_fini(scsa2usbp); 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate mutex_destroy(&scsa2usbp->scsa2usb_mutex); 14087c478bd9Sstevel@tonic-gate cv_destroy(&scsa2usbp->scsa2usb_transport_busy_cv); 14097c478bd9Sstevel@tonic-gate } 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate usb_client_detach(scsa2usbp->scsa2usb_dip, 14127c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_data); 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_ugen_hdl) { 14157c478bd9Sstevel@tonic-gate (void) usb_ugen_detach(scsa2usbp->scsa2usb_ugen_hdl, 14167c478bd9Sstevel@tonic-gate DDI_DETACH); 14177c478bd9Sstevel@tonic-gate usb_ugen_release_hdl(scsa2usbp->scsa2usb_ugen_hdl); 14187c478bd9Sstevel@tonic-gate } 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate usb_free_log_hdl(scsa2usbp->scsa2usb_log_handle); 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate ddi_prop_remove_all(dip); 14237c478bd9Sstevel@tonic-gate 14247c478bd9Sstevel@tonic-gate ddi_soft_state_free(scsa2usb_statep, ddi_get_instance(dip)); 14257c478bd9Sstevel@tonic-gate 14267c478bd9Sstevel@tonic-gate return (USB_SUCCESS); 14277c478bd9Sstevel@tonic-gate } 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate /* 14317c478bd9Sstevel@tonic-gate * scsa2usb_override: 14327c478bd9Sstevel@tonic-gate * some devices may be attached even though their subclass or 14337c478bd9Sstevel@tonic-gate * protocol info is not according to spec. 14347c478bd9Sstevel@tonic-gate * these can be determined by the 'subclass-protocol-override' 14357c478bd9Sstevel@tonic-gate * property set in the conf file. 14367c478bd9Sstevel@tonic-gate */ 14377c478bd9Sstevel@tonic-gate static void 14387c478bd9Sstevel@tonic-gate scsa2usb_override(scsa2usb_state_t *scsa2usbp) 14397c478bd9Sstevel@tonic-gate { 14407c478bd9Sstevel@tonic-gate scsa2usb_ov_t ov; 14417c478bd9Sstevel@tonic-gate char **override_str = NULL; 14427c478bd9Sstevel@tonic-gate char *override_str_cpy; 14437c478bd9Sstevel@tonic-gate uint_t override_str_len, override_str_cpy_len; 14447c478bd9Sstevel@tonic-gate uint_t i; 14457c478bd9Sstevel@tonic-gate usb_dev_descr_t *descr = scsa2usbp->scsa2usb_dev_data->dev_descr; 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_subclass_override = 14507c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_protocol_override = 0; 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, scsa2usbp->scsa2usb_dip, 14537c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "attribute-override-list", 14547c478bd9Sstevel@tonic-gate &override_str, &override_str_len) != DDI_PROP_SUCCESS) { 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate return; 14577c478bd9Sstevel@tonic-gate } 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate /* parse each string in the subclass-protocol-override property */ 14607c478bd9Sstevel@tonic-gate for (i = 0; i < override_str_len; i++) { 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 14637c478bd9Sstevel@tonic-gate "override_str[%d] = %s", i, override_str[i]); 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate /* 14667c478bd9Sstevel@tonic-gate * save a copy of the override string for possible 14677c478bd9Sstevel@tonic-gate * inclusion in soft state later 14687c478bd9Sstevel@tonic-gate */ 14697c478bd9Sstevel@tonic-gate override_str_cpy_len = strlen(override_str[i]) + 1; 14707c478bd9Sstevel@tonic-gate override_str_cpy = kmem_zalloc(override_str_cpy_len, KM_SLEEP); 14717c478bd9Sstevel@tonic-gate (void) strcpy(override_str_cpy, override_str[i]); 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate bzero(&ov, sizeof (scsa2usb_ov_t)); 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate if (scsa2usb_parse_input_str(override_str[i], &ov, 14767c478bd9Sstevel@tonic-gate scsa2usbp) == USB_FAILURE) { 14777c478bd9Sstevel@tonic-gate kmem_free(override_str_cpy, override_str_cpy_len); 14787c478bd9Sstevel@tonic-gate continue; 14797c478bd9Sstevel@tonic-gate } 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate /* 14827c478bd9Sstevel@tonic-gate * see if subclass/protocol needs to be overridden for device 14837c478bd9Sstevel@tonic-gate * or if device should not be power managed 14847c478bd9Sstevel@tonic-gate * if there'a a match, save the override string in soft state 14857c478bd9Sstevel@tonic-gate */ 14867c478bd9Sstevel@tonic-gate if (((descr->idVendor == (uint16_t)ov.vid) || (ov.vid == 0)) && 14877c478bd9Sstevel@tonic-gate ((descr->idProduct == (uint16_t)ov.pid) || (ov.pid == 0)) && 14887c478bd9Sstevel@tonic-gate ((descr->bcdDevice == (uint16_t)ov.rev) || (ov.rev == 0))) { 14897c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_subclass_override = ov.subclass; 14907c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_protocol_override = ov.protocol; 14917c478bd9Sstevel@tonic-gate 14924610e4a0Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, 14937c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 14947c478bd9Sstevel@tonic-gate "vid=0x%x pid=0x%x rev=0x%x subclass=0x%x " 14957c478bd9Sstevel@tonic-gate "protocol=0x%x " 14960167b58cScg149915 "pmoff=%d fake_removable=%d modesense=%d " 14977c478bd9Sstevel@tonic-gate "reduced-cmd-support=%d", 14987c478bd9Sstevel@tonic-gate ov.vid, ov.pid, ov.rev, ov.subclass, ov.protocol, 14990167b58cScg149915 ov.pmoff, ov.fake_removable, ov.no_modesense, 15007c478bd9Sstevel@tonic-gate ov.reduced_cmd_support); 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate if (ov.pmoff) { 15037c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= ~SCSA2USB_ATTRS_PM; 15047c478bd9Sstevel@tonic-gate } 15050167b58cScg149915 if (ov.fake_removable) { 15067c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= 15077c478bd9Sstevel@tonic-gate ~SCSA2USB_ATTRS_RMB; 15087c478bd9Sstevel@tonic-gate } 15097c478bd9Sstevel@tonic-gate if (ov.no_modesense) { 15107c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= 15117c478bd9Sstevel@tonic-gate ~SCSA2USB_ATTRS_MODE_SENSE; 15127c478bd9Sstevel@tonic-gate } 15137c478bd9Sstevel@tonic-gate if (ov.reduced_cmd_support) { 15147c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= 15157c478bd9Sstevel@tonic-gate ~SCSA2USB_ATTRS_REDUCED_CMD; 15167c478bd9Sstevel@tonic-gate } 15177c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_override_str = override_str_cpy; 15187c478bd9Sstevel@tonic-gate break; 15197c478bd9Sstevel@tonic-gate } else { 15207c478bd9Sstevel@tonic-gate kmem_free(override_str_cpy, override_str_cpy_len); 15217c478bd9Sstevel@tonic-gate } 15227c478bd9Sstevel@tonic-gate } 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate ddi_prop_free(override_str); 15257c478bd9Sstevel@tonic-gate } 15267c478bd9Sstevel@tonic-gate 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate /* 15297c478bd9Sstevel@tonic-gate * scsa2usb_parse_input_str: 15307c478bd9Sstevel@tonic-gate * parse one conf file subclass-protocol-override string 15317c478bd9Sstevel@tonic-gate * return vendor id, product id, revision, subclass, protocol 15327c478bd9Sstevel@tonic-gate * function return is success or failure 15337c478bd9Sstevel@tonic-gate */ 15347c478bd9Sstevel@tonic-gate static int 15357c478bd9Sstevel@tonic-gate scsa2usb_parse_input_str(char *str, scsa2usb_ov_t *ovp, 15367c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp) 15377c478bd9Sstevel@tonic-gate { 15387c478bd9Sstevel@tonic-gate char *input_field, *input_value; 15397c478bd9Sstevel@tonic-gate char *lasts; 15407c478bd9Sstevel@tonic-gate uint_t i; 15417c478bd9Sstevel@tonic-gate u_longlong_t value; 15427c478bd9Sstevel@tonic-gate 15437c478bd9Sstevel@tonic-gate /* parse all the input pairs in the string */ 15447c478bd9Sstevel@tonic-gate for (input_field = scsa2usb_strtok_r(str, "=", &lasts); 15457c478bd9Sstevel@tonic-gate input_field != NULL; 15467c478bd9Sstevel@tonic-gate input_field = scsa2usb_strtok_r(lasts, "=", &lasts)) { 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate if ((input_value = scsa2usb_strtok_r(lasts, " ", &lasts)) == 15497c478bd9Sstevel@tonic-gate NULL) { 15507c478bd9Sstevel@tonic-gate scsa2usb_override_error("format", scsa2usbp); 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate return (USB_FAILURE); 15537c478bd9Sstevel@tonic-gate } 15547c478bd9Sstevel@tonic-gate /* if input value is a 'don't care', skip to the next pair */ 15557c478bd9Sstevel@tonic-gate if (strcmp(input_value, "*") == 0) { 15567c478bd9Sstevel@tonic-gate continue; 15577c478bd9Sstevel@tonic-gate } 15587c478bd9Sstevel@tonic-gate if (strcasecmp(input_field, "vid") == 0) { 15597c478bd9Sstevel@tonic-gate if (kobj_getvalue(input_value, &value) == -1) { 15607c478bd9Sstevel@tonic-gate scsa2usb_override_error("vendor id", scsa2usbp); 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate return (USB_FAILURE); 15637c478bd9Sstevel@tonic-gate } 15647c478bd9Sstevel@tonic-gate ovp->vid = (int)value; 15657c478bd9Sstevel@tonic-gate } else if (strcasecmp(input_field, "pid") == 0) { 15667c478bd9Sstevel@tonic-gate if (kobj_getvalue(input_value, &value) == -1) { 15677c478bd9Sstevel@tonic-gate scsa2usb_override_error("product id", 15687c478bd9Sstevel@tonic-gate scsa2usbp); 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate return (USB_FAILURE); 15717c478bd9Sstevel@tonic-gate } 15727c478bd9Sstevel@tonic-gate ovp->pid = (int)value; 15737c478bd9Sstevel@tonic-gate } else if (strcasecmp(input_field, "rev") == 0) { 15747c478bd9Sstevel@tonic-gate if (kobj_getvalue(input_value, &value) == -1) { 15757c478bd9Sstevel@tonic-gate scsa2usb_override_error("revision id", 15767c478bd9Sstevel@tonic-gate scsa2usbp); 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate return (USB_FAILURE); 15797c478bd9Sstevel@tonic-gate } 15807c478bd9Sstevel@tonic-gate ovp->rev = (int)value; 15817c478bd9Sstevel@tonic-gate } else if (strcasecmp(input_field, "subclass") == 0) { 15827c478bd9Sstevel@tonic-gate for (i = 0; i < N_SCSA2USB_SUBC_OVERRIDE; i++) { 15837c478bd9Sstevel@tonic-gate if (strcasecmp(input_value, 15847c478bd9Sstevel@tonic-gate scsa2usb_subclass[i].name) == 0) { 15857c478bd9Sstevel@tonic-gate ovp->subclass = 15867c478bd9Sstevel@tonic-gate scsa2usb_subclass[i].value; 15877c478bd9Sstevel@tonic-gate break; 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate if (ovp->subclass == 0) { 15917c478bd9Sstevel@tonic-gate scsa2usb_override_error("subclass", scsa2usbp); 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate return (USB_FAILURE); 15947c478bd9Sstevel@tonic-gate } 15957c478bd9Sstevel@tonic-gate } else if (strcasecmp(input_field, "protocol") == 0) { 15967c478bd9Sstevel@tonic-gate for (i = 0; i < N_SCSA2USB_PROT_OVERRIDE; i++) { 15977c478bd9Sstevel@tonic-gate if (strcasecmp(input_value, 15987c478bd9Sstevel@tonic-gate scsa2usb_protocol[i].name) == 0) { 15997c478bd9Sstevel@tonic-gate ovp->protocol = 16007c478bd9Sstevel@tonic-gate scsa2usb_protocol[i].value; 16017c478bd9Sstevel@tonic-gate break; 16027c478bd9Sstevel@tonic-gate } 16037c478bd9Sstevel@tonic-gate } 16047c478bd9Sstevel@tonic-gate if (ovp->protocol == 0) { 16057c478bd9Sstevel@tonic-gate scsa2usb_override_error("protocol", scsa2usbp); 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate return (USB_FAILURE); 16087c478bd9Sstevel@tonic-gate } 16097c478bd9Sstevel@tonic-gate } else if (strcasecmp(input_field, "pm") == 0) { 16107c478bd9Sstevel@tonic-gate if (strcasecmp(input_value, "off") == 0) { 16117c478bd9Sstevel@tonic-gate ovp->pmoff = 1; 16127c478bd9Sstevel@tonic-gate break; 16137c478bd9Sstevel@tonic-gate } else { 16147c478bd9Sstevel@tonic-gate scsa2usb_override_error("pm", scsa2usbp); 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate return (USB_FAILURE); 16177c478bd9Sstevel@tonic-gate } 16187c478bd9Sstevel@tonic-gate } else if (strcasecmp(input_field, "removable") == 0) { 16190167b58cScg149915 if (strcasecmp(input_value, "true") == 0) { 16200167b58cScg149915 ovp->fake_removable = 1; 16217c478bd9Sstevel@tonic-gate break; 16227c478bd9Sstevel@tonic-gate } else { 16237c478bd9Sstevel@tonic-gate scsa2usb_override_error("removable", scsa2usbp); 16247c478bd9Sstevel@tonic-gate 16257c478bd9Sstevel@tonic-gate return (USB_FAILURE); 16267c478bd9Sstevel@tonic-gate } 16277c478bd9Sstevel@tonic-gate } else if (strcasecmp(input_field, "modesense") == 0) { 16287c478bd9Sstevel@tonic-gate if (strcasecmp(input_value, "false") == 0) { 16297c478bd9Sstevel@tonic-gate ovp->no_modesense = 1; 16307c478bd9Sstevel@tonic-gate break; 16317c478bd9Sstevel@tonic-gate } else { 16327c478bd9Sstevel@tonic-gate scsa2usb_override_error("modesense", 16337c478bd9Sstevel@tonic-gate scsa2usbp); 16347c478bd9Sstevel@tonic-gate 16357c478bd9Sstevel@tonic-gate return (USB_FAILURE); 16367c478bd9Sstevel@tonic-gate } 16377c478bd9Sstevel@tonic-gate } else if (strcasecmp(input_field, 16387c478bd9Sstevel@tonic-gate "reduced-cmd-support") == 0) { 16397c478bd9Sstevel@tonic-gate if (strcasecmp(input_value, "true") == 0) { 16407c478bd9Sstevel@tonic-gate ovp->reduced_cmd_support = 1; 16417c478bd9Sstevel@tonic-gate break; 16427c478bd9Sstevel@tonic-gate } else { 16437c478bd9Sstevel@tonic-gate scsa2usb_override_error( 16447c478bd9Sstevel@tonic-gate "reduced-cmd-support", scsa2usbp); 16457c478bd9Sstevel@tonic-gate 16467c478bd9Sstevel@tonic-gate return (USB_FAILURE); 16477c478bd9Sstevel@tonic-gate } 16487c478bd9Sstevel@tonic-gate } else { 16494610e4a0Sfrits scsa2usb_override_error(input_field, scsa2usbp); 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate return (USB_FAILURE); 16527c478bd9Sstevel@tonic-gate } 16537c478bd9Sstevel@tonic-gate } 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate return (USB_SUCCESS); 16567c478bd9Sstevel@tonic-gate } 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate 16597c478bd9Sstevel@tonic-gate /* 16607c478bd9Sstevel@tonic-gate * scsa2usb_override_error: 16617c478bd9Sstevel@tonic-gate * print an error message if conf file string is bad format 16627c478bd9Sstevel@tonic-gate */ 16637c478bd9Sstevel@tonic-gate static void 16647c478bd9Sstevel@tonic-gate scsa2usb_override_error(char *input_field, scsa2usb_state_t *scsa2usbp) 16657c478bd9Sstevel@tonic-gate { 16667c478bd9Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 16674610e4a0Sfrits "invalid %s in scsa2usb.conf file entry", input_field); 16687c478bd9Sstevel@tonic-gate } 16697c478bd9Sstevel@tonic-gate 16707c478bd9Sstevel@tonic-gate /* 16717c478bd9Sstevel@tonic-gate * scsa2usb_strtok_r: 16727c478bd9Sstevel@tonic-gate * parse a list of tokens 16737c478bd9Sstevel@tonic-gate */ 16747c478bd9Sstevel@tonic-gate static char * 16757c478bd9Sstevel@tonic-gate scsa2usb_strtok_r(char *p, char *sep, char **lasts) 16767c478bd9Sstevel@tonic-gate { 16777c478bd9Sstevel@tonic-gate char *e; 16787c478bd9Sstevel@tonic-gate char *tok = NULL; 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate if (p == 0 || *p == 0) { 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate return (NULL); 16837c478bd9Sstevel@tonic-gate } 16847c478bd9Sstevel@tonic-gate 16857c478bd9Sstevel@tonic-gate e = p+strlen(p); 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate do { 16887c478bd9Sstevel@tonic-gate if (strchr(sep, *p) != NULL) { 16897c478bd9Sstevel@tonic-gate if (tok != NULL) { 16907c478bd9Sstevel@tonic-gate *p = 0; 16917c478bd9Sstevel@tonic-gate *lasts = p+1; 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate return (tok); 16947c478bd9Sstevel@tonic-gate } 16957c478bd9Sstevel@tonic-gate } else if (tok == NULL) { 16967c478bd9Sstevel@tonic-gate tok = p; 16977c478bd9Sstevel@tonic-gate } 16987c478bd9Sstevel@tonic-gate } while (++p < e); 16997c478bd9Sstevel@tonic-gate 17007c478bd9Sstevel@tonic-gate *lasts = NULL; 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate return (tok); 17037c478bd9Sstevel@tonic-gate } 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate 17067c478bd9Sstevel@tonic-gate /* 17077c478bd9Sstevel@tonic-gate * scsa2usb_validate_attrs: 17087c478bd9Sstevel@tonic-gate * many devices have BO/CB/CBI protocol support issues. 17097c478bd9Sstevel@tonic-gate * use vendor/product info to reset the 17107c478bd9Sstevel@tonic-gate * individual erroneous attributes 17117c478bd9Sstevel@tonic-gate * 17127c478bd9Sstevel@tonic-gate * NOTE: we look at only device at a time (at attach time) 17137c478bd9Sstevel@tonic-gate */ 17147c478bd9Sstevel@tonic-gate static void 17157c478bd9Sstevel@tonic-gate scsa2usb_validate_attrs(scsa2usb_state_t *scsa2usbp) 17167c478bd9Sstevel@tonic-gate { 17177c478bd9Sstevel@tonic-gate int i, mask; 17187c478bd9Sstevel@tonic-gate usb_dev_descr_t *desc = scsa2usbp->scsa2usb_dev_data->dev_descr; 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate if (!SCSA2USB_IS_BULK_ONLY(scsa2usbp)) { 17217c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= ~SCSA2USB_ATTRS_GET_LUN; 17227c478bd9Sstevel@tonic-gate } 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate /* determine if this device is on the blacklist */ 17257c478bd9Sstevel@tonic-gate for (i = 0; i < N_SCSA2USB_BLACKLIST; i++) { 17267c478bd9Sstevel@tonic-gate if ((scsa2usb_blacklist[i].idVendor == desc->idVendor) && 17277c478bd9Sstevel@tonic-gate ((scsa2usb_blacklist[i].idProduct == desc->idProduct) || 17287c478bd9Sstevel@tonic-gate (scsa2usb_blacklist[i].idProduct == X))) { 17297c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= 17307c478bd9Sstevel@tonic-gate ~(scsa2usb_blacklist[i].attributes); 17317c478bd9Sstevel@tonic-gate break; 17327c478bd9Sstevel@tonic-gate } 17337c478bd9Sstevel@tonic-gate } 17347c478bd9Sstevel@tonic-gate 17357c478bd9Sstevel@tonic-gate /* 17367c478bd9Sstevel@tonic-gate * Mitsumi's CD-RW drives subclass isn't UFI. 17377c478bd9Sstevel@tonic-gate * But they support UFI command-set (this code ensures that) 17387c478bd9Sstevel@tonic-gate * NOTE: This is a special case, and is being called out so. 17397c478bd9Sstevel@tonic-gate */ 17407c478bd9Sstevel@tonic-gate if (desc->idVendor == MS_MITSUMI_VID) { 17417c478bd9Sstevel@tonic-gate mask = scsa2usbp->scsa2usb_cmd_protocol & SCSA2USB_CMDSET_MASK; 17427c478bd9Sstevel@tonic-gate if (mask) { 17437c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol &= ~mask; 17447c478bd9Sstevel@tonic-gate } 17457c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cmd_protocol |= SCSA2USB_UFI_CMDSET; 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_attrs != SCSA2USB_ALL_ATTRS) { 17497c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 17507c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 17517c478bd9Sstevel@tonic-gate "scsa2usb attributes modified: 0x%x", 17527c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs); 17537c478bd9Sstevel@tonic-gate } 17547c478bd9Sstevel@tonic-gate } 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate /* 17587c478bd9Sstevel@tonic-gate * scsa2usb_create_luns: 17597c478bd9Sstevel@tonic-gate * check the number of luns but continue if the check fails, 17607c478bd9Sstevel@tonic-gate * create child nodes for each lun 17617c478bd9Sstevel@tonic-gate */ 17627c478bd9Sstevel@tonic-gate static void 17637c478bd9Sstevel@tonic-gate scsa2usb_create_luns(scsa2usb_state_t *scsa2usbp) 17647c478bd9Sstevel@tonic-gate { 17657c478bd9Sstevel@tonic-gate int lun, rval; 17667c478bd9Sstevel@tonic-gate char *compatible[MAX_COMPAT_NAMES]; /* compatible names */ 17677c478bd9Sstevel@tonic-gate dev_info_t *cdip; 17687c478bd9Sstevel@tonic-gate uchar_t dtype; 17697c478bd9Sstevel@tonic-gate char *node_name; 17707c478bd9Sstevel@tonic-gate char *driver_name = NULL; 17717c478bd9Sstevel@tonic-gate 17727c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 17737c478bd9Sstevel@tonic-gate "scsa2usb_create_luns:"); 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate /* Set n_luns to 1 by default (for floppies and other devices) */ 17787c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_n_luns = 1; 17797c478bd9Sstevel@tonic-gate 17807c478bd9Sstevel@tonic-gate /* 17817c478bd9Sstevel@tonic-gate * Check if there are any device out there which don't 17827c478bd9Sstevel@tonic-gate * support the GET_MAX_LUN command. If so, don't issue 17837c478bd9Sstevel@tonic-gate * control request to them. 17847c478bd9Sstevel@tonic-gate */ 17857c478bd9Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_GET_LUN) == 0) { 17865547f1d8SBinzi Cao - Sun Microsystems - Beijing China USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 17877c478bd9Sstevel@tonic-gate "get_max_lun cmd not supported"); 17887c478bd9Sstevel@tonic-gate } else { 17897c478bd9Sstevel@tonic-gate if (SCSA2USB_IS_BULK_ONLY(scsa2usbp)) { 17907c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_n_luns = 17917c478bd9Sstevel@tonic-gate scsa2usb_bulk_only_get_max_lun(scsa2usbp); 17927c478bd9Sstevel@tonic-gate } 17937c478bd9Sstevel@tonic-gate } 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 17967c478bd9Sstevel@tonic-gate "scsa2usb_create_luns: %d luns found", scsa2usbp->scsa2usb_n_luns); 17977c478bd9Sstevel@tonic-gate 17987c478bd9Sstevel@tonic-gate /* 17997c478bd9Sstevel@tonic-gate * create disk child for each lun 18007c478bd9Sstevel@tonic-gate */ 18017c478bd9Sstevel@tonic-gate for (lun = 0; lun < scsa2usbp->scsa2usb_n_luns; lun++) { 18027c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_lun_dip[lun] == NULL); 18037c478bd9Sstevel@tonic-gate 18047c478bd9Sstevel@tonic-gate /* do an inquiry to get the dtype of this lun */ 18057c478bd9Sstevel@tonic-gate scsa2usb_do_inquiry(scsa2usbp, 0, lun); 18067c478bd9Sstevel@tonic-gate 18077c478bd9Sstevel@tonic-gate dtype = scsa2usbp->scsa2usb_lun_inquiry[lun]. 18087c478bd9Sstevel@tonic-gate inq_dtype & DTYPE_MASK; 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 18117c478bd9Sstevel@tonic-gate "dtype[%d]=0x%x", lun, dtype); 18127c478bd9Sstevel@tonic-gate 18137c478bd9Sstevel@tonic-gate driver_name = NULL; 18147c478bd9Sstevel@tonic-gate 18157c478bd9Sstevel@tonic-gate switch (dtype) { 18167c478bd9Sstevel@tonic-gate case DTYPE_DIRECT: 18177c478bd9Sstevel@tonic-gate case DTYPE_RODIRECT: 18187c478bd9Sstevel@tonic-gate case DTYPE_OPTICAL: 18197c478bd9Sstevel@tonic-gate node_name = "disk"; 18207c478bd9Sstevel@tonic-gate driver_name = "sd"; 18217c478bd9Sstevel@tonic-gate 18227c478bd9Sstevel@tonic-gate break; 18237c478bd9Sstevel@tonic-gate case DTYPE_SEQUENTIAL: 18247c478bd9Sstevel@tonic-gate node_name = "tape"; 18257c478bd9Sstevel@tonic-gate driver_name = "st"; 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate break; 18287c478bd9Sstevel@tonic-gate case DTYPE_PRINTER: 18297c478bd9Sstevel@tonic-gate node_name = "printer"; 18307c478bd9Sstevel@tonic-gate 18317c478bd9Sstevel@tonic-gate break; 18327c478bd9Sstevel@tonic-gate case DTYPE_PROCESSOR: 18337c478bd9Sstevel@tonic-gate node_name = "processor"; 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate break; 18367c478bd9Sstevel@tonic-gate case DTYPE_WORM: 18377c478bd9Sstevel@tonic-gate node_name = "worm"; 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate break; 18407c478bd9Sstevel@tonic-gate case DTYPE_SCANNER: 18417c478bd9Sstevel@tonic-gate node_name = "scanner"; 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate break; 18447c478bd9Sstevel@tonic-gate case DTYPE_CHANGER: 18457c478bd9Sstevel@tonic-gate node_name = "changer"; 18467c478bd9Sstevel@tonic-gate 18477c478bd9Sstevel@tonic-gate break; 18487c478bd9Sstevel@tonic-gate case DTYPE_COMM: 18497c478bd9Sstevel@tonic-gate node_name = "comm"; 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate break; 18527c478bd9Sstevel@tonic-gate case DTYPE_ARRAY_CTRL: 18537c478bd9Sstevel@tonic-gate node_name = "array_ctrl"; 18547c478bd9Sstevel@tonic-gate 18557c478bd9Sstevel@tonic-gate break; 18567c478bd9Sstevel@tonic-gate case DTYPE_ESI: 18577c478bd9Sstevel@tonic-gate node_name = "esi"; 18587c478bd9Sstevel@tonic-gate driver_name = "ses"; 18597c478bd9Sstevel@tonic-gate 18607c478bd9Sstevel@tonic-gate break; 18617c478bd9Sstevel@tonic-gate default: 18627c478bd9Sstevel@tonic-gate node_name = "generic"; 18637c478bd9Sstevel@tonic-gate 18647c478bd9Sstevel@tonic-gate break; 18657c478bd9Sstevel@tonic-gate } 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate if (driver_name) { 18687c478bd9Sstevel@tonic-gate compatible[0] = driver_name; 18697c478bd9Sstevel@tonic-gate } 18707c478bd9Sstevel@tonic-gate 18717c478bd9Sstevel@tonic-gate ndi_devi_alloc_sleep(scsa2usbp->scsa2usb_dip, node_name, 1872fa9e4066Sahrens (pnode_t)DEVI_SID_NODEID, &cdip); 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate /* attach target & lun properties */ 18757c478bd9Sstevel@tonic-gate rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "target", 0); 18767c478bd9Sstevel@tonic-gate if (rval != DDI_PROP_SUCCESS) { 18777c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 18787c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 18797c478bd9Sstevel@tonic-gate "ndi_prop_update_int target failed %d", rval); 18807c478bd9Sstevel@tonic-gate (void) ndi_devi_free(cdip); 18817c478bd9Sstevel@tonic-gate continue; 18827c478bd9Sstevel@tonic-gate } 18837c478bd9Sstevel@tonic-gate 18840167b58cScg149915 rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, 18850167b58cScg149915 "hotpluggable"); 18860167b58cScg149915 if (rval != DDI_PROP_SUCCESS) { 18870167b58cScg149915 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 18880167b58cScg149915 scsa2usbp->scsa2usb_log_handle, 18890167b58cScg149915 "ndi_prop_create_boolean hotpluggable failed %d", 18900167b58cScg149915 rval); 18910167b58cScg149915 ddi_prop_remove_all(cdip); 18920167b58cScg149915 (void) ndi_devi_free(cdip); 18930167b58cScg149915 continue; 18940167b58cScg149915 } 18950167b58cScg149915 /* 18960167b58cScg149915 * Some devices don't support LOG SENSE, so tells 18970167b58cScg149915 * sd driver not to send this command. 18980167b58cScg149915 */ 18990167b58cScg149915 rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, 19000167b58cScg149915 "pm-capable", 1); 19010167b58cScg149915 if (rval != DDI_PROP_SUCCESS) { 19020167b58cScg149915 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 19030167b58cScg149915 scsa2usbp->scsa2usb_log_handle, 19040167b58cScg149915 "ndi_prop_update_int pm-capable failed %d", rval); 19050167b58cScg149915 ddi_prop_remove_all(cdip); 19060167b58cScg149915 (void) ndi_devi_free(cdip); 19070167b58cScg149915 continue; 19080167b58cScg149915 } 19090167b58cScg149915 19107c478bd9Sstevel@tonic-gate rval = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "lun", lun); 19117c478bd9Sstevel@tonic-gate if (rval != DDI_PROP_SUCCESS) { 19127c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 19137c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 19147c478bd9Sstevel@tonic-gate "ndi_prop_update_int lun failed %d", rval); 19157c478bd9Sstevel@tonic-gate ddi_prop_remove_all(cdip); 19167c478bd9Sstevel@tonic-gate (void) ndi_devi_free(cdip); 19177c478bd9Sstevel@tonic-gate continue; 19187c478bd9Sstevel@tonic-gate } 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate if (driver_name) { 19217c478bd9Sstevel@tonic-gate rval = ndi_prop_update_string_array(DDI_DEV_T_NONE, 19227c478bd9Sstevel@tonic-gate cdip, "compatible", (char **)compatible, 19237c478bd9Sstevel@tonic-gate MAX_COMPAT_NAMES); 19247c478bd9Sstevel@tonic-gate if (rval != DDI_PROP_SUCCESS) { 19257c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 19267c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 19277c478bd9Sstevel@tonic-gate "ndi_prop_update_string_array failed %d", 19287c478bd9Sstevel@tonic-gate rval); 19297c478bd9Sstevel@tonic-gate ddi_prop_remove_all(cdip); 19307c478bd9Sstevel@tonic-gate (void) ndi_devi_free(cdip); 19317c478bd9Sstevel@tonic-gate continue; 19327c478bd9Sstevel@tonic-gate } 19337c478bd9Sstevel@tonic-gate } 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate /* 19367c478bd9Sstevel@tonic-gate * add property "usb" so we always verify that it is our child 19377c478bd9Sstevel@tonic-gate */ 19387c478bd9Sstevel@tonic-gate rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "usb"); 19397c478bd9Sstevel@tonic-gate if (rval != DDI_PROP_SUCCESS) { 19407c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 19417c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 19427c478bd9Sstevel@tonic-gate "ndi_prop_create_boolean failed %d", rval); 19437c478bd9Sstevel@tonic-gate ddi_prop_remove_all(cdip); 19447c478bd9Sstevel@tonic-gate (void) ndi_devi_free(cdip); 19457c478bd9Sstevel@tonic-gate continue; 19467c478bd9Sstevel@tonic-gate } 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 19497c478bd9Sstevel@tonic-gate (void) ddi_initchild(scsa2usbp->scsa2usb_dip, cdip); 19507c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 19517c478bd9Sstevel@tonic-gate 19527c478bd9Sstevel@tonic-gate usba_set_usba_device(cdip, 19537c478bd9Sstevel@tonic-gate usba_get_usba_device(scsa2usbp->scsa2usb_dip)); 19547c478bd9Sstevel@tonic-gate } 19557c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 19567c478bd9Sstevel@tonic-gate } 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate 19597c478bd9Sstevel@tonic-gate /* 19607c478bd9Sstevel@tonic-gate * scsa2usb_is_usb: 19617c478bd9Sstevel@tonic-gate * scsa2usb gets called for all possible sd children. 19627c478bd9Sstevel@tonic-gate * we can only accept usb children 19637c478bd9Sstevel@tonic-gate */ 19647c478bd9Sstevel@tonic-gate static int 19657c478bd9Sstevel@tonic-gate scsa2usb_is_usb(dev_info_t *dip) 19667c478bd9Sstevel@tonic-gate { 19677c478bd9Sstevel@tonic-gate if (dip) { 19687c478bd9Sstevel@tonic-gate return (ddi_prop_exists(DDI_DEV_T_ANY, dip, 19697c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "usb")); 19707c478bd9Sstevel@tonic-gate } 19717c478bd9Sstevel@tonic-gate return (0); 19727c478bd9Sstevel@tonic-gate } 19737c478bd9Sstevel@tonic-gate 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate /* 19767c478bd9Sstevel@tonic-gate * Panic Stuff 19777c478bd9Sstevel@tonic-gate * scsa2usb_panic_callb_init: 19787c478bd9Sstevel@tonic-gate * initialize PANIC callb and free allocated resources 19797c478bd9Sstevel@tonic-gate */ 19807c478bd9Sstevel@tonic-gate static void 19817c478bd9Sstevel@tonic-gate scsa2usb_panic_callb_init(scsa2usb_state_t *scsa2usbp) 19827c478bd9Sstevel@tonic-gate { 19837c478bd9Sstevel@tonic-gate /* 19847c478bd9Sstevel@tonic-gate * In case the system panics, the sync command flushes 19857c478bd9Sstevel@tonic-gate * dirty FS pages or buffers. This would cause a hang 19867c478bd9Sstevel@tonic-gate * in USB. 19877c478bd9Sstevel@tonic-gate * The reason for the failure is that we enter 19887c478bd9Sstevel@tonic-gate * polled mode (interrupts disabled) and HCD gets stuck 19897c478bd9Sstevel@tonic-gate * trying to execute bulk requests 19907c478bd9Sstevel@tonic-gate * The panic_callback registered below provides a warning 19917c478bd9Sstevel@tonic-gate * that a panic has occurred and from that point onwards, we 19927c478bd9Sstevel@tonic-gate * complete each request successfully and immediately. This 19937c478bd9Sstevel@tonic-gate * will fake successful syncing so at least the rest of the 19947c478bd9Sstevel@tonic-gate * filesystems complete syncing. 19957c478bd9Sstevel@tonic-gate */ 19967c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info = 19977c478bd9Sstevel@tonic-gate kmem_zalloc(sizeof (scsa2usb_cpr_t), KM_SLEEP); 19987c478bd9Sstevel@tonic-gate mutex_init(&scsa2usbp->scsa2usb_panic_info->lockp, 19997c478bd9Sstevel@tonic-gate NULL, MUTEX_DRIVER, 20007c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_data->dev_iblock_cookie); 20017c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info->statep = scsa2usbp; 20027c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info->cpr.cc_lockp = 20037c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_panic_info->lockp; 20047c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info->cpr.cc_id = 20057c478bd9Sstevel@tonic-gate callb_add(scsa2usb_panic_callb, 20067c478bd9Sstevel@tonic-gate (void *)scsa2usbp->scsa2usb_panic_info, 20077c478bd9Sstevel@tonic-gate CB_CL_PANIC, "scsa2usb"); 20087c478bd9Sstevel@tonic-gate } 20097c478bd9Sstevel@tonic-gate 20107c478bd9Sstevel@tonic-gate 20117c478bd9Sstevel@tonic-gate /* 20127c478bd9Sstevel@tonic-gate * scsa2usb_panic_callb_fini: 20137c478bd9Sstevel@tonic-gate * cancel out PANIC callb and free allocated resources 20147c478bd9Sstevel@tonic-gate */ 20157c478bd9Sstevel@tonic-gate static void 20167c478bd9Sstevel@tonic-gate scsa2usb_panic_callb_fini(scsa2usb_state_t *scsa2usbp) 20177c478bd9Sstevel@tonic-gate { 20187c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_panic_info) { 20197c478bd9Sstevel@tonic-gate SCSA2USB_CANCEL_CB(scsa2usbp->scsa2usb_panic_info->cpr.cc_id); 20207c478bd9Sstevel@tonic-gate mutex_destroy(&scsa2usbp->scsa2usb_panic_info->lockp); 20217c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info->statep = NULL; 20227c478bd9Sstevel@tonic-gate kmem_free(scsa2usbp->scsa2usb_panic_info, 20237c478bd9Sstevel@tonic-gate sizeof (scsa2usb_cpr_t)); 20247c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_panic_info = NULL; 20257c478bd9Sstevel@tonic-gate } 20267c478bd9Sstevel@tonic-gate } 20277c478bd9Sstevel@tonic-gate 20287c478bd9Sstevel@tonic-gate 20297c478bd9Sstevel@tonic-gate /* 20307c478bd9Sstevel@tonic-gate * scsa2usb_panic_callb: 20317c478bd9Sstevel@tonic-gate * This routine is called when there is a system panic. 20327c478bd9Sstevel@tonic-gate */ 20337c478bd9Sstevel@tonic-gate /* ARGSUSED */ 20347c478bd9Sstevel@tonic-gate static boolean_t 20357c478bd9Sstevel@tonic-gate scsa2usb_panic_callb(void *arg, int code) 20367c478bd9Sstevel@tonic-gate { 20377c478bd9Sstevel@tonic-gate scsa2usb_cpr_t *cpr_infop; 20387c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 20397c478bd9Sstevel@tonic-gate uint_t lun; 20407c478bd9Sstevel@tonic-gate 20417c478bd9Sstevel@tonic-gate _NOTE(NO_COMPETING_THREADS_NOW); 20427c478bd9Sstevel@tonic-gate cpr_infop = (scsa2usb_cpr_t *)arg; 20437c478bd9Sstevel@tonic-gate scsa2usbp = (scsa2usb_state_t *)cpr_infop->statep; 20447c478bd9Sstevel@tonic-gate 20457c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 20467c478bd9Sstevel@tonic-gate "scsa2usb_panic_callb: code=%d", code); 20477c478bd9Sstevel@tonic-gate 20487c478bd9Sstevel@tonic-gate /* 20497c478bd9Sstevel@tonic-gate * If we return error here, "sd" prints lots of error 20507c478bd9Sstevel@tonic-gate * messages and could retry the same pkt over and over again. 20517c478bd9Sstevel@tonic-gate * The sync recovery isn't "smooth" in that case. By faking 20527c478bd9Sstevel@tonic-gate * a success return, instead, we force sync to complete. 20537c478bd9Sstevel@tonic-gate */ 20547c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_cur_pkt) { 20557c478bd9Sstevel@tonic-gate /* 20567c478bd9Sstevel@tonic-gate * Do not print the "no sync" warning here. it will then be 20577c478bd9Sstevel@tonic-gate * displayed before we actually start syncing. Also we don't 20587c478bd9Sstevel@tonic-gate * replace this code with a call to scsa2usb_pkt_completion(). 20597c478bd9Sstevel@tonic-gate * NOTE: mutexes are disabled during panic. 20607c478bd9Sstevel@tonic-gate */ 20617c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cur_pkt->pkt_reason = CMD_CMPLT; 20627c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 20637c478bd9Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usbp, scsa2usbp->scsa2usb_cur_pkt); 20647c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 20657c478bd9Sstevel@tonic-gate } 20667c478bd9Sstevel@tonic-gate 20677c478bd9Sstevel@tonic-gate /* get rid of waitQ */ 20687c478bd9Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 20697c478bd9Sstevel@tonic-gate scsa2usb_flush_waitQ(scsa2usbp, lun, CMD_CMPLT); 20707c478bd9Sstevel@tonic-gate } 20717c478bd9Sstevel@tonic-gate 2072055d7c80Scarlsonj #ifndef lint 20737c478bd9Sstevel@tonic-gate _NOTE(COMPETING_THREADS_NOW); 2074055d7c80Scarlsonj #endif 20757c478bd9Sstevel@tonic-gate 20767c478bd9Sstevel@tonic-gate return (B_TRUE); 20777c478bd9Sstevel@tonic-gate } 20787c478bd9Sstevel@tonic-gate 20797c478bd9Sstevel@tonic-gate /* 20807c478bd9Sstevel@tonic-gate * scsa2usb_cpr_suspend 20817c478bd9Sstevel@tonic-gate * determine if the device's state can be changed to SUSPENDED 20827c478bd9Sstevel@tonic-gate * close pipes if there is no activity 20837c478bd9Sstevel@tonic-gate */ 20847c478bd9Sstevel@tonic-gate /* ARGSUSED */ 20857c478bd9Sstevel@tonic-gate static int 20867c478bd9Sstevel@tonic-gate scsa2usb_cpr_suspend(dev_info_t *dip) 20877c478bd9Sstevel@tonic-gate { 20887c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 20897c478bd9Sstevel@tonic-gate int prev_state; 20907c478bd9Sstevel@tonic-gate int rval = USB_FAILURE; 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate scsa2usbp = ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 20937c478bd9Sstevel@tonic-gate 20947c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 20957c478bd9Sstevel@tonic-gate 20967c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 20977c478bd9Sstevel@tonic-gate "scsa2usb_cpr_suspend:"); 20987c478bd9Sstevel@tonic-gate 20997c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 21007c478bd9Sstevel@tonic-gate switch (scsa2usbp->scsa2usb_dev_state) { 21017c478bd9Sstevel@tonic-gate case USB_DEV_ONLINE: 21027c478bd9Sstevel@tonic-gate case USB_DEV_PWRED_DOWN: 21037c478bd9Sstevel@tonic-gate case USB_DEV_DISCONNECTED: 21047c478bd9Sstevel@tonic-gate prev_state = scsa2usbp->scsa2usb_dev_state; 21057c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_SUSPENDED; 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate /* 21087c478bd9Sstevel@tonic-gate * If the device is busy, we cannot suspend 21097c478bd9Sstevel@tonic-gate */ 21107c478bd9Sstevel@tonic-gate if (SCSA2USB_BUSY(scsa2usbp)) { 21117c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 21127c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 21137c478bd9Sstevel@tonic-gate "scsa2usb_cpr_suspend: I/O active"); 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate /* fall back to previous state */ 21167c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = prev_state; 21177c478bd9Sstevel@tonic-gate } else { 21187c478bd9Sstevel@tonic-gate rval = USB_SUCCESS; 21197c478bd9Sstevel@tonic-gate } 21207c478bd9Sstevel@tonic-gate 21217c478bd9Sstevel@tonic-gate break; 21227c478bd9Sstevel@tonic-gate case USB_DEV_SUSPENDED: 21237c478bd9Sstevel@tonic-gate default: 21247c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 21257c478bd9Sstevel@tonic-gate "scsa2usb_cpr_suspend: Illegal dev state: %d", 21267c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state); 21277c478bd9Sstevel@tonic-gate 21287c478bd9Sstevel@tonic-gate break; 21297c478bd9Sstevel@tonic-gate } 21307c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 21317c478bd9Sstevel@tonic-gate 21327c478bd9Sstevel@tonic-gate if ((rval == USB_SUCCESS) && scsa2usbp->scsa2usb_ugen_hdl) { 21337c478bd9Sstevel@tonic-gate rval = usb_ugen_detach(scsa2usbp->scsa2usb_ugen_hdl, 21347c478bd9Sstevel@tonic-gate DDI_SUSPEND); 21357c478bd9Sstevel@tonic-gate } 21367c478bd9Sstevel@tonic-gate 21377c478bd9Sstevel@tonic-gate return (rval); 21387c478bd9Sstevel@tonic-gate } 21397c478bd9Sstevel@tonic-gate 21407c478bd9Sstevel@tonic-gate 21417c478bd9Sstevel@tonic-gate /* 21427c478bd9Sstevel@tonic-gate * scsa2usb_cpr_resume: 21437c478bd9Sstevel@tonic-gate * restore device's state 21447c478bd9Sstevel@tonic-gate */ 21457c478bd9Sstevel@tonic-gate static void 21467c478bd9Sstevel@tonic-gate scsa2usb_cpr_resume(dev_info_t *dip) 21477c478bd9Sstevel@tonic-gate { 21487c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = 21497c478bd9Sstevel@tonic-gate ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 21527c478bd9Sstevel@tonic-gate 21537c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 2154112116d8Sfb209375 "scsa2usb_cpr_resume: dip = 0x%p", (void *)dip); 21557c478bd9Sstevel@tonic-gate 21567c478bd9Sstevel@tonic-gate scsa2usb_restore_device_state(dip, scsa2usbp); 21577c478bd9Sstevel@tonic-gate 21587c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_ugen_hdl) { 21597c478bd9Sstevel@tonic-gate (void) usb_ugen_attach(scsa2usbp->scsa2usb_ugen_hdl, 21607c478bd9Sstevel@tonic-gate DDI_RESUME); 21617c478bd9Sstevel@tonic-gate } 21627c478bd9Sstevel@tonic-gate } 21637c478bd9Sstevel@tonic-gate 21647c478bd9Sstevel@tonic-gate 21657c478bd9Sstevel@tonic-gate /* 21667c478bd9Sstevel@tonic-gate * scsa2usb_restore_device_state: 21677c478bd9Sstevel@tonic-gate * - raise the device's power 21687c478bd9Sstevel@tonic-gate * - reopen all the pipes 21697c478bd9Sstevel@tonic-gate */ 21707c478bd9Sstevel@tonic-gate static void 21717c478bd9Sstevel@tonic-gate scsa2usb_restore_device_state(dev_info_t *dip, scsa2usb_state_t *scsa2usbp) 21727c478bd9Sstevel@tonic-gate { 21737c478bd9Sstevel@tonic-gate uint_t prev_state; 21747c478bd9Sstevel@tonic-gate 21757c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 21767c478bd9Sstevel@tonic-gate "scsa2usb_restore_device_state:"); 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 21797c478bd9Sstevel@tonic-gate prev_state = scsa2usbp->scsa2usb_dev_state; 21807c478bd9Sstevel@tonic-gate 21817c478bd9Sstevel@tonic-gate scsa2usb_raise_power(scsa2usbp); 21827c478bd9Sstevel@tonic-gate 21837c478bd9Sstevel@tonic-gate ASSERT((prev_state == USB_DEV_DISCONNECTED) || 21847c478bd9Sstevel@tonic-gate (prev_state == USB_DEV_SUSPENDED)); 21857c478bd9Sstevel@tonic-gate 21867c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 21877c478bd9Sstevel@tonic-gate 21887c478bd9Sstevel@tonic-gate /* Check for the same device */ 21897c478bd9Sstevel@tonic-gate if (usb_check_same_device(dip, scsa2usbp->scsa2usb_log_handle, 21907c478bd9Sstevel@tonic-gate USB_LOG_L0, DPRINT_MASK_ALL, USB_CHK_ALL, NULL) != USB_SUCCESS) { 21917c478bd9Sstevel@tonic-gate 21927c478bd9Sstevel@tonic-gate /* change the flags to active */ 21937c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 21947c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_DISCONNECTED; 2195496d8c83Sfrits mutex_exit(&scsa2usbp->scsa2usb_mutex); 21967c478bd9Sstevel@tonic-gate 21977c478bd9Sstevel@tonic-gate scsa2usb_pm_idle_component(scsa2usbp); 21987c478bd9Sstevel@tonic-gate 21997c478bd9Sstevel@tonic-gate return; 22007c478bd9Sstevel@tonic-gate } 22017c478bd9Sstevel@tonic-gate 22027c478bd9Sstevel@tonic-gate /* 22037c478bd9Sstevel@tonic-gate * if the device had remote wakeup earlier, 22047c478bd9Sstevel@tonic-gate * enable it again 22057c478bd9Sstevel@tonic-gate */ 22067c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 22077c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_pm && 22087c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pm->scsa2usb_wakeup_enabled) { 22097c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 22107c478bd9Sstevel@tonic-gate (void) usb_handle_remote_wakeup(scsa2usbp->scsa2usb_dip, 22117c478bd9Sstevel@tonic-gate USB_REMOTE_WAKEUP_ENABLE); 22127c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 22137c478bd9Sstevel@tonic-gate } 22147c478bd9Sstevel@tonic-gate 22157c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_ONLINE; 22167c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_NONE; 2217496d8c83Sfrits mutex_exit(&scsa2usbp->scsa2usb_mutex); 22187c478bd9Sstevel@tonic-gate 22197c478bd9Sstevel@tonic-gate scsa2usb_pm_idle_component(scsa2usbp); 22207c478bd9Sstevel@tonic-gate } 22217c478bd9Sstevel@tonic-gate 22227c478bd9Sstevel@tonic-gate 22237c478bd9Sstevel@tonic-gate /* 22247c478bd9Sstevel@tonic-gate * SCSA entry points: 22257c478bd9Sstevel@tonic-gate * 22267c478bd9Sstevel@tonic-gate * scsa2usb_scsi_tgt_probe: 22277c478bd9Sstevel@tonic-gate * scsa functions are exported by means of the transport table 22287c478bd9Sstevel@tonic-gate * Issue a probe to get the inquiry data. 22297c478bd9Sstevel@tonic-gate */ 22307c478bd9Sstevel@tonic-gate /* ARGSUSED */ 22317c478bd9Sstevel@tonic-gate static int 22327c478bd9Sstevel@tonic-gate scsa2usb_scsi_tgt_probe(struct scsi_device *sd, int (*waitfunc)(void)) 22337c478bd9Sstevel@tonic-gate { 22347c478bd9Sstevel@tonic-gate scsi_hba_tran_t *tran; 22357c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 22367c478bd9Sstevel@tonic-gate dev_info_t *dip = ddi_get_parent(sd->sd_dev); 22377c478bd9Sstevel@tonic-gate int rval; 22387c478bd9Sstevel@tonic-gate 22397c478bd9Sstevel@tonic-gate ASSERT(dip); 22407c478bd9Sstevel@tonic-gate 22417c478bd9Sstevel@tonic-gate tran = ddi_get_driver_private(dip); 22427c478bd9Sstevel@tonic-gate ASSERT(tran != NULL); 22437c478bd9Sstevel@tonic-gate scsa2usbp = (scsa2usb_state_t *)tran->tran_hba_private; 22447c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp); 22457c478bd9Sstevel@tonic-gate 22467c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 22477c478bd9Sstevel@tonic-gate "scsa2usb_scsi_tgt_probe:"); 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate /* if device is disconnected (ie. pipes closed), fail immediately */ 22507c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 22517c478bd9Sstevel@tonic-gate if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 22527c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 22537c478bd9Sstevel@tonic-gate 22547c478bd9Sstevel@tonic-gate return (SCSIPROBE_FAILURE); 22557c478bd9Sstevel@tonic-gate } 22567c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 22577c478bd9Sstevel@tonic-gate 22587c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 2259112116d8Sfb209375 "scsa2usb_scsi_tgt_probe: scsi_device = 0x%p", (void *)sd); 22607c478bd9Sstevel@tonic-gate 22617c478bd9Sstevel@tonic-gate if ((rval = scsi_hba_probe(sd, waitfunc)) == SCSIPROBE_EXISTS) { 22627c478bd9Sstevel@tonic-gate /* 22630167b58cScg149915 * respect the removable bit on all USB storage devices 22647c478bd9Sstevel@tonic-gate * unless overridden by a scsa2usb.conf entry 22657c478bd9Sstevel@tonic-gate */ 22667c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 22670167b58cScg149915 if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_RMB)) { 22687c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unshared", scsi_inquiry)) 22697c478bd9Sstevel@tonic-gate sd->sd_inq->inq_rmb = 1; 22707c478bd9Sstevel@tonic-gate } 22717c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 22727c478bd9Sstevel@tonic-gate } 22737c478bd9Sstevel@tonic-gate 22747c478bd9Sstevel@tonic-gate return (rval); 22757c478bd9Sstevel@tonic-gate } 22767c478bd9Sstevel@tonic-gate 22777c478bd9Sstevel@tonic-gate 22787c478bd9Sstevel@tonic-gate /* 22797c478bd9Sstevel@tonic-gate * scsa2usb_scsi_tgt_init: 22807c478bd9Sstevel@tonic-gate * check whether we created this child ourselves 22817c478bd9Sstevel@tonic-gate */ 22827c478bd9Sstevel@tonic-gate /* ARGSUSED */ 22837c478bd9Sstevel@tonic-gate static int 22847c478bd9Sstevel@tonic-gate scsa2usb_scsi_tgt_init(dev_info_t *dip, dev_info_t *cdip, 22857c478bd9Sstevel@tonic-gate scsi_hba_tran_t *tran, struct scsi_device *sd) 22867c478bd9Sstevel@tonic-gate { 22877c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *) 22887c478bd9Sstevel@tonic-gate tran->tran_hba_private; 22897c478bd9Sstevel@tonic-gate int lun; 22907c478bd9Sstevel@tonic-gate int t_len = sizeof (lun); 22917c478bd9Sstevel@tonic-gate 22927c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF, 22937c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS|DDI_PROP_CANSLEEP, "lun", (caddr_t)&lun, 22947c478bd9Sstevel@tonic-gate &t_len) != DDI_PROP_SUCCESS) { 22957c478bd9Sstevel@tonic-gate 22967c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 22977c478bd9Sstevel@tonic-gate } 22987c478bd9Sstevel@tonic-gate 22997c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 23007c478bd9Sstevel@tonic-gate "scsa2usb_scsi_tgt_init: %s, lun%d", ddi_driver_name(cdip), lun); 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate /* is this a child we created? */ 23037c478bd9Sstevel@tonic-gate if (scsa2usb_is_usb(cdip) == 0) { 23047c478bd9Sstevel@tonic-gate 23057c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 23067c478bd9Sstevel@tonic-gate "scsa2usb_scsi_tgt_init: new child %s%d", 23077c478bd9Sstevel@tonic-gate ddi_driver_name(cdip), ddi_get_instance(cdip)); 23087c478bd9Sstevel@tonic-gate 23097c478bd9Sstevel@tonic-gate /* 23107c478bd9Sstevel@tonic-gate * add property "usb" so we can always verify that it 23117c478bd9Sstevel@tonic-gate * is our child 23127c478bd9Sstevel@tonic-gate */ 23137c478bd9Sstevel@tonic-gate if (ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "usb") != 23147c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 23157c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 23167c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 23177c478bd9Sstevel@tonic-gate "ndi_prop_create_boolean failed"); 23187c478bd9Sstevel@tonic-gate 23197c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 23207c478bd9Sstevel@tonic-gate } 23217c478bd9Sstevel@tonic-gate 23227c478bd9Sstevel@tonic-gate usba_set_usba_device(cdip, 23237c478bd9Sstevel@tonic-gate usba_get_usba_device(scsa2usbp->scsa2usb_dip)); 23247c478bd9Sstevel@tonic-gate 23257c478bd9Sstevel@tonic-gate /* 23267c478bd9Sstevel@tonic-gate * we don't store this dip in scsa2usb_lun_dip, there 23277c478bd9Sstevel@tonic-gate * might be multiple dips for the same device 23287c478bd9Sstevel@tonic-gate */ 23297c478bd9Sstevel@tonic-gate 23307c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 23317c478bd9Sstevel@tonic-gate } 23327c478bd9Sstevel@tonic-gate 23337c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 23347c478bd9Sstevel@tonic-gate if ((lun >= scsa2usbp->scsa2usb_n_luns) || 23357c478bd9Sstevel@tonic-gate (scsa2usbp->scsa2usb_lun_dip[lun] != NULL)) { 23367c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 23377c478bd9Sstevel@tonic-gate 23387c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 23397c478bd9Sstevel@tonic-gate } 23407c478bd9Sstevel@tonic-gate 23417c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_lun_dip[lun] = cdip; 23427c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 23437c478bd9Sstevel@tonic-gate 23447c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 23457c478bd9Sstevel@tonic-gate } 23467c478bd9Sstevel@tonic-gate 23477c478bd9Sstevel@tonic-gate 23487c478bd9Sstevel@tonic-gate /* 23497c478bd9Sstevel@tonic-gate * scsa2usb_scsi_tgt_free: 23507c478bd9Sstevel@tonic-gate */ 23517c478bd9Sstevel@tonic-gate /* ARGSUSED */ 23527c478bd9Sstevel@tonic-gate static void 23537c478bd9Sstevel@tonic-gate scsa2usb_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *cdip, 23547c478bd9Sstevel@tonic-gate scsi_hba_tran_t *tran, struct scsi_device *sd) 23557c478bd9Sstevel@tonic-gate { 23567c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *) 23577c478bd9Sstevel@tonic-gate tran->tran_hba_private; 23587c478bd9Sstevel@tonic-gate int lun; 23597c478bd9Sstevel@tonic-gate int t_len = sizeof (lun); 23607c478bd9Sstevel@tonic-gate 23617c478bd9Sstevel@tonic-gate /* is this our child? */ 23627c478bd9Sstevel@tonic-gate if (scsa2usb_is_usb(cdip) == 0) { 23637c478bd9Sstevel@tonic-gate 23647c478bd9Sstevel@tonic-gate return; 23657c478bd9Sstevel@tonic-gate } 23667c478bd9Sstevel@tonic-gate 23677c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF, 23687c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS|DDI_PROP_CANSLEEP, "lun", (caddr_t)&lun, 23697c478bd9Sstevel@tonic-gate &t_len) != DDI_PROP_SUCCESS) { 23707c478bd9Sstevel@tonic-gate 23717c478bd9Sstevel@tonic-gate return; 23727c478bd9Sstevel@tonic-gate } 23737c478bd9Sstevel@tonic-gate 23747c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 23757c478bd9Sstevel@tonic-gate "scsa2usb_scsi_tgt_free: %s lun%d", ddi_driver_name(cdip), lun); 23767c478bd9Sstevel@tonic-gate 23777c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 23787c478bd9Sstevel@tonic-gate if (lun < scsa2usbp->scsa2usb_n_luns) { 23797c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_lun_dip[lun] == cdip) { 23807c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_lun_dip[lun] = NULL; 23817c478bd9Sstevel@tonic-gate } 23827c478bd9Sstevel@tonic-gate } 23837c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 23847c478bd9Sstevel@tonic-gate } 23857c478bd9Sstevel@tonic-gate 23867c478bd9Sstevel@tonic-gate 23877c478bd9Sstevel@tonic-gate /* 23887c478bd9Sstevel@tonic-gate * bus enumeration entry points 23897c478bd9Sstevel@tonic-gate */ 23907c478bd9Sstevel@tonic-gate static int 23917c478bd9Sstevel@tonic-gate scsa2usb_scsi_bus_config(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op, 23927c478bd9Sstevel@tonic-gate void *arg, dev_info_t **child) 23937c478bd9Sstevel@tonic-gate { 23947c478bd9Sstevel@tonic-gate int circ; 23957c478bd9Sstevel@tonic-gate int rval; 23967c478bd9Sstevel@tonic-gate 23977c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = 23987c478bd9Sstevel@tonic-gate ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 23997c478bd9Sstevel@tonic-gate 24007c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 24017c478bd9Sstevel@tonic-gate 24027c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 24037c478bd9Sstevel@tonic-gate "scsa2usb_scsi_bus_config: op=%d", op); 24047c478bd9Sstevel@tonic-gate 24057c478bd9Sstevel@tonic-gate if (scsa2usb_scsi_bus_config_debug) { 24067c478bd9Sstevel@tonic-gate flag |= NDI_DEVI_DEBUG; 24077c478bd9Sstevel@tonic-gate } 24087c478bd9Sstevel@tonic-gate 24097c478bd9Sstevel@tonic-gate ndi_devi_enter(dip, &circ); 24107c478bd9Sstevel@tonic-gate /* create children if necessary */ 24117c478bd9Sstevel@tonic-gate if (DEVI(dip)->devi_child == NULL) { 24127c478bd9Sstevel@tonic-gate scsa2usb_create_luns(scsa2usbp); 24137c478bd9Sstevel@tonic-gate } 24147c478bd9Sstevel@tonic-gate 24157c478bd9Sstevel@tonic-gate rval = ndi_busop_bus_config(dip, flag, op, arg, child, 0); 24167c478bd9Sstevel@tonic-gate 24177c478bd9Sstevel@tonic-gate ndi_devi_exit(dip, circ); 24187c478bd9Sstevel@tonic-gate 24197c478bd9Sstevel@tonic-gate return (rval); 24207c478bd9Sstevel@tonic-gate } 24217c478bd9Sstevel@tonic-gate 24227c478bd9Sstevel@tonic-gate 24237c478bd9Sstevel@tonic-gate static int 24247c478bd9Sstevel@tonic-gate scsa2usb_scsi_bus_unconfig(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op, 24257c478bd9Sstevel@tonic-gate void *arg) 24267c478bd9Sstevel@tonic-gate { 24277c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = 24287c478bd9Sstevel@tonic-gate ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 24297c478bd9Sstevel@tonic-gate 24307c478bd9Sstevel@tonic-gate int circular_count; 24317c478bd9Sstevel@tonic-gate int rval = NDI_SUCCESS; 24327c478bd9Sstevel@tonic-gate uint_t save_flag = flag; 24337c478bd9Sstevel@tonic-gate 24347c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 24357c478bd9Sstevel@tonic-gate 24367c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 24377c478bd9Sstevel@tonic-gate "scsa2usb_scsi_bus_unconfig: op=%d", op); 24387c478bd9Sstevel@tonic-gate 24397c478bd9Sstevel@tonic-gate if (scsa2usb_scsi_bus_config_debug) { 24407c478bd9Sstevel@tonic-gate flag |= NDI_DEVI_DEBUG; 24417c478bd9Sstevel@tonic-gate } 24427c478bd9Sstevel@tonic-gate 24437c478bd9Sstevel@tonic-gate /* 24447c478bd9Sstevel@tonic-gate * first offline and if offlining successful, then 24457c478bd9Sstevel@tonic-gate * remove children 24467c478bd9Sstevel@tonic-gate */ 24477c478bd9Sstevel@tonic-gate if (op == BUS_UNCONFIG_ALL) { 24487c478bd9Sstevel@tonic-gate flag &= ~(NDI_DEVI_REMOVE | NDI_UNCONFIG); 24497c478bd9Sstevel@tonic-gate } 24507c478bd9Sstevel@tonic-gate 24517c478bd9Sstevel@tonic-gate ndi_devi_enter(dip, &circular_count); 24527c478bd9Sstevel@tonic-gate rval = ndi_busop_bus_unconfig(dip, flag, op, arg); 24537c478bd9Sstevel@tonic-gate 24547c478bd9Sstevel@tonic-gate /* 24557c478bd9Sstevel@tonic-gate * If unconfig is successful and not part of modunload 24567c478bd9Sstevel@tonic-gate * daemon, attempt to remove children. 24577c478bd9Sstevel@tonic-gate */ 24587c478bd9Sstevel@tonic-gate if (op == BUS_UNCONFIG_ALL && rval == NDI_SUCCESS && 24597c478bd9Sstevel@tonic-gate (flag & NDI_AUTODETACH) == 0) { 24607c478bd9Sstevel@tonic-gate flag |= NDI_DEVI_REMOVE; 24617c478bd9Sstevel@tonic-gate rval = ndi_busop_bus_unconfig(dip, flag, op, arg); 24627c478bd9Sstevel@tonic-gate } 24637c478bd9Sstevel@tonic-gate ndi_devi_exit(dip, circular_count); 24647c478bd9Sstevel@tonic-gate 24657c478bd9Sstevel@tonic-gate if ((rval != NDI_SUCCESS) && (op == BUS_UNCONFIG_ALL) && 24667c478bd9Sstevel@tonic-gate (save_flag & NDI_DEVI_REMOVE)) { 24677c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 24687c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_warning_given != B_TRUE) { 246967318e4aSlg150142 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 24707c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 24717c478bd9Sstevel@tonic-gate "Disconnected device was busy, " 24727c478bd9Sstevel@tonic-gate "please reconnect."); 24737c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_warning_given = B_TRUE; 24747c478bd9Sstevel@tonic-gate } 24757c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 24767c478bd9Sstevel@tonic-gate } 24777c478bd9Sstevel@tonic-gate 24787c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 24797c478bd9Sstevel@tonic-gate "scsa2usb_scsi_bus_unconfig: rval=%d", rval); 24807c478bd9Sstevel@tonic-gate 24817c478bd9Sstevel@tonic-gate return (rval); 24827c478bd9Sstevel@tonic-gate } 24837c478bd9Sstevel@tonic-gate 24847c478bd9Sstevel@tonic-gate 24857c478bd9Sstevel@tonic-gate /* 24867c478bd9Sstevel@tonic-gate * scsa2usb_scsi_init_pkt: 24877c478bd9Sstevel@tonic-gate * Set up the scsi_pkt for transport. Also initialize 24887c478bd9Sstevel@tonic-gate * scsa2usb_cmd struct for the transport. 24897c478bd9Sstevel@tonic-gate * NOTE: We do not do any DMA setup here as USBA framework 24907c478bd9Sstevel@tonic-gate * does that for us. 24917c478bd9Sstevel@tonic-gate */ 24927c478bd9Sstevel@tonic-gate static struct scsi_pkt * 24937c478bd9Sstevel@tonic-gate scsa2usb_scsi_init_pkt(struct scsi_address *ap, 24947c478bd9Sstevel@tonic-gate struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen, 24957c478bd9Sstevel@tonic-gate int tgtlen, int flags, int (*callback)(), caddr_t arg) 24967c478bd9Sstevel@tonic-gate { 24977c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd; 24987c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 24997c478bd9Sstevel@tonic-gate struct scsi_pkt *in_pkt = pkt; 25007c478bd9Sstevel@tonic-gate 25017c478bd9Sstevel@tonic-gate ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC); 25027c478bd9Sstevel@tonic-gate 25037c478bd9Sstevel@tonic-gate scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap); 25047c478bd9Sstevel@tonic-gate 25057c478bd9Sstevel@tonic-gate /* Print sync message */ 25067c478bd9Sstevel@tonic-gate if (ddi_in_panic()) { 25077c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 25087c478bd9Sstevel@tonic-gate SCSA2USB_PRINT_SYNC_MSG(scsa2usb_sync_message, scsa2usbp); 25097c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 25107c478bd9Sstevel@tonic-gate /* continue so caller will not hang or complain */ 25117c478bd9Sstevel@tonic-gate } 25127c478bd9Sstevel@tonic-gate 25137c478bd9Sstevel@tonic-gate /* allocate a pkt, if none already allocated */ 25147c478bd9Sstevel@tonic-gate if (pkt == NULL) { 25157c478bd9Sstevel@tonic-gate if (statuslen < sizeof (struct scsi_arq_status)) { 25167c478bd9Sstevel@tonic-gate statuslen = sizeof (struct scsi_arq_status); 25177c478bd9Sstevel@tonic-gate } 25187c478bd9Sstevel@tonic-gate 25197c478bd9Sstevel@tonic-gate pkt = scsi_hba_pkt_alloc(scsa2usbp->scsa2usb_dip, ap, cmdlen, 25207c478bd9Sstevel@tonic-gate statuslen, tgtlen, sizeof (scsa2usb_cmd_t), 25217c478bd9Sstevel@tonic-gate callback, arg); 25227c478bd9Sstevel@tonic-gate if (pkt == NULL) { 25237c478bd9Sstevel@tonic-gate 25247c478bd9Sstevel@tonic-gate return (NULL); 25257c478bd9Sstevel@tonic-gate } 25267c478bd9Sstevel@tonic-gate 25277c478bd9Sstevel@tonic-gate cmd = PKT2CMD(pkt); 25287c478bd9Sstevel@tonic-gate cmd->cmd_pkt = pkt; /* back link to pkt */ 25297c478bd9Sstevel@tonic-gate cmd->cmd_scblen = statuslen; 25307c478bd9Sstevel@tonic-gate cmd->cmd_cdblen = (uchar_t)cmdlen; 25317c478bd9Sstevel@tonic-gate 25327c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 25337c478bd9Sstevel@tonic-gate cmd->cmd_tag = scsa2usbp->scsa2usb_tag++; 25347c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 25357c478bd9Sstevel@tonic-gate 25367c478bd9Sstevel@tonic-gate cmd->cmd_bp = bp; 2537fae6130aSlh195018 /* 2538fae6130aSlh195018 * The buffer size of cmd->cmd_scb is constrained 2539fae6130aSlh195018 * to sizeof (struct scsi_arq_status), if the scblen 2540fae6130aSlh195018 * is bigger than that, we use pkt->pkt_scbp directly. 2541fae6130aSlh195018 */ 2542fae6130aSlh195018 if (cmd->cmd_scblen == sizeof (struct scsi_arq_status)) { 25437c478bd9Sstevel@tonic-gate pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb; 2544fae6130aSlh195018 } 25457c478bd9Sstevel@tonic-gate 25467c478bd9Sstevel@tonic-gate usba_init_list(&cmd->cmd_waitQ, (usb_opaque_t)cmd, 25477c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_data->dev_iblock_cookie); 25487c478bd9Sstevel@tonic-gate } else { 25497c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 25507c478bd9Sstevel@tonic-gate "scsa2usb: pkt != NULL"); 25517c478bd9Sstevel@tonic-gate 25527c478bd9Sstevel@tonic-gate /* nothing to do */ 25537c478bd9Sstevel@tonic-gate } 25547c478bd9Sstevel@tonic-gate 2555df4cb6e0Ssl147100 if (bp && (bp->b_bcount != 0)) { 25567c478bd9Sstevel@tonic-gate if ((bp_mapin_common(bp, (callback == SLEEP_FUNC) ? 25577c478bd9Sstevel@tonic-gate VM_SLEEP : VM_NOSLEEP)) == NULL) { 25587c478bd9Sstevel@tonic-gate if (pkt != in_pkt) { 25597c478bd9Sstevel@tonic-gate scsi_hba_pkt_free(ap, pkt); 25607c478bd9Sstevel@tonic-gate } 25617c478bd9Sstevel@tonic-gate 25627c478bd9Sstevel@tonic-gate return (NULL); 25637c478bd9Sstevel@tonic-gate } 25647c478bd9Sstevel@tonic-gate 25657c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 25667c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 25677c478bd9Sstevel@tonic-gate "scsa2usb_scsi_init_pkt: mapped in 0x%p, addr=0x%p", 2568112116d8Sfb209375 (void *)bp, (void *)bp->b_un.b_addr); 25697c478bd9Sstevel@tonic-gate } 25707c478bd9Sstevel@tonic-gate 25717c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 25727c478bd9Sstevel@tonic-gate "scsa2usb_scsi_init_pkt: ap = 0x%p pkt: 0x%p\n\t" 25737c478bd9Sstevel@tonic-gate "bp = 0x%p cmdlen = %x stlen = 0x%x tlen = 0x%x flags = 0x%x", 2574112116d8Sfb209375 (void *)ap, (void *)pkt, (void *)bp, cmdlen, statuslen, 2575112116d8Sfb209375 tgtlen, flags); 25767c478bd9Sstevel@tonic-gate 25777c478bd9Sstevel@tonic-gate return (pkt); 25787c478bd9Sstevel@tonic-gate } 25797c478bd9Sstevel@tonic-gate 25807c478bd9Sstevel@tonic-gate 25817c478bd9Sstevel@tonic-gate /* 25827c478bd9Sstevel@tonic-gate * scsa2usb_scsi_destroy_pkt: 25837c478bd9Sstevel@tonic-gate * We are done with the packet. Get rid of it. 25847c478bd9Sstevel@tonic-gate */ 25857c478bd9Sstevel@tonic-gate static void 25867c478bd9Sstevel@tonic-gate scsa2usb_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 25877c478bd9Sstevel@tonic-gate { 25887c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd = PKT2CMD(pkt); 25897c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ADDR2SCSA2USB(ap); 25907c478bd9Sstevel@tonic-gate 25917c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 2592112116d8Sfb209375 "scsa2usb_scsi_destroy_pkt: pkt=0x%p", (void *)pkt); 25937c478bd9Sstevel@tonic-gate 25947c478bd9Sstevel@tonic-gate usba_destroy_list(&cmd->cmd_waitQ); 25957c478bd9Sstevel@tonic-gate scsi_hba_pkt_free(ap, pkt); 25967c478bd9Sstevel@tonic-gate } 25977c478bd9Sstevel@tonic-gate 25987c478bd9Sstevel@tonic-gate 25997c478bd9Sstevel@tonic-gate /* 26007c478bd9Sstevel@tonic-gate * scsa2usb_scsi_start: 26017c478bd9Sstevel@tonic-gate * For each command being issued, build up the CDB 26027c478bd9Sstevel@tonic-gate * and call scsi_transport to issue the command. This 26037c478bd9Sstevel@tonic-gate * function is based on the assumption that USB allows 26047c478bd9Sstevel@tonic-gate * a subset of SCSI commands. Other SCSI commands we fail. 26057c478bd9Sstevel@tonic-gate */ 26067c478bd9Sstevel@tonic-gate static int 26077c478bd9Sstevel@tonic-gate scsa2usb_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 26087c478bd9Sstevel@tonic-gate { 26097c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd; 26107c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = ADDR2SCSA2USB(ap); 26117c478bd9Sstevel@tonic-gate uint_t lun = ap->a_lun; 26127c478bd9Sstevel@tonic-gate 26137c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 26147c478bd9Sstevel@tonic-gate 26157c478bd9Sstevel@tonic-gate cmd = PKT2CMD(pkt); 26167c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 26177c478bd9Sstevel@tonic-gate "scsa2usb_scsi_start:\n\t" 26187c478bd9Sstevel@tonic-gate "bp: 0x%p ap: 0x%p pkt: 0x%p flag: 0x%x time: 0x%x\n\tcdb0: 0x%x " 26197c478bd9Sstevel@tonic-gate "dev_state: 0x%x pkt_state: 0x%x flags: 0x%x pipe_state: 0x%x", 2620112116d8Sfb209375 (void *)cmd->cmd_bp, (void *)ap, (void *)pkt, pkt->pkt_flags, 2621112116d8Sfb209375 pkt->pkt_time, pkt->pkt_cdbp[0], scsa2usbp->scsa2usb_dev_state, 26227c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pkt_state, scsa2usbp->scsa2usb_flags, 26237c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pipe_state); 26247c478bd9Sstevel@tonic-gate 26257c478bd9Sstevel@tonic-gate if (pkt->pkt_time == 0) { 26267c478bd9Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 26277c478bd9Sstevel@tonic-gate "pkt submitted with 0 timeout which may cause indefinite " 26287c478bd9Sstevel@tonic-gate "hangs"); 26297c478bd9Sstevel@tonic-gate } 26307c478bd9Sstevel@tonic-gate 26317c478bd9Sstevel@tonic-gate /* 26327c478bd9Sstevel@tonic-gate * if we are in panic, we are in polled mode, so we can just 26337c478bd9Sstevel@tonic-gate * accept the request, drop it and return 26347c478bd9Sstevel@tonic-gate * if we fail this request, the rest of the file systems do not 26357c478bd9Sstevel@tonic-gate * get synced 26367c478bd9Sstevel@tonic-gate */ 26377c478bd9Sstevel@tonic-gate if (ddi_in_panic()) { 26387c478bd9Sstevel@tonic-gate extern int do_polled_io; 26397c478bd9Sstevel@tonic-gate 26407c478bd9Sstevel@tonic-gate ASSERT(do_polled_io); 26417c478bd9Sstevel@tonic-gate scsa2usb_prepare_pkt(scsa2usbp, pkt); 26427c478bd9Sstevel@tonic-gate SCSA2USB_PRINT_SYNC_MSG(scsa2usb_sync_message, scsa2usbp); 26437c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 26447c478bd9Sstevel@tonic-gate 26457c478bd9Sstevel@tonic-gate return (TRAN_ACCEPT); 26467c478bd9Sstevel@tonic-gate } 26477c478bd9Sstevel@tonic-gate 26487c478bd9Sstevel@tonic-gate /* we cannot do polling, this should not happen */ 26497c478bd9Sstevel@tonic-gate if (pkt->pkt_flags & FLAG_NOINTR) { 26507c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 26517c478bd9Sstevel@tonic-gate "NOINTR packet: opcode = 0%x", pkt->pkt_cdbp[0]); 26527c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 26537c478bd9Sstevel@tonic-gate 26547c478bd9Sstevel@tonic-gate return (TRAN_BADPKT); 26557c478bd9Sstevel@tonic-gate } 26567c478bd9Sstevel@tonic-gate 26577c478bd9Sstevel@tonic-gate /* prepare packet */ 26587c478bd9Sstevel@tonic-gate scsa2usb_prepare_pkt(scsa2usbp, pkt); 26597c478bd9Sstevel@tonic-gate 26607c478bd9Sstevel@tonic-gate /* just queue up the requests in the waitQ if below max */ 26617c478bd9Sstevel@tonic-gate if (usba_list_entry_count(&scsa2usbp->scsa2usb_waitQ[lun]) > 26627c478bd9Sstevel@tonic-gate SCSA2USB_MAX_REQ_PER_LUN) { 26637c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 26647c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 26657c478bd9Sstevel@tonic-gate "scsa2usb_scsi_start: limit (%d) exceeded", 26667c478bd9Sstevel@tonic-gate SCSA2USB_MAX_REQ_PER_LUN); 26677c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 26687c478bd9Sstevel@tonic-gate 26697c478bd9Sstevel@tonic-gate return (TRAN_BUSY); 26707c478bd9Sstevel@tonic-gate } 26717c478bd9Sstevel@tonic-gate 26727c478bd9Sstevel@tonic-gate usba_add_to_list(&scsa2usbp->scsa2usb_waitQ[lun], &cmd->cmd_waitQ); 26737c478bd9Sstevel@tonic-gate 2674496d8c83Sfrits USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 2675112116d8Sfb209375 "scsa2usb_work_thread_id=0x%p, count=%d, lun=%d", 2676112116d8Sfb209375 (void *)scsa2usbp->scsa2usb_work_thread_id, 2677496d8c83Sfrits usba_list_entry_count(&scsa2usbp->scsa2usb_waitQ[lun]), lun); 2678496d8c83Sfrits 26797c478bd9Sstevel@tonic-gate /* fire up a thread to start executing the protocol */ 26807c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_work_thread_id == 0) { 26817c478bd9Sstevel@tonic-gate if ((usb_async_req(scsa2usbp->scsa2usb_dip, 26827c478bd9Sstevel@tonic-gate scsa2usb_work_thread, 26837c478bd9Sstevel@tonic-gate (void *)scsa2usbp, USB_FLAGS_SLEEP)) != USB_SUCCESS) { 26847c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 26857c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 26867c478bd9Sstevel@tonic-gate "no work thread started"); 26877c478bd9Sstevel@tonic-gate 26887c478bd9Sstevel@tonic-gate if (usba_rm_from_list( 26897c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_waitQ[lun], 26907c478bd9Sstevel@tonic-gate &cmd->cmd_waitQ) == USB_SUCCESS) { 26917c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 26927c478bd9Sstevel@tonic-gate 26937c478bd9Sstevel@tonic-gate return (TRAN_BUSY); 26947c478bd9Sstevel@tonic-gate } else { 26957c478bd9Sstevel@tonic-gate 26967c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 26977c478bd9Sstevel@tonic-gate 26987c478bd9Sstevel@tonic-gate return (TRAN_ACCEPT); 26997c478bd9Sstevel@tonic-gate } 27007c478bd9Sstevel@tonic-gate } 27017c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_work_thread_id = (kthread_t *)1; 27027c478bd9Sstevel@tonic-gate } 2703496d8c83Sfrits 27047c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 27057c478bd9Sstevel@tonic-gate 27067c478bd9Sstevel@tonic-gate return (TRAN_ACCEPT); 27077c478bd9Sstevel@tonic-gate } 27087c478bd9Sstevel@tonic-gate 27097c478bd9Sstevel@tonic-gate 27107c478bd9Sstevel@tonic-gate /* 27117c478bd9Sstevel@tonic-gate * scsa2usb_scsi_abort: 27127c478bd9Sstevel@tonic-gate * Issue SCSI abort command. This function is a NOP. 27137c478bd9Sstevel@tonic-gate */ 27147c478bd9Sstevel@tonic-gate /* ARGSUSED */ 27157c478bd9Sstevel@tonic-gate static int 27167c478bd9Sstevel@tonic-gate scsa2usb_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 27177c478bd9Sstevel@tonic-gate { 27187c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap); 27197c478bd9Sstevel@tonic-gate 27207c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 2721112116d8Sfb209375 "scsa2usb_scsi_abort: pkt = %p", (void *)pkt); 27227c478bd9Sstevel@tonic-gate 27237c478bd9Sstevel@tonic-gate /* if device is disconnected (ie. pipes closed), fail immediately */ 27247c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 27257c478bd9Sstevel@tonic-gate if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 27267c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 27277c478bd9Sstevel@tonic-gate 27287c478bd9Sstevel@tonic-gate return (0); 27297c478bd9Sstevel@tonic-gate } 27307c478bd9Sstevel@tonic-gate 27317c478bd9Sstevel@tonic-gate /* flush waitQ if target and lun match */ 27327c478bd9Sstevel@tonic-gate if ((ap->a_target == pkt->pkt_address.a_target) && 27337c478bd9Sstevel@tonic-gate (ap->a_lun == pkt->pkt_address.a_lun)) { 27347c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 27357c478bd9Sstevel@tonic-gate scsa2usb_flush_waitQ(scsa2usbp, ap->a_lun, CMD_ABORTED); 27367c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 27377c478bd9Sstevel@tonic-gate } 27387c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 27397c478bd9Sstevel@tonic-gate 27407c478bd9Sstevel@tonic-gate return (0); 27417c478bd9Sstevel@tonic-gate } 27427c478bd9Sstevel@tonic-gate 27437c478bd9Sstevel@tonic-gate 27447c478bd9Sstevel@tonic-gate /* 27457c478bd9Sstevel@tonic-gate * scsa2usb_scsi_reset: 27467c478bd9Sstevel@tonic-gate * device reset may turn the device into a brick and bus reset 27477c478bd9Sstevel@tonic-gate * is not applicable. 27487c478bd9Sstevel@tonic-gate * just flush the waitQ 27497c478bd9Sstevel@tonic-gate * We return success, always. 27507c478bd9Sstevel@tonic-gate */ 27517c478bd9Sstevel@tonic-gate /* ARGSUSED */ 27527c478bd9Sstevel@tonic-gate static int 27537c478bd9Sstevel@tonic-gate scsa2usb_scsi_reset(struct scsi_address *ap, int level) 27547c478bd9Sstevel@tonic-gate { 27557c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap); 27567c478bd9Sstevel@tonic-gate 27577c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 2758112116d8Sfb209375 "scsa2usb_scsi_reset: ap = 0x%p, level = %d", (void *)ap, level); 27597c478bd9Sstevel@tonic-gate 27607c478bd9Sstevel@tonic-gate /* flush waitQ */ 27617c478bd9Sstevel@tonic-gate scsa2usb_flush_waitQ(scsa2usbp, ap->a_lun, CMD_RESET); 27627c478bd9Sstevel@tonic-gate 27637c478bd9Sstevel@tonic-gate return (1); 27647c478bd9Sstevel@tonic-gate } 27657c478bd9Sstevel@tonic-gate 27667c478bd9Sstevel@tonic-gate 27677c478bd9Sstevel@tonic-gate /* 27687c478bd9Sstevel@tonic-gate * scsa2usb_scsi_getcap: 27697c478bd9Sstevel@tonic-gate * Get SCSI capabilities. 27707c478bd9Sstevel@tonic-gate */ 27717c478bd9Sstevel@tonic-gate /* ARGSUSED */ 27727c478bd9Sstevel@tonic-gate static int 27737c478bd9Sstevel@tonic-gate scsa2usb_scsi_getcap(struct scsi_address *ap, char *cap, int whom) 27747c478bd9Sstevel@tonic-gate { 27757c478bd9Sstevel@tonic-gate int rval = -1; 27767c478bd9Sstevel@tonic-gate uint_t cidx; 27777c478bd9Sstevel@tonic-gate size_t dev_bsize_cap; 27787c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap); 27797c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp); 27807c478bd9Sstevel@tonic-gate 27817c478bd9Sstevel@tonic-gate if (cap == NULL) { 27827c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 27837c478bd9Sstevel@tonic-gate "scsa2usb_scsi_getcap: invalid arg, " 2784112116d8Sfb209375 "cap = 0x%p whom = %d", (void *)cap, whom); 27857c478bd9Sstevel@tonic-gate 27867c478bd9Sstevel@tonic-gate return (rval); 27877c478bd9Sstevel@tonic-gate } 27887c478bd9Sstevel@tonic-gate 27897c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 27907c478bd9Sstevel@tonic-gate "scsa2usb_scsi_getcap: cap = %s", cap); 27917c478bd9Sstevel@tonic-gate 27927c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 27937c478bd9Sstevel@tonic-gate 27947c478bd9Sstevel@tonic-gate /* if device is disconnected (ie. pipes closed), fail immediately */ 27957c478bd9Sstevel@tonic-gate if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 27967c478bd9Sstevel@tonic-gate 27977c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 27987c478bd9Sstevel@tonic-gate 27997c478bd9Sstevel@tonic-gate return (rval); 28007c478bd9Sstevel@tonic-gate } 28017c478bd9Sstevel@tonic-gate 28027c478bd9Sstevel@tonic-gate cidx = scsi_hba_lookup_capstr(cap); 28037c478bd9Sstevel@tonic-gate switch (cidx) { 28047c478bd9Sstevel@tonic-gate case SCSI_CAP_GEOMETRY: 2805e7cc2e17Sbc224572 /* Just check and fail immediately if zero, rarely happens */ 2806e7cc2e17Sbc224572 if (scsa2usbp->scsa2usb_secsz[ap->a_lun] == 0) { 2807e7cc2e17Sbc224572 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 2808e7cc2e17Sbc224572 scsa2usbp->scsa2usb_log_handle, 2809e7cc2e17Sbc224572 "scsa2usb_scsi_getcap failed:" 2810e7cc2e17Sbc224572 "scsa2usbp->scsa2usb_secsz[ap->a_lun] == 0"); 2811e7cc2e17Sbc224572 mutex_exit(&scsa2usbp->scsa2usb_mutex); 2812e7cc2e17Sbc224572 2813e7cc2e17Sbc224572 return (rval); 2814e7cc2e17Sbc224572 } 2815e7cc2e17Sbc224572 28167c478bd9Sstevel@tonic-gate dev_bsize_cap = scsa2usbp->scsa2usb_totalsec[ap->a_lun]; 28177c478bd9Sstevel@tonic-gate 28187c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_secsz[ap->a_lun] > DEV_BSIZE) { 28197c478bd9Sstevel@tonic-gate dev_bsize_cap *= 28207c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_secsz[ap->a_lun] / DEV_BSIZE; 28217c478bd9Sstevel@tonic-gate } else if (scsa2usbp->scsa2usb_secsz[ap->a_lun] < 28227c478bd9Sstevel@tonic-gate DEV_BSIZE) { 28237c478bd9Sstevel@tonic-gate dev_bsize_cap /= 28247c478bd9Sstevel@tonic-gate DEV_BSIZE / scsa2usbp->scsa2usb_secsz[ap->a_lun]; 28257c478bd9Sstevel@tonic-gate } 28267c478bd9Sstevel@tonic-gate 28277c478bd9Sstevel@tonic-gate if (dev_bsize_cap < 65536 * 2 * 18) { /* < ~1GB */ 28287c478bd9Sstevel@tonic-gate /* unlabeled floppy, 18k per cylinder */ 28297c478bd9Sstevel@tonic-gate rval = ((2 << 16) | 18); 28307c478bd9Sstevel@tonic-gate } else if (dev_bsize_cap < 65536 * 64 * 32) { /* < 64GB */ 28317c478bd9Sstevel@tonic-gate /* 1024k per cylinder */ 28327c478bd9Sstevel@tonic-gate rval = ((64 << 16) | 32); 28337c478bd9Sstevel@tonic-gate } else if (dev_bsize_cap < 65536 * 255 * 63) { /* < ~500GB */ 28347c478bd9Sstevel@tonic-gate /* ~8m per cylinder */ 28357c478bd9Sstevel@tonic-gate rval = ((255 << 16) | 63); 28367c478bd9Sstevel@tonic-gate } else { /* .. 8TB */ 28377c478bd9Sstevel@tonic-gate /* 64m per cylinder */ 28387c478bd9Sstevel@tonic-gate rval = ((512 << 16) | 256); 28397c478bd9Sstevel@tonic-gate } 28407c478bd9Sstevel@tonic-gate break; 28417c478bd9Sstevel@tonic-gate 28427c478bd9Sstevel@tonic-gate case SCSI_CAP_DMA_MAX: 28437c478bd9Sstevel@tonic-gate rval = scsa2usbp->scsa2usb_max_bulk_xfer_size; 28447c478bd9Sstevel@tonic-gate break; 28457c478bd9Sstevel@tonic-gate case SCSI_CAP_SCSI_VERSION: 28467c478bd9Sstevel@tonic-gate rval = SCSI_VERSION_2; 28477c478bd9Sstevel@tonic-gate break; 28487c478bd9Sstevel@tonic-gate case SCSI_CAP_INTERCONNECT_TYPE: 28497c478bd9Sstevel@tonic-gate rval = INTERCONNECT_USB; 28507c478bd9Sstevel@tonic-gate break; 28517c478bd9Sstevel@tonic-gate case SCSI_CAP_ARQ: 28527c478bd9Sstevel@tonic-gate /* FALLTHRU */ 28537c478bd9Sstevel@tonic-gate case SCSI_CAP_UNTAGGED_QING: 28547c478bd9Sstevel@tonic-gate rval = 1; 28557c478bd9Sstevel@tonic-gate break; 28567c478bd9Sstevel@tonic-gate default: 28577c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 28587c478bd9Sstevel@tonic-gate "scsa2usb_scsi_getcap: unsupported cap = %s", cap); 28597c478bd9Sstevel@tonic-gate break; 28607c478bd9Sstevel@tonic-gate } 28617c478bd9Sstevel@tonic-gate 28627c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 28637c478bd9Sstevel@tonic-gate "scsa2usb_scsi_getcap: cap = %s, returned = %d", cap, rval); 28647c478bd9Sstevel@tonic-gate 28657c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 28667c478bd9Sstevel@tonic-gate 28677c478bd9Sstevel@tonic-gate return (rval); 28687c478bd9Sstevel@tonic-gate } 28697c478bd9Sstevel@tonic-gate 28707c478bd9Sstevel@tonic-gate 28717c478bd9Sstevel@tonic-gate /* 28727c478bd9Sstevel@tonic-gate * scsa2usb_scsi_setcap: 28737c478bd9Sstevel@tonic-gate * Set SCSI capabilities. 28747c478bd9Sstevel@tonic-gate */ 28757c478bd9Sstevel@tonic-gate /* ARGSUSED */ 28767c478bd9Sstevel@tonic-gate static int 28777c478bd9Sstevel@tonic-gate scsa2usb_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) 28787c478bd9Sstevel@tonic-gate { 28797c478bd9Sstevel@tonic-gate int rval = -1; /* default is cap undefined */ 28807c478bd9Sstevel@tonic-gate uint_t cidx; 28817c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)ADDR2SCSA2USB(ap); 28827c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp); 28837c478bd9Sstevel@tonic-gate 28847c478bd9Sstevel@tonic-gate if (cap == NULL || whom == 0) { 28857c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 28867c478bd9Sstevel@tonic-gate "scsa2usb_scsi_setcap: invalid arg"); 28877c478bd9Sstevel@tonic-gate 28887c478bd9Sstevel@tonic-gate return (rval); 28897c478bd9Sstevel@tonic-gate } 28907c478bd9Sstevel@tonic-gate 28917c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 28927c478bd9Sstevel@tonic-gate /* if device is disconnected (ie. pipes closed), fail immediately */ 28937c478bd9Sstevel@tonic-gate if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 28947c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 28957c478bd9Sstevel@tonic-gate 28967c478bd9Sstevel@tonic-gate return (rval); 28977c478bd9Sstevel@tonic-gate } 28987c478bd9Sstevel@tonic-gate 28997c478bd9Sstevel@tonic-gate cidx = scsi_hba_lookup_capstr(cap); 29007c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 29017c478bd9Sstevel@tonic-gate "scsa2usb_scsi_setcap: ap = 0x%p value = 0x%x whom = 0x%x " 2902112116d8Sfb209375 "cidx = 0x%x", (void *)ap, value, whom, cidx); 29037c478bd9Sstevel@tonic-gate 29047c478bd9Sstevel@tonic-gate switch (cidx) { 29057c478bd9Sstevel@tonic-gate case SCSI_CAP_SECTOR_SIZE: 29067c478bd9Sstevel@tonic-gate if (value) { 29077c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_secsz[ap->a_lun] = value; 29087c478bd9Sstevel@tonic-gate } 29097c478bd9Sstevel@tonic-gate break; 29107c478bd9Sstevel@tonic-gate case SCSI_CAP_TOTAL_SECTORS: 29117c478bd9Sstevel@tonic-gate if (value) { 29127c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_totalsec[ap->a_lun] = value; 29137c478bd9Sstevel@tonic-gate } 29147c478bd9Sstevel@tonic-gate break; 29157c478bd9Sstevel@tonic-gate case SCSI_CAP_ARQ: 29167c478bd9Sstevel@tonic-gate rval = 1; 29177c478bd9Sstevel@tonic-gate break; 29187c478bd9Sstevel@tonic-gate case SCSI_CAP_DMA_MAX: 29197c478bd9Sstevel@tonic-gate case SCSI_CAP_SCSI_VERSION: 29207c478bd9Sstevel@tonic-gate case SCSI_CAP_INTERCONNECT_TYPE: 29217c478bd9Sstevel@tonic-gate case SCSI_CAP_UNTAGGED_QING: 29227c478bd9Sstevel@tonic-gate /* supported but not settable */ 29237c478bd9Sstevel@tonic-gate rval = 0; 29247c478bd9Sstevel@tonic-gate break; 29257c478bd9Sstevel@tonic-gate default: 29267c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 29277c478bd9Sstevel@tonic-gate "scsa2usb_scsi_setcap: unsupported cap = %s", cap); 29287c478bd9Sstevel@tonic-gate break; 29297c478bd9Sstevel@tonic-gate } 29307c478bd9Sstevel@tonic-gate 29317c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 29327c478bd9Sstevel@tonic-gate 29337c478bd9Sstevel@tonic-gate return (rval); 29347c478bd9Sstevel@tonic-gate } 29357c478bd9Sstevel@tonic-gate 29367c478bd9Sstevel@tonic-gate 29377c478bd9Sstevel@tonic-gate /* 29387c478bd9Sstevel@tonic-gate * scsa2usb - cmd and transport stuff 29397c478bd9Sstevel@tonic-gate */ 29407c478bd9Sstevel@tonic-gate /* 29417c478bd9Sstevel@tonic-gate * scsa2usb_prepare_pkt: 29427c478bd9Sstevel@tonic-gate * initialize some fields of the pkt and cmd 29437c478bd9Sstevel@tonic-gate * (the pkt may have been resubmitted/retried) 29447c478bd9Sstevel@tonic-gate */ 29457c478bd9Sstevel@tonic-gate static void 29467c478bd9Sstevel@tonic-gate scsa2usb_prepare_pkt(scsa2usb_state_t *scsa2usbp, struct scsi_pkt *pkt) 29477c478bd9Sstevel@tonic-gate { 29487c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd = PKT2CMD(pkt); 29497c478bd9Sstevel@tonic-gate 29507c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 29517c478bd9Sstevel@tonic-gate "scsa2usb_prepare_pkt: pkt=0x%p cdb: 0x%x (%s)", 2952112116d8Sfb209375 (void *)pkt, pkt->pkt_cdbp[0], 29537c478bd9Sstevel@tonic-gate scsi_cname(pkt->pkt_cdbp[0], scsa2usb_cmds)); 29547c478bd9Sstevel@tonic-gate 29557c478bd9Sstevel@tonic-gate pkt->pkt_reason = CMD_CMPLT; /* Set reason to pkt_complete */ 29567c478bd9Sstevel@tonic-gate pkt->pkt_state = 0; /* Reset next three fields */ 29577c478bd9Sstevel@tonic-gate pkt->pkt_statistics = 0; 29587c478bd9Sstevel@tonic-gate pkt->pkt_resid = 0; 29597c478bd9Sstevel@tonic-gate bzero(pkt->pkt_scbp, cmd->cmd_scblen); /* Set status to good */ 29607c478bd9Sstevel@tonic-gate 29617c478bd9Sstevel@tonic-gate if (cmd) { 29627c478bd9Sstevel@tonic-gate cmd->cmd_timeout = pkt->pkt_time; 29637c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = 0; /* Reset the fields */ 29647c478bd9Sstevel@tonic-gate cmd->cmd_total_xfercount = 0; 29657c478bd9Sstevel@tonic-gate cmd->cmd_lba = 0; 29667c478bd9Sstevel@tonic-gate cmd->cmd_done = 0; 29677c478bd9Sstevel@tonic-gate cmd->cmd_dir = 0; 29687c478bd9Sstevel@tonic-gate cmd->cmd_offset = 0; 29697c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = cmd->cmd_cdblen; 29707c478bd9Sstevel@tonic-gate } 29717c478bd9Sstevel@tonic-gate } 29727c478bd9Sstevel@tonic-gate 29737c478bd9Sstevel@tonic-gate 29747c478bd9Sstevel@tonic-gate /* 29757c478bd9Sstevel@tonic-gate * scsa2usb_force_invalid_request 29767c478bd9Sstevel@tonic-gate */ 29777c478bd9Sstevel@tonic-gate static void 29787c478bd9Sstevel@tonic-gate scsa2usb_force_invalid_request(scsa2usb_state_t *scsa2usbp, 29797c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd) 29807c478bd9Sstevel@tonic-gate { 29817c478bd9Sstevel@tonic-gate struct scsi_arq_status *arqp; 29827c478bd9Sstevel@tonic-gate 29837c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 2984112116d8Sfb209375 "scsa2usb_force_invalid_request: pkt = 0x%p", (void *)cmd->cmd_pkt); 29857c478bd9Sstevel@tonic-gate 29867c478bd9Sstevel@tonic-gate if (cmd->cmd_scblen >= sizeof (struct scsi_arq_status)) { 29877c478bd9Sstevel@tonic-gate arqp = (struct scsi_arq_status *)cmd->cmd_pkt->pkt_scbp; 29887c478bd9Sstevel@tonic-gate bzero(arqp, cmd->cmd_scblen); 29897c478bd9Sstevel@tonic-gate 29907c478bd9Sstevel@tonic-gate arqp->sts_status.sts_chk = 1; 29917c478bd9Sstevel@tonic-gate arqp->sts_rqpkt_reason = CMD_CMPLT; 29927c478bd9Sstevel@tonic-gate arqp->sts_rqpkt_state = STATE_XFERRED_DATA | 29937c478bd9Sstevel@tonic-gate STATE_GOT_BUS | STATE_GOT_STATUS; 29947c478bd9Sstevel@tonic-gate arqp->sts_sensedata.es_valid = 1; 29957c478bd9Sstevel@tonic-gate arqp->sts_sensedata.es_class = 7; 29967c478bd9Sstevel@tonic-gate arqp->sts_sensedata.es_key = KEY_ILLEGAL_REQUEST; 29977c478bd9Sstevel@tonic-gate 29987c478bd9Sstevel@tonic-gate cmd->cmd_pkt->pkt_state = STATE_ARQ_DONE | 29997c478bd9Sstevel@tonic-gate STATE_GOT_BUS | STATE_GOT_BUS | STATE_GOT_BUS | 30007c478bd9Sstevel@tonic-gate STATE_GOT_STATUS; 30017c478bd9Sstevel@tonic-gate #ifdef DEBUG 30027c478bd9Sstevel@tonic-gate { 30037c478bd9Sstevel@tonic-gate uchar_t *p = (uchar_t *)(&arqp->sts_sensedata); 30047c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 30057c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 30067c478bd9Sstevel@tonic-gate "cdb: %x rqsense: " 30077c478bd9Sstevel@tonic-gate "%x %x %x %x %x %x %x %x %x %x " 30087c478bd9Sstevel@tonic-gate "%x %x %x %x %x %x %x %x %x %x", 30097c478bd9Sstevel@tonic-gate cmd->cmd_pkt->pkt_cdbp[0], 30107c478bd9Sstevel@tonic-gate p[0], p[1], p[2], p[3], p[4], 30117c478bd9Sstevel@tonic-gate p[5], p[6], p[7], p[8], p[9], 30127c478bd9Sstevel@tonic-gate p[10], p[11], p[12], p[13], p[14], 30137c478bd9Sstevel@tonic-gate p[15], p[16], p[17], p[18], p[19]); 30147c478bd9Sstevel@tonic-gate } 30157c478bd9Sstevel@tonic-gate #endif 30167c478bd9Sstevel@tonic-gate 30177c478bd9Sstevel@tonic-gate } 30187c478bd9Sstevel@tonic-gate } 30197c478bd9Sstevel@tonic-gate 30207c478bd9Sstevel@tonic-gate 30217c478bd9Sstevel@tonic-gate /* 30227c478bd9Sstevel@tonic-gate * scsa2usb_cmd_transport: 30237c478bd9Sstevel@tonic-gate */ 30247c478bd9Sstevel@tonic-gate static int 30257c478bd9Sstevel@tonic-gate scsa2usb_cmd_transport(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) 30267c478bd9Sstevel@tonic-gate { 30277c478bd9Sstevel@tonic-gate int rval, transport; 30287c478bd9Sstevel@tonic-gate struct scsi_pkt *pkt; 30297c478bd9Sstevel@tonic-gate 30307c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 30317c478bd9Sstevel@tonic-gate "scsa2usb_cmd_transport: pkt: 0x%p, cur_pkt = 0x%p", 3032112116d8Sfb209375 (void *)cmd->cmd_pkt, (void *)scsa2usbp->scsa2usb_cur_pkt); 30337c478bd9Sstevel@tonic-gate 30347c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 30357c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_cur_pkt == NULL); 30367c478bd9Sstevel@tonic-gate 30377c478bd9Sstevel@tonic-gate pkt = scsa2usbp->scsa2usb_cur_pkt = cmd->cmd_pkt; 30387c478bd9Sstevel@tonic-gate 30397c478bd9Sstevel@tonic-gate /* check black-listed attrs first */ 30407c478bd9Sstevel@tonic-gate if (SCSA2USB_IS_BULK_ONLY(scsa2usbp)) { 30417c478bd9Sstevel@tonic-gate transport = scsa2usb_check_bulkonly_blacklist_attrs(scsa2usbp, 30427c478bd9Sstevel@tonic-gate cmd, pkt->pkt_cdbp[0]); 30437c478bd9Sstevel@tonic-gate } else if (SCSA2USB_IS_CB(scsa2usbp) || SCSA2USB_IS_CBI(scsa2usbp)) { 30447c478bd9Sstevel@tonic-gate transport = scsa2usb_check_ufi_blacklist_attrs(scsa2usbp, 30457c478bd9Sstevel@tonic-gate pkt->pkt_cdbp[0], cmd); 30467c478bd9Sstevel@tonic-gate } 30477c478bd9Sstevel@tonic-gate 3048b248f0fdSguoqing zhu - Sun Microsystems - Beijing China /* just accept the command or return error */ 30497c478bd9Sstevel@tonic-gate if (transport == SCSA2USB_JUST_ACCEPT) { 30507c478bd9Sstevel@tonic-gate SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 30517c478bd9Sstevel@tonic-gate 30527c478bd9Sstevel@tonic-gate return (TRAN_ACCEPT); 3053b248f0fdSguoqing zhu - Sun Microsystems - Beijing China } else if (transport == SCSA2USB_REJECT) { 3054b248f0fdSguoqing zhu - Sun Microsystems - Beijing China return (TRAN_FATAL_ERROR); 30557c478bd9Sstevel@tonic-gate } 30567c478bd9Sstevel@tonic-gate 30577c478bd9Sstevel@tonic-gate /* check command set next */ 30587c478bd9Sstevel@tonic-gate if (SCSA2USB_IS_SCSI_CMDSET(scsa2usbp) || 30597c478bd9Sstevel@tonic-gate SCSA2USB_IS_ATAPI_CMDSET(scsa2usbp)) { 30607c478bd9Sstevel@tonic-gate transport = 30617c478bd9Sstevel@tonic-gate scsa2usb_handle_scsi_cmd_sub_class(scsa2usbp, cmd, pkt); 30627c478bd9Sstevel@tonic-gate } else if (SCSA2USB_IS_UFI_CMDSET(scsa2usbp)) { 30637c478bd9Sstevel@tonic-gate transport = 30647c478bd9Sstevel@tonic-gate scsa2usb_handle_ufi_subclass_cmd(scsa2usbp, cmd, pkt); 30657c478bd9Sstevel@tonic-gate } else { 30667c478bd9Sstevel@tonic-gate transport = SCSA2USB_REJECT; 30677c478bd9Sstevel@tonic-gate } 30687c478bd9Sstevel@tonic-gate 3069910cba4fScg149915 switch (transport) { 3070910cba4fScg149915 case SCSA2USB_TRANSPORT: 30717c478bd9Sstevel@tonic-gate if (SCSA2USB_IS_BULK_ONLY(scsa2usbp)) { 30727c478bd9Sstevel@tonic-gate rval = scsa2usb_bulk_only_transport(scsa2usbp, cmd); 30737c478bd9Sstevel@tonic-gate } else if (SCSA2USB_IS_CB(scsa2usbp) || 30747c478bd9Sstevel@tonic-gate SCSA2USB_IS_CBI(scsa2usbp)) { 30757c478bd9Sstevel@tonic-gate rval = scsa2usb_cbi_transport(scsa2usbp, cmd); 30767c478bd9Sstevel@tonic-gate } else { 30777c478bd9Sstevel@tonic-gate rval = TRAN_FATAL_ERROR; 30787c478bd9Sstevel@tonic-gate } 3079910cba4fScg149915 break; 3080910cba4fScg149915 case SCSA2USB_JUST_ACCEPT: 3081910cba4fScg149915 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 3082910cba4fScg149915 rval = TRAN_ACCEPT; 3083910cba4fScg149915 break; 3084910cba4fScg149915 default: 30857c478bd9Sstevel@tonic-gate rval = TRAN_FATAL_ERROR; 30867c478bd9Sstevel@tonic-gate } 30877c478bd9Sstevel@tonic-gate 30887c478bd9Sstevel@tonic-gate return (rval); 30897c478bd9Sstevel@tonic-gate } 30907c478bd9Sstevel@tonic-gate 30917c478bd9Sstevel@tonic-gate 30927c478bd9Sstevel@tonic-gate /* 30937c478bd9Sstevel@tonic-gate * scsa2usb_check_bulkonly_blacklist_attrs: 30947c478bd9Sstevel@tonic-gate * validate "scsa2usb_blacklist_attrs" (see scsa2usb.h) 30957c478bd9Sstevel@tonic-gate * if blacklisted attrs match accept the request 30967c478bd9Sstevel@tonic-gate * attributes checked are:- 30977c478bd9Sstevel@tonic-gate * SCSA2USB_ATTRS_START_STOP 30987c478bd9Sstevel@tonic-gate */ 30997c478bd9Sstevel@tonic-gate int 31007c478bd9Sstevel@tonic-gate scsa2usb_check_bulkonly_blacklist_attrs(scsa2usb_state_t *scsa2usbp, 31017c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd, uchar_t opcode) 31027c478bd9Sstevel@tonic-gate { 31034610e4a0Sfrits struct scsi_inquiry *inq = 31044610e4a0Sfrits &scsa2usbp->scsa2usb_lun_inquiry[cmd->cmd_pkt->pkt_address.a_lun]; 31054610e4a0Sfrits 31067c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 31077c478bd9Sstevel@tonic-gate "scsa2usb_check_bulkonly_blacklist_attrs: opcode = %s", 31087c478bd9Sstevel@tonic-gate scsi_cname(opcode, scsa2usb_cmds)); 31097c478bd9Sstevel@tonic-gate 31107c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 31117c478bd9Sstevel@tonic-gate 31127c478bd9Sstevel@tonic-gate /* 31137c478bd9Sstevel@tonic-gate * decode and convert the packet 31147c478bd9Sstevel@tonic-gate * for most cmds, we can bcopy the cdb 31157c478bd9Sstevel@tonic-gate */ 31167c478bd9Sstevel@tonic-gate switch (opcode) { 31177c478bd9Sstevel@tonic-gate case SCMD_DOORLOCK: 31187c478bd9Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_DOORLOCK)) { 31197c478bd9Sstevel@tonic-gate 31207c478bd9Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 31217c478bd9Sstevel@tonic-gate 31224610e4a0Sfrits /* 31234610e4a0Sfrits * only lock the door for CD and DVD drives 31244610e4a0Sfrits */ 31254610e4a0Sfrits } else if ((inq->inq_dtype == DTYPE_RODIRECT) || 31264610e4a0Sfrits (inq->inq_dtype == DTYPE_OPTICAL)) { 31274610e4a0Sfrits 31284610e4a0Sfrits if (inq->inq_rmb) { 31297c478bd9Sstevel@tonic-gate 31307c478bd9Sstevel@tonic-gate break; 31317c478bd9Sstevel@tonic-gate } 31324610e4a0Sfrits } 31337c478bd9Sstevel@tonic-gate 31347c478bd9Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 31357c478bd9Sstevel@tonic-gate 31369038fe48SSheshadri Vasudevan case SCMD_START_STOP: /* SCMD_LOAD for sequential devices */ 31377c478bd9Sstevel@tonic-gate /* 31387c478bd9Sstevel@tonic-gate * these devices don't have mechanics that spin the 31397c478bd9Sstevel@tonic-gate * media up and down. So, it doesn't make much sense 31407c478bd9Sstevel@tonic-gate * to issue this cmd. 31417c478bd9Sstevel@tonic-gate * 31427c478bd9Sstevel@tonic-gate * Furthermore, Hagiwara devices do not handle these 31437c478bd9Sstevel@tonic-gate * cmds well. just accept this command as success. 31447c478bd9Sstevel@tonic-gate */ 31457c478bd9Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_START_STOP)) { 31467c478bd9Sstevel@tonic-gate 31477c478bd9Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 31487c478bd9Sstevel@tonic-gate 31499038fe48SSheshadri Vasudevan } else if (inq->inq_dtype == DTYPE_SEQUENTIAL) { 31509038fe48SSheshadri Vasudevan /* 31519038fe48SSheshadri Vasudevan * In case of USB tape device, we need to send the 31529038fe48SSheshadri Vasudevan * command to the device to unload the media. 31539038fe48SSheshadri Vasudevan */ 31549038fe48SSheshadri Vasudevan break; 31559038fe48SSheshadri Vasudevan 31567c478bd9Sstevel@tonic-gate } else if (cmd->cmd_pkt->pkt_cdbp[4] & LOEJECT) { 31577c478bd9Sstevel@tonic-gate /* 31587c478bd9Sstevel@tonic-gate * if the device is really a removable then 31597c478bd9Sstevel@tonic-gate * pass it on to the device, else just accept 31607c478bd9Sstevel@tonic-gate */ 31614610e4a0Sfrits if (inq->inq_rmb) { 31627c478bd9Sstevel@tonic-gate 31637c478bd9Sstevel@tonic-gate break; 31647c478bd9Sstevel@tonic-gate } 31657c478bd9Sstevel@tonic-gate 31667c478bd9Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 31677c478bd9Sstevel@tonic-gate 31687c478bd9Sstevel@tonic-gate } else if (!scsa2usbp->scsa2usb_rcvd_not_ready) { 31697c478bd9Sstevel@tonic-gate /* 31707c478bd9Sstevel@tonic-gate * if we have not received a NOT READY condition, 31717c478bd9Sstevel@tonic-gate * just accept since some device choke on this too. 31727c478bd9Sstevel@tonic-gate * we do have to let EJECT get through though 31737c478bd9Sstevel@tonic-gate */ 31747c478bd9Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 31757c478bd9Sstevel@tonic-gate } 31767c478bd9Sstevel@tonic-gate 31777c478bd9Sstevel@tonic-gate break; 31787c478bd9Sstevel@tonic-gate case SCMD_INQUIRY: 31797c478bd9Sstevel@tonic-gate /* 31807c478bd9Sstevel@tonic-gate * Some devices do not handle the inquiry cmd well 31817c478bd9Sstevel@tonic-gate * so build an inquiry and accept this command as 31827c478bd9Sstevel@tonic-gate * success. 31837c478bd9Sstevel@tonic-gate */ 31847c478bd9Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_INQUIRY)) { 31857c478bd9Sstevel@tonic-gate uchar_t evpd = 0x01; 31863fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic unsigned int bufsize; 31873fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic int count; 31887c478bd9Sstevel@tonic-gate 3189b248f0fdSguoqing zhu - Sun Microsystems - Beijing China if (cmd->cmd_pkt->pkt_cdbp[1] & evpd) 31907c478bd9Sstevel@tonic-gate return (SCSA2USB_REJECT); 31913fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic 31923fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic scsa2usb_fake_inquiry(scsa2usbp, inq); 31933fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic 31943fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic /* Copy no more than requested */ 31953fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic count = MIN(cmd->cmd_bp->b_bcount, 31963fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic sizeof (struct scsi_inquiry)); 31973fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic bufsize = cmd->cmd_pkt->pkt_cdbp[4]; 31983fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic count = MIN(count, bufsize); 31993fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic bcopy(inq, cmd->cmd_bp->b_un.b_addr, count); 32003fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic 32013fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic cmd->cmd_pkt->pkt_resid = bufsize - count; 32027c478bd9Sstevel@tonic-gate cmd->cmd_pkt->pkt_state |= STATE_XFERRED_DATA; 32037c478bd9Sstevel@tonic-gate 32047c478bd9Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 32058f588c83Sguoqing zhu - Sun Microsystems - Beijing China } else if (!(scsa2usbp->scsa2usb_attrs & 32068f588c83Sguoqing zhu - Sun Microsystems - Beijing China SCSA2USB_ATTRS_INQUIRY_EVPD)) { 32078f588c83Sguoqing zhu - Sun Microsystems - Beijing China /* 32088f588c83Sguoqing zhu - Sun Microsystems - Beijing China * Some devices do not handle the inquiry cmd with 32098f588c83Sguoqing zhu - Sun Microsystems - Beijing China * evpd bit set well, e.g. some devices return the 32108f588c83Sguoqing zhu - Sun Microsystems - Beijing China * same page 0x83 data which will cause the generated 32118f588c83Sguoqing zhu - Sun Microsystems - Beijing China * devid by sd is not unique, thus return CHECK 32128f588c83Sguoqing zhu - Sun Microsystems - Beijing China * CONDITION directly to sd. 32138f588c83Sguoqing zhu - Sun Microsystems - Beijing China */ 32148f588c83Sguoqing zhu - Sun Microsystems - Beijing China uchar_t evpd = 0x01; 32158f588c83Sguoqing zhu - Sun Microsystems - Beijing China 32168f588c83Sguoqing zhu - Sun Microsystems - Beijing China if (!(cmd->cmd_pkt->pkt_cdbp[1] & evpd)) 32177c478bd9Sstevel@tonic-gate break; 32187c478bd9Sstevel@tonic-gate 32198f588c83Sguoqing zhu - Sun Microsystems - Beijing China if (cmd->cmd_bp) { 32208f588c83Sguoqing zhu - Sun Microsystems - Beijing China cmd->cmd_pkt->pkt_resid = cmd->cmd_bp-> 32218f588c83Sguoqing zhu - Sun Microsystems - Beijing China b_bcount; 32228f588c83Sguoqing zhu - Sun Microsystems - Beijing China } 32238f588c83Sguoqing zhu - Sun Microsystems - Beijing China scsa2usb_force_invalid_request(scsa2usbp, cmd); 32248f588c83Sguoqing zhu - Sun Microsystems - Beijing China 32258f588c83Sguoqing zhu - Sun Microsystems - Beijing China return (SCSA2USB_JUST_ACCEPT); 32268f588c83Sguoqing zhu - Sun Microsystems - Beijing China } 32278f588c83Sguoqing zhu - Sun Microsystems - Beijing China break; 32287c478bd9Sstevel@tonic-gate /* 32294610e4a0Sfrits * Fake accepting the following Opcodes 32304610e4a0Sfrits * (as most drives don't support these) 32317c478bd9Sstevel@tonic-gate * These are needed by format command. 32327c478bd9Sstevel@tonic-gate */ 32337c478bd9Sstevel@tonic-gate case SCMD_RESERVE: 32347c478bd9Sstevel@tonic-gate case SCMD_RELEASE: 32357c478bd9Sstevel@tonic-gate case SCMD_PERSISTENT_RESERVE_IN: 32367c478bd9Sstevel@tonic-gate case SCMD_PERSISTENT_RESERVE_OUT: 32377c478bd9Sstevel@tonic-gate 32387c478bd9Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 32397c478bd9Sstevel@tonic-gate 32407c478bd9Sstevel@tonic-gate case SCMD_MODE_SENSE: 32417c478bd9Sstevel@tonic-gate case SCMD_MODE_SELECT: 32427c478bd9Sstevel@tonic-gate case SCMD_MODE_SENSE_G1: 32437c478bd9Sstevel@tonic-gate case SCMD_MODE_SELECT_G1: 32447c478bd9Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_MODE_SENSE)) { 32457c478bd9Sstevel@tonic-gate if (cmd->cmd_bp) { 32467c478bd9Sstevel@tonic-gate cmd->cmd_pkt->pkt_resid = cmd->cmd_bp-> 32477c478bd9Sstevel@tonic-gate b_bcount; 32487c478bd9Sstevel@tonic-gate } 32497c478bd9Sstevel@tonic-gate scsa2usb_force_invalid_request(scsa2usbp, cmd); 32507c478bd9Sstevel@tonic-gate 32517c478bd9Sstevel@tonic-gate return (SCSA2USB_JUST_ACCEPT); 32527c478bd9Sstevel@tonic-gate } 32537c478bd9Sstevel@tonic-gate 32547c478bd9Sstevel@tonic-gate break; 32557c478bd9Sstevel@tonic-gate default: 32567c478bd9Sstevel@tonic-gate 32577c478bd9Sstevel@tonic-gate break; 32587c478bd9Sstevel@tonic-gate } 32597c478bd9Sstevel@tonic-gate 32607c478bd9Sstevel@tonic-gate return (SCSA2USB_TRANSPORT); 32617c478bd9Sstevel@tonic-gate } 32627c478bd9Sstevel@tonic-gate 32637c478bd9Sstevel@tonic-gate 32647c478bd9Sstevel@tonic-gate /* 32657c478bd9Sstevel@tonic-gate * scsa2usb_handle_scsi_cmd_sub_class: 32667c478bd9Sstevel@tonic-gate * prepare a scsi cmd 32677c478bd9Sstevel@tonic-gate * returns SCSA2USB_TRANSPORT, SCSA2USB_REJECT, SCSA2USB_JUST_ACCEPT 32687c478bd9Sstevel@tonic-gate */ 32697c478bd9Sstevel@tonic-gate int 32707c478bd9Sstevel@tonic-gate scsa2usb_handle_scsi_cmd_sub_class(scsa2usb_state_t *scsa2usbp, 32717c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd, struct scsi_pkt *pkt) 32727c478bd9Sstevel@tonic-gate { 32738f588c83Sguoqing zhu - Sun Microsystems - Beijing China uchar_t evpd = 0x01; 32747c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 32757c478bd9Sstevel@tonic-gate "scsa2usb_handle_scsi_cmd_sub_class: cmd = 0x%p pkt = 0x%p", 3276112116d8Sfb209375 (void *)cmd, (void *)pkt); 32777c478bd9Sstevel@tonic-gate 32787c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 32797c478bd9Sstevel@tonic-gate 32807c478bd9Sstevel@tonic-gate bzero(&cmd->cmd_cdb, SCSI_CDB_SIZE); 32817c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_OPCODE] = pkt->pkt_cdbp[0]; /* Set the opcode */ 32827c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LUN] = pkt->pkt_cdbp[1]; 32837c478bd9Sstevel@tonic-gate 32847c478bd9Sstevel@tonic-gate /* 32857c478bd9Sstevel@tonic-gate * decode and convert the packet 32867c478bd9Sstevel@tonic-gate * for most cmds, we can bcopy the cdb 32877c478bd9Sstevel@tonic-gate */ 32887c478bd9Sstevel@tonic-gate switch (pkt->pkt_cdbp[0]) { 32897c478bd9Sstevel@tonic-gate case SCMD_FORMAT: 32907c478bd9Sstevel@tonic-gate /* 32917c478bd9Sstevel@tonic-gate * SCMD_FORMAT used to limit cmd->cmd_xfercount 32927c478bd9Sstevel@tonic-gate * to 4 bytes, but this hangs 32937c478bd9Sstevel@tonic-gate * formatting dvd media using cdrecord (that is, 32947c478bd9Sstevel@tonic-gate * a SCSI FORMAT UNIT command with a parameter list > 4 bytes) 32957c478bd9Sstevel@tonic-gate * (bit 4 in cdb1 is the Fmtdata bit) 32967c478bd9Sstevel@tonic-gate */ 32977c478bd9Sstevel@tonic-gate if ((pkt->pkt_cdbp[1] & 0x10) && cmd->cmd_bp) { 32987c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = cmd->cmd_bp->b_bcount; 32997c478bd9Sstevel@tonic-gate } else { 33007c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = 4; 33017c478bd9Sstevel@tonic-gate } 33027c478bd9Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_OUT; 33037c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 33047c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 33057c478bd9Sstevel@tonic-gate break; 33067c478bd9Sstevel@tonic-gate 33077c478bd9Sstevel@tonic-gate case SCMD_INQUIRY: 33087c478bd9Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_IN; 33097c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 33107c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_0] = pkt->pkt_cdbp[2]; 33118f588c83Sguoqing zhu - Sun Microsystems - Beijing China 33128f588c83Sguoqing zhu - Sun Microsystems - Beijing China /* 33138f588c83Sguoqing zhu - Sun Microsystems - Beijing China * If vpd pages data is limited to maximum SCSA2USB_MAX_INQ_LEN, 33148f588c83Sguoqing zhu - Sun Microsystems - Beijing China * the page data may be truncated, which may cause some issues 33158f588c83Sguoqing zhu - Sun Microsystems - Beijing China * such as making the unique page 0x83 or 0x80 data from 33168f588c83Sguoqing zhu - Sun Microsystems - Beijing China * different devices become the same. So don't limit return 33178f588c83Sguoqing zhu - Sun Microsystems - Beijing China * length for vpd page inquiry cmd. 33188f588c83Sguoqing zhu - Sun Microsystems - Beijing China * Another, in order to maintain compatibility, the original 33198f588c83Sguoqing zhu - Sun Microsystems - Beijing China * length limitation for standard inquiry retains here. It 33208f588c83Sguoqing zhu - Sun Microsystems - Beijing China * can be removed in future if it is verified that enough 33218f588c83Sguoqing zhu - Sun Microsystems - Beijing China * devices can work well. 33228f588c83Sguoqing zhu - Sun Microsystems - Beijing China */ 33238f588c83Sguoqing zhu - Sun Microsystems - Beijing China if (pkt->pkt_cdbp[1] & evpd) { 33248f588c83Sguoqing zhu - Sun Microsystems - Beijing China cmd->cmd_cdb[SCSA2USB_LBA_2] = cmd->cmd_xfercount = 33258f588c83Sguoqing zhu - Sun Microsystems - Beijing China (cmd->cmd_bp ? cmd->cmd_bp->b_bcount : 0); 33268f588c83Sguoqing zhu - Sun Microsystems - Beijing China } else { 33277c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = cmd->cmd_xfercount = 33287c478bd9Sstevel@tonic-gate min(SCSA2USB_MAX_INQ_LEN, 33297c478bd9Sstevel@tonic-gate cmd->cmd_bp ? cmd->cmd_bp->b_bcount : 0); 33308f588c83Sguoqing zhu - Sun Microsystems - Beijing China } 33317c478bd9Sstevel@tonic-gate break; 33327c478bd9Sstevel@tonic-gate 33337c478bd9Sstevel@tonic-gate case SCMD_READ_CAPACITY: 33347c478bd9Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_IN; 33357c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 33367c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = sizeof (scsa2usb_read_cap_t); 33377c478bd9Sstevel@tonic-gate break; 33387c478bd9Sstevel@tonic-gate 33397c478bd9Sstevel@tonic-gate /* 33407c478bd9Sstevel@tonic-gate * SCMD_READ/SCMD_WRITE are converted to G1 cmds 33417c478bd9Sstevel@tonic-gate * (as ATAPI devices don't recognize G0 commands) 33427c478bd9Sstevel@tonic-gate * 33437c478bd9Sstevel@tonic-gate * SCMD_READ_LONG/SCMD_WRITE_LONG are handled in 33447c478bd9Sstevel@tonic-gate * scsa2usb_rw_transport() along with other commands. 33457c478bd9Sstevel@tonic-gate * 33467c478bd9Sstevel@tonic-gate * USB Host Controllers cannot handle large (read/write) 33477c478bd9Sstevel@tonic-gate * xfers. We split the large request to chunks of 33487c478bd9Sstevel@tonic-gate * smaller ones to meet the HCD limitations. 33497c478bd9Sstevel@tonic-gate */ 33507c478bd9Sstevel@tonic-gate case SCMD_READ: 33517c478bd9Sstevel@tonic-gate case SCMD_WRITE: 33527c478bd9Sstevel@tonic-gate case SCMD_READ_G1: 33537c478bd9Sstevel@tonic-gate case SCMD_WRITE_G1: 33547c478bd9Sstevel@tonic-gate case SCMD_READ_G5: 33557c478bd9Sstevel@tonic-gate case SCMD_WRITE_G5: 33567c478bd9Sstevel@tonic-gate case SCMD_READ_LONG: 33577c478bd9Sstevel@tonic-gate case SCMD_WRITE_LONG: 33587c478bd9Sstevel@tonic-gate case SCMD_READ_CD: 33597c478bd9Sstevel@tonic-gate switch (scsa2usbp-> 33607c478bd9Sstevel@tonic-gate scsa2usb_lun_inquiry[pkt->pkt_address.a_lun]. 33617c478bd9Sstevel@tonic-gate inq_dtype & DTYPE_MASK) { 33627c478bd9Sstevel@tonic-gate case DTYPE_DIRECT: 33637c478bd9Sstevel@tonic-gate case DTYPE_RODIRECT: 33647c478bd9Sstevel@tonic-gate case DTYPE_OPTICAL: 33657c478bd9Sstevel@tonic-gate return (scsa2usb_rw_transport( 33667c478bd9Sstevel@tonic-gate scsa2usbp, pkt)); 33677c478bd9Sstevel@tonic-gate default: 33687c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 33697c478bd9Sstevel@tonic-gate if (cmd->cmd_bp) { 33707c478bd9Sstevel@tonic-gate cmd->cmd_dir = 33717c478bd9Sstevel@tonic-gate (cmd->cmd_bp->b_flags & B_READ) ? 33727c478bd9Sstevel@tonic-gate CBW_DIR_IN : CBW_DIR_OUT; 33737c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = 33747c478bd9Sstevel@tonic-gate cmd->cmd_bp->b_bcount; 33757c478bd9Sstevel@tonic-gate } 33767c478bd9Sstevel@tonic-gate break; 33777c478bd9Sstevel@tonic-gate } 33787c478bd9Sstevel@tonic-gate break; 33797c478bd9Sstevel@tonic-gate 33807c478bd9Sstevel@tonic-gate case SCMD_REQUEST_SENSE: 33817c478bd9Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_IN; 33827c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = pkt->pkt_cdbp[4]; 33837c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = pkt->pkt_cdbp[4]; 33847c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 33857c478bd9Sstevel@tonic-gate break; 33867c478bd9Sstevel@tonic-gate 33877c478bd9Sstevel@tonic-gate case SCMD_DOORLOCK: 33887c478bd9Sstevel@tonic-gate case SCMD_START_STOP: 33897c478bd9Sstevel@tonic-gate case SCMD_TEST_UNIT_READY: 33907c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 33917c478bd9Sstevel@tonic-gate break; 33927c478bd9Sstevel@tonic-gate 33937c478bd9Sstevel@tonic-gate /* 33947c478bd9Sstevel@tonic-gate * Needed by zip protocol to reset the device 33957c478bd9Sstevel@tonic-gate */ 33967c478bd9Sstevel@tonic-gate case SCMD_SDIAG: 33977c478bd9Sstevel@tonic-gate case SCMD_REZERO_UNIT: 33987c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 33997c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 34007c478bd9Sstevel@tonic-gate break; 34017c478bd9Sstevel@tonic-gate 34027c478bd9Sstevel@tonic-gate case SCMD_WRITE_VERIFY: 34037c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 34047c478bd9Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_OUT; 34057c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8]; 34067c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 34077c478bd9Sstevel@tonic-gate break; 34087c478bd9Sstevel@tonic-gate 34097c478bd9Sstevel@tonic-gate /* 34107c478bd9Sstevel@tonic-gate * Next command does not have a SCSI equivalent as 34117c478bd9Sstevel@tonic-gate * it is vendor specific. 34127c478bd9Sstevel@tonic-gate * It was listed in the vendor's ATAPI Zip specs. 34137c478bd9Sstevel@tonic-gate */ 34147c478bd9Sstevel@tonic-gate case SCMD_READ_FORMAT_CAP: 34157c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 34167c478bd9Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_IN; 34177c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8]; 34187c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 34197c478bd9Sstevel@tonic-gate break; 34207c478bd9Sstevel@tonic-gate case IOMEGA_CMD_CARTRIDGE_PROTECT: 34217c478bd9Sstevel@tonic-gate cmd->cmd_dir = CBW_DIR_OUT; 34227c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = pkt->pkt_cdbp[4]; 34237c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] &= ~1; /* Make it even */ 34247c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LUN] = pkt->pkt_cdbp[1]; 34257c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 34267c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = pkt->pkt_cdbp[4]; /* Length of password */ 34277c478bd9Sstevel@tonic-gate break; 34287c478bd9Sstevel@tonic-gate 342914d649faScg149915 /* 343014d649faScg149915 * Do not convert SCMD_MODE_SENSE/SELECT to G1 cmds because 343114d649faScg149915 * the mode header is different as well. USB devices don't 343214d649faScg149915 * support 0x03 & 0x04 mode pages, which are already obsoleted 343314d649faScg149915 * by SPC-2 specification. 343414d649faScg149915 */ 343514d649faScg149915 case SCMD_MODE_SENSE: 343614d649faScg149915 case SCMD_MODE_SELECT: 343742e43e98Sguoqing zhu - Sun Microsystems - Beijing China if (((pkt->pkt_cdbp[2] & SD_MODE_SENSE_PAGE_MASK) 343842e43e98Sguoqing zhu - Sun Microsystems - Beijing China == SD_MODE_SENSE_PAGE3_CODE) || 343942e43e98Sguoqing zhu - Sun Microsystems - Beijing China ((pkt->pkt_cdbp[2] & SD_MODE_SENSE_PAGE_MASK) 344042e43e98Sguoqing zhu - Sun Microsystems - Beijing China == SD_MODE_SENSE_PAGE4_CODE)) { 344114d649faScg149915 if (cmd->cmd_bp) { 344214d649faScg149915 cmd->cmd_pkt->pkt_resid = cmd->cmd_bp->b_bcount; 344314d649faScg149915 } 344414d649faScg149915 scsa2usb_force_invalid_request(scsa2usbp, cmd); 344514d649faScg149915 return (SCSA2USB_JUST_ACCEPT); 344614d649faScg149915 } 344714d649faScg149915 /* FALLTHROUGH */ 344814d649faScg149915 34497c478bd9Sstevel@tonic-gate default: 34507c478bd9Sstevel@tonic-gate /* 34517c478bd9Sstevel@tonic-gate * an unknown command may be a uscsi cmd which we 34527c478bd9Sstevel@tonic-gate * should let go thru without mapping 34537c478bd9Sstevel@tonic-gate */ 34547c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 34557c478bd9Sstevel@tonic-gate if (cmd->cmd_bp) { 34567c478bd9Sstevel@tonic-gate cmd->cmd_dir = (cmd->cmd_bp->b_flags & B_READ) ? 34577c478bd9Sstevel@tonic-gate CBW_DIR_IN : CBW_DIR_OUT; 34587c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = cmd->cmd_bp->b_bcount; 34597c478bd9Sstevel@tonic-gate } 34607c478bd9Sstevel@tonic-gate 34617c478bd9Sstevel@tonic-gate break; 34627c478bd9Sstevel@tonic-gate } /* end of switch */ 34637c478bd9Sstevel@tonic-gate 34647c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 34657c478bd9Sstevel@tonic-gate "scsa2usb_handle_scsi_cmd_sub_class: opcode = 0x%x count = 0x%lx", 34667c478bd9Sstevel@tonic-gate pkt->pkt_cdbp[SCSA2USB_OPCODE], cmd->cmd_xfercount); 34677c478bd9Sstevel@tonic-gate 34687c478bd9Sstevel@tonic-gate cmd->cmd_total_xfercount = cmd->cmd_xfercount; 34697c478bd9Sstevel@tonic-gate 34707c478bd9Sstevel@tonic-gate return (SCSA2USB_TRANSPORT); 34717c478bd9Sstevel@tonic-gate } 34727c478bd9Sstevel@tonic-gate 34737c478bd9Sstevel@tonic-gate 34747c478bd9Sstevel@tonic-gate /* 3475df4cb6e0Ssl147100 * scsa2usb_do_tur is performed before READ CAPACITY command is issued. 3476df4cb6e0Ssl147100 * It returns media status, 0 for media ready, -1 for media not ready 3477df4cb6e0Ssl147100 * or other errors. 3478df4cb6e0Ssl147100 */ 3479df4cb6e0Ssl147100 static int 3480df4cb6e0Ssl147100 scsa2usb_do_tur(scsa2usb_state_t *scsa2usbp, struct scsi_address *ap) 3481df4cb6e0Ssl147100 { 3482df4cb6e0Ssl147100 struct scsi_pkt *pkt; 3483df4cb6e0Ssl147100 scsa2usb_cmd_t *turcmd; 3484df4cb6e0Ssl147100 int rval = -1; 3485df4cb6e0Ssl147100 3486df4cb6e0Ssl147100 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 3487df4cb6e0Ssl147100 "scsa2usb_do_tur:"); 3488df4cb6e0Ssl147100 3489df4cb6e0Ssl147100 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 3490df4cb6e0Ssl147100 3491df4cb6e0Ssl147100 mutex_exit(&scsa2usbp->scsa2usb_mutex); 3492df4cb6e0Ssl147100 if ((pkt = scsi_init_pkt(ap, NULL, NULL, CDB_GROUP0, 1, 3493df4cb6e0Ssl147100 PKT_PRIV_LEN, PKT_CONSISTENT, SLEEP_FUNC, NULL)) == NULL) { 3494df4cb6e0Ssl147100 mutex_enter(&scsa2usbp->scsa2usb_mutex); 3495df4cb6e0Ssl147100 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 3496df4cb6e0Ssl147100 scsa2usbp->scsa2usb_log_handle, 3497df4cb6e0Ssl147100 "scsa2usb_do_tur: init pkt failed"); 3498df4cb6e0Ssl147100 3499df4cb6e0Ssl147100 return (rval); 3500df4cb6e0Ssl147100 } 3501df4cb6e0Ssl147100 3502df4cb6e0Ssl147100 RQ_MAKECOM_G0(pkt, FLAG_HEAD | FLAG_NODISCON, 3503df4cb6e0Ssl147100 (char)SCMD_TEST_UNIT_READY, 0, 0); 3504df4cb6e0Ssl147100 3505df4cb6e0Ssl147100 pkt->pkt_comp = NULL; 3506df4cb6e0Ssl147100 pkt->pkt_time = PKT_DEFAULT_TIMEOUT; 3507df4cb6e0Ssl147100 turcmd = PKT2CMD(pkt); 3508df4cb6e0Ssl147100 3509df4cb6e0Ssl147100 mutex_enter(&scsa2usbp->scsa2usb_mutex); 3510df4cb6e0Ssl147100 scsa2usb_prepare_pkt(scsa2usbp, turcmd->cmd_pkt); 3511df4cb6e0Ssl147100 3512df4cb6e0Ssl147100 if (scsa2usb_cmd_transport(scsa2usbp, turcmd) != TRAN_ACCEPT) { 3513df4cb6e0Ssl147100 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 3514df4cb6e0Ssl147100 scsa2usbp->scsa2usb_log_handle, 3515df4cb6e0Ssl147100 "scsa2usb_do_tur: cmd transport failed, " 3516df4cb6e0Ssl147100 "pkt_reason=0x%x", turcmd->cmd_pkt->pkt_reason); 3517df4cb6e0Ssl147100 } else if (*(turcmd->cmd_pkt->pkt_scbp) != STATUS_GOOD) { 3518df4cb6e0Ssl147100 /* 3519df4cb6e0Ssl147100 * Theoretically, the sense data should be retrieved and 3520df4cb6e0Ssl147100 * sense key be checked when check condition happens. If 3521df4cb6e0Ssl147100 * the sense key is UNIT ATTENTION, TEST UNIT READY cmd 3522df4cb6e0Ssl147100 * needs to be sent again to clear the UNIT ATTENTION and 3523df4cb6e0Ssl147100 * another TUR to be sent to get the real media status. 3524df4cb6e0Ssl147100 * But the AMI virtual floppy device simply cannot recover 3525df4cb6e0Ssl147100 * from UNIT ATTENTION by re-sending a TUR cmd, so it 3526df4cb6e0Ssl147100 * doesn't make any difference whether to check sense key 3527df4cb6e0Ssl147100 * or not. Just ignore sense key checking here and assume 3528df4cb6e0Ssl147100 * the device is NOT READY. 3529df4cb6e0Ssl147100 */ 3530df4cb6e0Ssl147100 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 3531df4cb6e0Ssl147100 scsa2usbp->scsa2usb_log_handle, 3532df4cb6e0Ssl147100 "scsa2usb_do_tur: media not ready"); 3533df4cb6e0Ssl147100 } else { 3534df4cb6e0Ssl147100 rval = 0; 3535df4cb6e0Ssl147100 } 3536df4cb6e0Ssl147100 3537df4cb6e0Ssl147100 mutex_exit(&scsa2usbp->scsa2usb_mutex); 3538df4cb6e0Ssl147100 scsi_destroy_pkt(pkt); 3539df4cb6e0Ssl147100 mutex_enter(&scsa2usbp->scsa2usb_mutex); 3540df4cb6e0Ssl147100 3541df4cb6e0Ssl147100 return (rval); 3542df4cb6e0Ssl147100 } 3543df4cb6e0Ssl147100 3544df4cb6e0Ssl147100 3545df4cb6e0Ssl147100 /* 35467c478bd9Sstevel@tonic-gate * scsa2usb_check_ufi_blacklist_attrs: 35477c478bd9Sstevel@tonic-gate * validate "scsa2usb_blacklist_attrs" (see scsa2usb.h) 35487c478bd9Sstevel@tonic-gate * if blacklisted attrs match accept the request 35497c478bd9Sstevel@tonic-gate * attributes checked are:- 35507c478bd9Sstevel@tonic-gate * SCSA2USB_ATTRS_GET_CONF 35517c478bd9Sstevel@tonic-gate * SCSA2USB_ATTRS_GET_PERF 35527c478bd9Sstevel@tonic-gate * SCSA2USB_ATTRS_GET_START_STOP 35537c478bd9Sstevel@tonic-gate */ 35547c478bd9Sstevel@tonic-gate static int 35557c478bd9Sstevel@tonic-gate scsa2usb_check_ufi_blacklist_attrs(scsa2usb_state_t *scsa2usbp, uchar_t opcode, 35567c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd) 35577c478bd9Sstevel@tonic-gate { 35587c478bd9Sstevel@tonic-gate int rval = SCSA2USB_TRANSPORT; 35597c478bd9Sstevel@tonic-gate 35607c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 35617c478bd9Sstevel@tonic-gate 35627c478bd9Sstevel@tonic-gate switch (opcode) { 35637c478bd9Sstevel@tonic-gate case SCMD_PRIN: 35647c478bd9Sstevel@tonic-gate case SCMD_PROUT: 35657c478bd9Sstevel@tonic-gate rval = SCSA2USB_JUST_ACCEPT; 35667c478bd9Sstevel@tonic-gate break; 35677c478bd9Sstevel@tonic-gate case SCMD_MODE_SENSE: 35687c478bd9Sstevel@tonic-gate case SCMD_MODE_SELECT: 35697c478bd9Sstevel@tonic-gate if (cmd->cmd_bp) { 35707c478bd9Sstevel@tonic-gate cmd->cmd_pkt->pkt_resid = cmd->cmd_bp->b_bcount; 35717c478bd9Sstevel@tonic-gate } 35727c478bd9Sstevel@tonic-gate scsa2usb_force_invalid_request(scsa2usbp, cmd); 35737c478bd9Sstevel@tonic-gate rval = SCSA2USB_JUST_ACCEPT; 35747c478bd9Sstevel@tonic-gate break; 35757c478bd9Sstevel@tonic-gate case SCMD_GET_CONFIGURATION: 35767c478bd9Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_GET_CONF)) { 35777c478bd9Sstevel@tonic-gate rval = SCSA2USB_JUST_ACCEPT; 35787c478bd9Sstevel@tonic-gate } 35797c478bd9Sstevel@tonic-gate break; 35807c478bd9Sstevel@tonic-gate case SCMD_GET_PERFORMANCE: 35817c478bd9Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_GET_PERF)) { 35827c478bd9Sstevel@tonic-gate rval = SCSA2USB_JUST_ACCEPT; 35837c478bd9Sstevel@tonic-gate } 35847c478bd9Sstevel@tonic-gate break; 35857c478bd9Sstevel@tonic-gate case SCMD_START_STOP: 35867c478bd9Sstevel@tonic-gate /* 35877c478bd9Sstevel@tonic-gate * some CB/CBI devices don't have mechanics that spin the 35887c478bd9Sstevel@tonic-gate * media up and down. So, it doesn't make much sense 35897c478bd9Sstevel@tonic-gate * to issue this cmd to those devices. 35907c478bd9Sstevel@tonic-gate */ 35917c478bd9Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_START_STOP)) { 35927c478bd9Sstevel@tonic-gate rval = SCSA2USB_JUST_ACCEPT; 35937c478bd9Sstevel@tonic-gate } 35947c478bd9Sstevel@tonic-gate break; 3595df4cb6e0Ssl147100 case SCMD_READ_CAPACITY: 3596df4cb6e0Ssl147100 /* 3597df4cb6e0Ssl147100 * Some devices don't support READ CAPACITY command 3598df4cb6e0Ssl147100 * when media is not ready. Need to check media status 3599df4cb6e0Ssl147100 * before issuing the cmd to such device. 3600df4cb6e0Ssl147100 */ 3601df4cb6e0Ssl147100 if (!(scsa2usbp->scsa2usb_attrs & 3602df4cb6e0Ssl147100 SCSA2USB_ATTRS_NO_MEDIA_CHECK)) { 3603df4cb6e0Ssl147100 struct scsi_pkt *pkt = cmd->cmd_pkt; 3604df4cb6e0Ssl147100 3605df4cb6e0Ssl147100 ASSERT(scsa2usbp->scsa2usb_cur_pkt == pkt); 3606df4cb6e0Ssl147100 scsa2usbp->scsa2usb_cur_pkt = NULL; 3607df4cb6e0Ssl147100 3608df4cb6e0Ssl147100 if (scsa2usb_do_tur(scsa2usbp, 3609df4cb6e0Ssl147100 &pkt->pkt_address) != 0) { 3610df4cb6e0Ssl147100 /* media not ready, force cmd invalid */ 3611df4cb6e0Ssl147100 if (cmd->cmd_bp) { 3612df4cb6e0Ssl147100 cmd->cmd_pkt->pkt_resid = 3613df4cb6e0Ssl147100 cmd->cmd_bp->b_bcount; 3614df4cb6e0Ssl147100 } 3615df4cb6e0Ssl147100 scsa2usb_force_invalid_request(scsa2usbp, cmd); 3616df4cb6e0Ssl147100 rval = SCSA2USB_JUST_ACCEPT; 3617df4cb6e0Ssl147100 } 3618df4cb6e0Ssl147100 3619df4cb6e0Ssl147100 scsa2usbp->scsa2usb_cur_pkt = pkt; 3620df4cb6e0Ssl147100 } 3621df4cb6e0Ssl147100 break; 36227c478bd9Sstevel@tonic-gate default: 36237c478bd9Sstevel@tonic-gate break; 36247c478bd9Sstevel@tonic-gate } 36257c478bd9Sstevel@tonic-gate 36267c478bd9Sstevel@tonic-gate return (rval); 36277c478bd9Sstevel@tonic-gate } 36287c478bd9Sstevel@tonic-gate 36297c478bd9Sstevel@tonic-gate 36307c478bd9Sstevel@tonic-gate /* 36317c478bd9Sstevel@tonic-gate * scsa2usb_handle_ufi_subclass_cmd: 36327c478bd9Sstevel@tonic-gate * prepare a UFI cmd 36337c478bd9Sstevel@tonic-gate * returns SCSA2USB_TRANSPORT, SCSA2USB_REJECT 36347c478bd9Sstevel@tonic-gate */ 36357c478bd9Sstevel@tonic-gate int 36367c478bd9Sstevel@tonic-gate scsa2usb_handle_ufi_subclass_cmd(scsa2usb_state_t *scsa2usbp, 36377c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd, struct scsi_pkt *pkt) 36387c478bd9Sstevel@tonic-gate { 36397c478bd9Sstevel@tonic-gate uchar_t opcode = pkt->pkt_cdbp[0]; 36407c478bd9Sstevel@tonic-gate 36417c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 36427c478bd9Sstevel@tonic-gate "scsa2usb_handle_ufi_subclass_cmd: cmd = 0x%p pkt = 0x%p", 3643112116d8Sfb209375 (void *)cmd, (void *)pkt); 36447c478bd9Sstevel@tonic-gate 36457c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 36467c478bd9Sstevel@tonic-gate 36477c478bd9Sstevel@tonic-gate bzero(&cmd->cmd_cdb, SCSI_CDB_SIZE); 36487c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_OPCODE] = opcode; /* Set the opcode */ 36497c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LUN] = pkt->pkt_cdbp[1]; 36507c478bd9Sstevel@tonic-gate 36517c478bd9Sstevel@tonic-gate /* 36527c478bd9Sstevel@tonic-gate * decode and convert the packet if necessary 36537c478bd9Sstevel@tonic-gate * for most cmds, we can bcopy the cdb 36547c478bd9Sstevel@tonic-gate */ 36557c478bd9Sstevel@tonic-gate switch (opcode) { 36567c478bd9Sstevel@tonic-gate case SCMD_FORMAT: 36577c478bd9Sstevel@tonic-gate /* if parameter list is specified */ 36587c478bd9Sstevel@tonic-gate if (pkt->pkt_cdbp[1] & 0x10) { 36597c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = 36607c478bd9Sstevel@tonic-gate (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8]; 36617c478bd9Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_OUT; 36627c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP5; 36637c478bd9Sstevel@tonic-gate } 36647c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 36657c478bd9Sstevel@tonic-gate break; 36667c478bd9Sstevel@tonic-gate case SCMD_INQUIRY: 36677c478bd9Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_IN; 36687c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 36697c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_0] = pkt->pkt_cdbp[2]; 36707c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = cmd->cmd_xfercount = 36717c478bd9Sstevel@tonic-gate min(SCSA2USB_MAX_INQ_LEN, 36727c478bd9Sstevel@tonic-gate cmd->cmd_bp ? cmd->cmd_bp->b_bcount : 0); 36737c478bd9Sstevel@tonic-gate break; 36747c478bd9Sstevel@tonic-gate case SCMD_READ_CAPACITY: 36757c478bd9Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_IN; 36767c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 36777c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = sizeof (scsa2usb_read_cap_t); 36787c478bd9Sstevel@tonic-gate break; 36797c478bd9Sstevel@tonic-gate case SCMD_REQUEST_SENSE: 36807c478bd9Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_IN; 36817c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = pkt->pkt_cdbp[4]; 36827c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = pkt->pkt_cdbp[4]; 36837c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP0; 36847c478bd9Sstevel@tonic-gate break; 36857c478bd9Sstevel@tonic-gate 36867c478bd9Sstevel@tonic-gate /* 36877c478bd9Sstevel@tonic-gate * do not convert SCMD_MODE_SENSE/SELECT because the 36887c478bd9Sstevel@tonic-gate * mode header is different as well 36897c478bd9Sstevel@tonic-gate */ 36907c478bd9Sstevel@tonic-gate 36917c478bd9Sstevel@tonic-gate /* 36927c478bd9Sstevel@tonic-gate * see usb_bulkonly.c for comments on the next set of commands 36937c478bd9Sstevel@tonic-gate */ 36947c478bd9Sstevel@tonic-gate case SCMD_READ: 36957c478bd9Sstevel@tonic-gate case SCMD_WRITE: 36967c478bd9Sstevel@tonic-gate case SCMD_READ_G1: 36977c478bd9Sstevel@tonic-gate case SCMD_WRITE_G1: 36987c478bd9Sstevel@tonic-gate case SCMD_READ_G5: 36997c478bd9Sstevel@tonic-gate case SCMD_WRITE_G5: 37007c478bd9Sstevel@tonic-gate case SCMD_READ_LONG: 37017c478bd9Sstevel@tonic-gate case SCMD_WRITE_LONG: 37027c478bd9Sstevel@tonic-gate case SCMD_READ_CD: 37037c478bd9Sstevel@tonic-gate 37047c478bd9Sstevel@tonic-gate return (scsa2usb_rw_transport(scsa2usbp, pkt)); 37057c478bd9Sstevel@tonic-gate 37067c478bd9Sstevel@tonic-gate case SCMD_TEST_UNIT_READY: 37077c478bd9Sstevel@tonic-gate /* 37087c478bd9Sstevel@tonic-gate * Some CB/CBI devices may not support TUR. 37097c478bd9Sstevel@tonic-gate */ 37107c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 37117c478bd9Sstevel@tonic-gate break; 37127c478bd9Sstevel@tonic-gate case SCMD_READ_FORMAT_CAP: 37137c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 37147c478bd9Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_IN; 37157c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 37167c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8]; 37177c478bd9Sstevel@tonic-gate break; 37187c478bd9Sstevel@tonic-gate case SCMD_WRITE_VERIFY: 37197c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 37207c478bd9Sstevel@tonic-gate cmd->cmd_dir = USB_EP_DIR_OUT; 37217c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 37227c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = (pkt->pkt_cdbp[7] << 8) | pkt->pkt_cdbp[8]; 37237c478bd9Sstevel@tonic-gate break; 37247c478bd9Sstevel@tonic-gate case SCMD_START_STOP: 37257c478bd9Sstevel@tonic-gate /* A larger timeout is needed for 'flaky' CD-RW devices */ 37267c478bd9Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_BIG_TIMEOUT)) { 37277c478bd9Sstevel@tonic-gate cmd->cmd_timeout = max(cmd->cmd_timeout, 37287c478bd9Sstevel@tonic-gate 20 * SCSA2USB_BULK_PIPE_TIMEOUT); 37297c478bd9Sstevel@tonic-gate } 37307c478bd9Sstevel@tonic-gate /* FALLTHRU */ 37317c478bd9Sstevel@tonic-gate default: 37327c478bd9Sstevel@tonic-gate /* 37337c478bd9Sstevel@tonic-gate * all other commands don't need special mapping 37347c478bd9Sstevel@tonic-gate */ 37357c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 37367c478bd9Sstevel@tonic-gate if (cmd->cmd_bp) { 37377c478bd9Sstevel@tonic-gate cmd->cmd_dir = (cmd->cmd_bp->b_flags & B_READ) ? 37387c478bd9Sstevel@tonic-gate CBW_DIR_IN : CBW_DIR_OUT; 37397c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = cmd->cmd_bp->b_bcount; 37407c478bd9Sstevel@tonic-gate } 37417c478bd9Sstevel@tonic-gate break; 37427c478bd9Sstevel@tonic-gate 37437c478bd9Sstevel@tonic-gate } /* end of switch */ 37447c478bd9Sstevel@tonic-gate 37457c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 37467c478bd9Sstevel@tonic-gate "scsa2usb_handle_ufi_subclass_cmd: opcode = 0x%x count = 0x%lx", 37477c478bd9Sstevel@tonic-gate opcode, cmd->cmd_xfercount); 37487c478bd9Sstevel@tonic-gate 37497c478bd9Sstevel@tonic-gate cmd->cmd_total_xfercount = cmd->cmd_xfercount; 37507c478bd9Sstevel@tonic-gate 37517c478bd9Sstevel@tonic-gate return (SCSA2USB_TRANSPORT); 37527c478bd9Sstevel@tonic-gate } 37537c478bd9Sstevel@tonic-gate 37547c478bd9Sstevel@tonic-gate 37557c478bd9Sstevel@tonic-gate /* 37567c478bd9Sstevel@tonic-gate * scsa2usb_rw_transport: 37577c478bd9Sstevel@tonic-gate * Handle splitting READ and WRITE requests to the 37587c478bd9Sstevel@tonic-gate * device to a size that the host controller allows. 37597c478bd9Sstevel@tonic-gate * 37607c478bd9Sstevel@tonic-gate * returns TRAN_* values and not USB_SUCCESS/FAILURE 37617c478bd9Sstevel@tonic-gate * 37627c478bd9Sstevel@tonic-gate * To support CD-R/CD-RW/DVD media, we need to support a 37637c478bd9Sstevel@tonic-gate * variety of block sizes for the different types of CD 37647c478bd9Sstevel@tonic-gate * data (audio, data, video, CD-XA, yellowbook, redbook etc.) 37657c478bd9Sstevel@tonic-gate * 37667c478bd9Sstevel@tonic-gate * Some of the block sizes used are:- 512, 1k, 2k, 2056, 2336 37677c478bd9Sstevel@tonic-gate * 2340, 2352, 2368, 2448, 2646, 2647 etc. 37687c478bd9Sstevel@tonic-gate * 37697c478bd9Sstevel@tonic-gate * NOTE: the driver could be entertaining a SCSI CDB that uses 37707c478bd9Sstevel@tonic-gate * any of the above listed block sizes at a given time, and a 37717c478bd9Sstevel@tonic-gate * totally different block size at any other given time for a 37727c478bd9Sstevel@tonic-gate * different CDB. 37737c478bd9Sstevel@tonic-gate * 37747c478bd9Sstevel@tonic-gate * We need to compute block size every time and figure out 37757c478bd9Sstevel@tonic-gate * matching LBA and LEN accordingly. 37767c478bd9Sstevel@tonic-gate * 37777c478bd9Sstevel@tonic-gate * Also UHCI has a limitation that it can only xfer 32k at a 37787c478bd9Sstevel@tonic-gate * given time. So, with "odd" sized blocks and a limitation of 37797c478bd9Sstevel@tonic-gate * how much we can xfer per shot, we need to compute xfer_count 37807c478bd9Sstevel@tonic-gate * as well each time. 37817c478bd9Sstevel@tonic-gate * 37827c478bd9Sstevel@tonic-gate * The same computation is also done in the function 37837c478bd9Sstevel@tonic-gate * scsa2usb_setup_next_xfer(). To save computing block_size in 37847c478bd9Sstevel@tonic-gate * this function, I am saving block_size in "cmd" now. 37857c478bd9Sstevel@tonic-gate */ 37867c478bd9Sstevel@tonic-gate int 37877c478bd9Sstevel@tonic-gate scsa2usb_rw_transport(scsa2usb_state_t *scsa2usbp, struct scsi_pkt *pkt) 37887c478bd9Sstevel@tonic-gate { 37897c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd = PKT2CMD(pkt); 37907c478bd9Sstevel@tonic-gate int lba, dir, opcode; 37917c478bd9Sstevel@tonic-gate struct buf *bp = cmd->cmd_bp; 37927c478bd9Sstevel@tonic-gate size_t len, xfer_count; 37937c478bd9Sstevel@tonic-gate size_t blk_size; /* calculate the block size to be used */ 37947c478bd9Sstevel@tonic-gate int sz; 37957c478bd9Sstevel@tonic-gate 37967c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 37977c478bd9Sstevel@tonic-gate "scsa2usb_rw_transport:"); 37987c478bd9Sstevel@tonic-gate 37997c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 38007c478bd9Sstevel@tonic-gate 38017c478bd9Sstevel@tonic-gate opcode = pkt->pkt_cdbp[0]; 38027c478bd9Sstevel@tonic-gate blk_size = scsa2usbp->scsa2usb_lbasize[pkt->pkt_address.a_lun]; 38037c478bd9Sstevel@tonic-gate /* set to default */ 38047c478bd9Sstevel@tonic-gate 38057c478bd9Sstevel@tonic-gate switch (opcode) { 38067c478bd9Sstevel@tonic-gate case SCMD_READ: 38077c478bd9Sstevel@tonic-gate /* 38087c478bd9Sstevel@tonic-gate * Note that READ/WRITE(6) are not supported by the drive. 38097c478bd9Sstevel@tonic-gate * convert it into a 10 byte read/write. 38107c478bd9Sstevel@tonic-gate */ 38117c478bd9Sstevel@tonic-gate lba = SCSA2USB_LBA_6BYTE(pkt); 38127c478bd9Sstevel@tonic-gate len = SCSA2USB_LEN_6BYTE(pkt); 38137c478bd9Sstevel@tonic-gate opcode = SCMD_READ_G1; /* Overwrite it w/ byte 10 cmd val */ 38147c478bd9Sstevel@tonic-gate dir = USB_EP_DIR_IN; 38157c478bd9Sstevel@tonic-gate break; 38167c478bd9Sstevel@tonic-gate case SCMD_WRITE: 38177c478bd9Sstevel@tonic-gate lba = SCSA2USB_LBA_6BYTE(pkt); 38187c478bd9Sstevel@tonic-gate len = SCSA2USB_LEN_6BYTE(pkt); 38197c478bd9Sstevel@tonic-gate opcode = SCMD_WRITE_G1; /* Overwrite it w/ byte 10 cmd val */ 38207c478bd9Sstevel@tonic-gate dir = USB_EP_DIR_OUT; 38217c478bd9Sstevel@tonic-gate break; 38227c478bd9Sstevel@tonic-gate case SCMD_READ_G1: 38237c478bd9Sstevel@tonic-gate case SCMD_READ_LONG: 38247c478bd9Sstevel@tonic-gate lba = SCSA2USB_LBA_10BYTE(pkt); 38257c478bd9Sstevel@tonic-gate len = SCSA2USB_LEN_10BYTE(pkt); 38267c478bd9Sstevel@tonic-gate dir = USB_EP_DIR_IN; 38277c478bd9Sstevel@tonic-gate break; 38287c478bd9Sstevel@tonic-gate case SCMD_WRITE_G1: 38297c478bd9Sstevel@tonic-gate case SCMD_WRITE_LONG: 38307c478bd9Sstevel@tonic-gate lba = SCSA2USB_LBA_10BYTE(pkt); 38317c478bd9Sstevel@tonic-gate len = SCSA2USB_LEN_10BYTE(pkt); 38327c478bd9Sstevel@tonic-gate dir = USB_EP_DIR_OUT; 38337c478bd9Sstevel@tonic-gate if (len) { 38347c478bd9Sstevel@tonic-gate sz = SCSA2USB_CDRW_BLKSZ(bp ? bp->b_bcount : 0, len); 38357c478bd9Sstevel@tonic-gate if (SCSA2USB_VALID_CDRW_BLKSZ(sz)) { 38367c478bd9Sstevel@tonic-gate blk_size = sz; /* change it accordingly */ 38377c478bd9Sstevel@tonic-gate } 38387c478bd9Sstevel@tonic-gate } 38397c478bd9Sstevel@tonic-gate break; 38407c478bd9Sstevel@tonic-gate case SCMD_READ_CD: 38417c478bd9Sstevel@tonic-gate lba = SCSA2USB_LBA_10BYTE(pkt); 38427c478bd9Sstevel@tonic-gate len = SCSA2USB_LEN_READ_CD(pkt); 38437c478bd9Sstevel@tonic-gate dir = USB_EP_DIR_IN; 38447c478bd9Sstevel@tonic-gate 38457c478bd9Sstevel@tonic-gate /* Figure out the block size */ 38467c478bd9Sstevel@tonic-gate blk_size = scsa2usb_read_cd_blk_size(pkt->pkt_cdbp[1] >> 2); 38477c478bd9Sstevel@tonic-gate break; 38487c478bd9Sstevel@tonic-gate case SCMD_READ_G5: 38497c478bd9Sstevel@tonic-gate lba = SCSA2USB_LBA_12BYTE(pkt); 38507c478bd9Sstevel@tonic-gate len = SCSA2USB_LEN_12BYTE(pkt); 38517c478bd9Sstevel@tonic-gate dir = USB_EP_DIR_IN; 38527c478bd9Sstevel@tonic-gate break; 38537c478bd9Sstevel@tonic-gate case SCMD_WRITE_G5: 38547c478bd9Sstevel@tonic-gate lba = SCSA2USB_LBA_12BYTE(pkt); 38557c478bd9Sstevel@tonic-gate len = SCSA2USB_LEN_12BYTE(pkt); 38567c478bd9Sstevel@tonic-gate dir = USB_EP_DIR_OUT; 38577c478bd9Sstevel@tonic-gate break; 38587c478bd9Sstevel@tonic-gate } 38597c478bd9Sstevel@tonic-gate 38607c478bd9Sstevel@tonic-gate cmd->cmd_total_xfercount = xfer_count = len * blk_size; 38617c478bd9Sstevel@tonic-gate 38627c478bd9Sstevel@tonic-gate /* reduce xfer count if necessary */ 38637c478bd9Sstevel@tonic-gate if (blk_size && 38647c478bd9Sstevel@tonic-gate (xfer_count > scsa2usbp->scsa2usb_max_bulk_xfer_size)) { 38657c478bd9Sstevel@tonic-gate /* 38667c478bd9Sstevel@tonic-gate * For CD-RW devices reduce the xfer count based 38677c478bd9Sstevel@tonic-gate * on the block size used by these devices. The 38687c478bd9Sstevel@tonic-gate * block size could change for READ_CD and WRITE 38697c478bd9Sstevel@tonic-gate * opcodes. 38707c478bd9Sstevel@tonic-gate * 38717c478bd9Sstevel@tonic-gate * Also as UHCI allows a max xfer of 32k at a time; 38727c478bd9Sstevel@tonic-gate * compute the xfer_count based on the new block_size. 38737c478bd9Sstevel@tonic-gate * 38747c478bd9Sstevel@tonic-gate * The len part of the cdb changes as a result of that. 38757c478bd9Sstevel@tonic-gate */ 38767c478bd9Sstevel@tonic-gate if (SCSA2USB_VALID_CDRW_BLKSZ(blk_size)) { 38777c478bd9Sstevel@tonic-gate xfer_count = ((scsa2usbp->scsa2usb_max_bulk_xfer_size/ 38787c478bd9Sstevel@tonic-gate blk_size) * blk_size); 38797c478bd9Sstevel@tonic-gate len = xfer_count/blk_size; 38807c478bd9Sstevel@tonic-gate xfer_count = blk_size * len; 38817c478bd9Sstevel@tonic-gate } else { 38827c478bd9Sstevel@tonic-gate xfer_count = scsa2usbp->scsa2usb_max_bulk_xfer_size; 38837c478bd9Sstevel@tonic-gate len = xfer_count/blk_size; 38847c478bd9Sstevel@tonic-gate } 38857c478bd9Sstevel@tonic-gate } 38867c478bd9Sstevel@tonic-gate 38877c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = xfer_count; 38887c478bd9Sstevel@tonic-gate cmd->cmd_dir = (uchar_t)dir; 3889d29f5a71Szhigang lu - Sun Microsystems - Beijing China cmd->cmd_blksize = (int)blk_size; 38907c478bd9Sstevel@tonic-gate 38917c478bd9Sstevel@tonic-gate /* 38927c478bd9Sstevel@tonic-gate * Having figure out the 'partial' xfer len based on he 38937c478bd9Sstevel@tonic-gate * block size; fill it in to the cmd->cmd_cdb 38947c478bd9Sstevel@tonic-gate */ 38957c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_OPCODE] = (uchar_t)opcode; 38967c478bd9Sstevel@tonic-gate switch (opcode) { 38977c478bd9Sstevel@tonic-gate case SCMD_READ_CD: 38987c478bd9Sstevel@tonic-gate bcopy(pkt->pkt_cdbp, &cmd->cmd_cdb, cmd->cmd_cdblen); 38997c478bd9Sstevel@tonic-gate scsa2usb_fill_up_ReadCD_cdb_len(cmd, len, CDB_GROUP5); 39007c478bd9Sstevel@tonic-gate break; 39017c478bd9Sstevel@tonic-gate case SCMD_WRITE_G5: 39027c478bd9Sstevel@tonic-gate case SCMD_READ_G5: 39037c478bd9Sstevel@tonic-gate scsa2usb_fill_up_12byte_cdb_len(cmd, len, CDB_GROUP5); 39047c478bd9Sstevel@tonic-gate break; 39057c478bd9Sstevel@tonic-gate default: 39067c478bd9Sstevel@tonic-gate scsa2usb_fill_up_cdb_len(cmd, len); 39077c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = CDB_GROUP1; 39087c478bd9Sstevel@tonic-gate break; 39097c478bd9Sstevel@tonic-gate } 39107c478bd9Sstevel@tonic-gate 39117c478bd9Sstevel@tonic-gate scsa2usb_fill_up_cdb_lba(cmd, lba); 39127c478bd9Sstevel@tonic-gate 39137c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 39147c478bd9Sstevel@tonic-gate "bcount=0x%lx lba=0x%x len=0x%lx xfercount=0x%lx total=0x%lx", 39157c478bd9Sstevel@tonic-gate bp ? bp->b_bcount : 0, lba, len, cmd->cmd_xfercount, 39167c478bd9Sstevel@tonic-gate cmd->cmd_total_xfercount); 39177c478bd9Sstevel@tonic-gate 39187c478bd9Sstevel@tonic-gate /* Set the timeout value as per command request */ 39197c478bd9Sstevel@tonic-gate if ((opcode == SCMD_WRITE_G1) && SCSA2USB_VALID_CDRW_BLKSZ(blk_size)) { 39207c478bd9Sstevel@tonic-gate /* 39217c478bd9Sstevel@tonic-gate * We increase the time as CD-RW writes have two things 39227c478bd9Sstevel@tonic-gate * to do. After writing out the data to the media, a 39237c478bd9Sstevel@tonic-gate * TOC needs to be filled up at the beginning of the media 39247c478bd9Sstevel@tonic-gate * This is when the write gets "finalized". 39257c478bd9Sstevel@tonic-gate * Hence the actual write could take longer than the 39267c478bd9Sstevel@tonic-gate * value specified in cmd->cmd_timeout. 39277c478bd9Sstevel@tonic-gate */ 39287c478bd9Sstevel@tonic-gate cmd->cmd_timeout *= 4; 39297c478bd9Sstevel@tonic-gate 39307c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, 39317c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 39327c478bd9Sstevel@tonic-gate "new timeout value = 0x%x", cmd->cmd_timeout); 39337c478bd9Sstevel@tonic-gate } 39347c478bd9Sstevel@tonic-gate 39357c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 39367c478bd9Sstevel@tonic-gate "lba 0x%x len 0x%lx xfercount 0x%lx total 0x%lx", 39377c478bd9Sstevel@tonic-gate lba, len, cmd->cmd_xfercount, cmd->cmd_total_xfercount); 39387c478bd9Sstevel@tonic-gate 39397c478bd9Sstevel@tonic-gate return (SCSA2USB_TRANSPORT); 39407c478bd9Sstevel@tonic-gate } 39417c478bd9Sstevel@tonic-gate 39427c478bd9Sstevel@tonic-gate 39437c478bd9Sstevel@tonic-gate /* 39447c478bd9Sstevel@tonic-gate * scsa2usb_setup_next_xfer: 39457c478bd9Sstevel@tonic-gate * For READs and WRITEs we split up the transfer in terms of 39467c478bd9Sstevel@tonic-gate * HCD understood units. This function handles the split transfers. 39477c478bd9Sstevel@tonic-gate * 39487c478bd9Sstevel@tonic-gate * See comments in the previous function scsa2usb_rw_transport 39497c478bd9Sstevel@tonic-gate * 39507c478bd9Sstevel@tonic-gate * The lba computation was being done based on scsa2usb_max_bulk_xfer_size 39517c478bd9Sstevel@tonic-gate * earlier. With CD-RW devices, the xfer_count and the block_size may 39527c478bd9Sstevel@tonic-gate * no longer be a multiple of scsa2usb_max_bulk_xfer_size. So compute 39537c478bd9Sstevel@tonic-gate * xfer_count all over again. Adjust lba, based on the previous requests' 39547c478bd9Sstevel@tonic-gate * len. Find out the len and add it to cmd->cmd_lba to get the new lba 39557c478bd9Sstevel@tonic-gate */ 39567c478bd9Sstevel@tonic-gate void 39577c478bd9Sstevel@tonic-gate scsa2usb_setup_next_xfer(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) 39587c478bd9Sstevel@tonic-gate { 39597c478bd9Sstevel@tonic-gate int xfer_len = min(scsa2usbp->scsa2usb_max_bulk_xfer_size, 39607c478bd9Sstevel@tonic-gate cmd->cmd_total_xfercount); 39617c478bd9Sstevel@tonic-gate int cdb_len; 39627c478bd9Sstevel@tonic-gate size_t blk_size; 39637c478bd9Sstevel@tonic-gate 39647c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 39657c478bd9Sstevel@tonic-gate 39667c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 39677c478bd9Sstevel@tonic-gate "scsa2usb_setup_next_xfer: opcode = 0x%x lba = 0x%x " 39687c478bd9Sstevel@tonic-gate "total count = 0x%lx", cmd->cmd_cdb[SCSA2USB_OPCODE], 39697c478bd9Sstevel@tonic-gate cmd->cmd_lba, cmd->cmd_total_xfercount); 39707c478bd9Sstevel@tonic-gate 39717c478bd9Sstevel@tonic-gate ASSERT(cmd->cmd_total_xfercount > 0); 39727c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = xfer_len; 39737c478bd9Sstevel@tonic-gate blk_size = scsa2usbp->scsa2usb_lbasize[ 39747c478bd9Sstevel@tonic-gate cmd->cmd_pkt->pkt_address.a_lun]; 39757c478bd9Sstevel@tonic-gate 39767c478bd9Sstevel@tonic-gate /* 39777c478bd9Sstevel@tonic-gate * For CD-RW devices reduce the xfer count based on the 39787c478bd9Sstevel@tonic-gate * block_size used by these devices. See changes below 39797c478bd9Sstevel@tonic-gate * where xfer_count is being adjusted. 39807c478bd9Sstevel@tonic-gate * 39817c478bd9Sstevel@tonic-gate * Also adjust len/lba based on the block_size and xfer_count. 39827c478bd9Sstevel@tonic-gate * NOTE: Always calculate lba first, as it based on previous 39837c478bd9Sstevel@tonic-gate * commands' values. 39847c478bd9Sstevel@tonic-gate */ 39857c478bd9Sstevel@tonic-gate switch (cmd->cmd_cdb[SCSA2USB_OPCODE]) { 39867c478bd9Sstevel@tonic-gate case SCMD_READ_CD: 39877c478bd9Sstevel@tonic-gate /* calculate lba = current_lba + len_of_prev_cmd */ 39887c478bd9Sstevel@tonic-gate cmd->cmd_lba += (cmd->cmd_cdb[6] << 16) + 39897c478bd9Sstevel@tonic-gate (cmd->cmd_cdb[7] << 8) + cmd->cmd_cdb[8]; 39907c478bd9Sstevel@tonic-gate cdb_len = xfer_len/cmd->cmd_blksize; 39917c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_2] = (uchar_t)cdb_len; 39927c478bd9Sstevel@tonic-gate /* re-adjust xfer count */ 39937c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = cdb_len * cmd->cmd_blksize; 39947c478bd9Sstevel@tonic-gate break; 39957c478bd9Sstevel@tonic-gate case SCMD_WRITE_G5: 39967c478bd9Sstevel@tonic-gate case SCMD_READ_G5: 39977c478bd9Sstevel@tonic-gate /* calculate lba = current_lba + len_of_prev_cmd */ 39987c478bd9Sstevel@tonic-gate cmd->cmd_lba += (cmd->cmd_cdb[6] << 24) + 39997c478bd9Sstevel@tonic-gate (cmd->cmd_cdb[7] << 16) + (cmd->cmd_cdb[8] << 8) + 40007c478bd9Sstevel@tonic-gate cmd->cmd_cdb[9]; 40017c478bd9Sstevel@tonic-gate if (blk_size) { 40027c478bd9Sstevel@tonic-gate xfer_len /= blk_size; 40037c478bd9Sstevel@tonic-gate } 40047c478bd9Sstevel@tonic-gate scsa2usb_fill_up_12byte_cdb_len(cmd, xfer_len, CDB_GROUP5); 40057c478bd9Sstevel@tonic-gate break; 40067c478bd9Sstevel@tonic-gate case SCMD_WRITE_G1: 40077c478bd9Sstevel@tonic-gate case SCMD_WRITE_LONG: 40087c478bd9Sstevel@tonic-gate /* calculate lba = current_lba + len_of_prev_cmd */ 40097c478bd9Sstevel@tonic-gate cmd->cmd_lba += (cmd->cmd_cdb[7] << 8) + cmd->cmd_cdb[8]; 40107c478bd9Sstevel@tonic-gate if (SCSA2USB_VALID_CDRW_BLKSZ(cmd->cmd_blksize)) { 40117c478bd9Sstevel@tonic-gate blk_size = cmd->cmd_blksize; 40127c478bd9Sstevel@tonic-gate } 40137c478bd9Sstevel@tonic-gate cdb_len = xfer_len/blk_size; 40147c478bd9Sstevel@tonic-gate scsa2usb_fill_up_cdb_len(cmd, cdb_len); 40157c478bd9Sstevel@tonic-gate /* re-adjust xfer count */ 40167c478bd9Sstevel@tonic-gate cmd->cmd_xfercount = cdb_len * blk_size; 40177c478bd9Sstevel@tonic-gate break; 40187c478bd9Sstevel@tonic-gate default: 40197c478bd9Sstevel@tonic-gate if (blk_size) { 40207c478bd9Sstevel@tonic-gate xfer_len /= blk_size; 40217c478bd9Sstevel@tonic-gate } 40227c478bd9Sstevel@tonic-gate scsa2usb_fill_up_cdb_len(cmd, xfer_len); 40237c478bd9Sstevel@tonic-gate cmd->cmd_lba += scsa2usbp->scsa2usb_max_bulk_xfer_size/blk_size; 40247c478bd9Sstevel@tonic-gate } 40257c478bd9Sstevel@tonic-gate 40267c478bd9Sstevel@tonic-gate /* fill in the lba */ 40277c478bd9Sstevel@tonic-gate scsa2usb_fill_up_cdb_lba(cmd, cmd->cmd_lba); 40287c478bd9Sstevel@tonic-gate 40297c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 40307c478bd9Sstevel@tonic-gate "scsa2usb_setup_next_xfer:\n\tlba = 0x%x xfer_len = 0x%x " 40317c478bd9Sstevel@tonic-gate "xfercount = 0x%lx total = 0x%lx", cmd->cmd_lba, xfer_len, 40327c478bd9Sstevel@tonic-gate cmd->cmd_xfercount, cmd->cmd_total_xfercount); 40337c478bd9Sstevel@tonic-gate } 40347c478bd9Sstevel@tonic-gate 40357c478bd9Sstevel@tonic-gate 40367c478bd9Sstevel@tonic-gate /* 40377c478bd9Sstevel@tonic-gate * take one request from the lun's waitQ and transport it 40387c478bd9Sstevel@tonic-gate */ 40397c478bd9Sstevel@tonic-gate static void 40407c478bd9Sstevel@tonic-gate scsa2usb_transport_request(scsa2usb_state_t *scsa2usbp, uint_t lun) 40417c478bd9Sstevel@tonic-gate { 40427c478bd9Sstevel@tonic-gate int rval; 40437c478bd9Sstevel@tonic-gate struct scsi_pkt *pkt; 40447c478bd9Sstevel@tonic-gate struct scsa2usb_cmd *cmd, *arqcmd; 40457c478bd9Sstevel@tonic-gate 40467c478bd9Sstevel@tonic-gate if ((cmd = (scsa2usb_cmd_t *) 40477c478bd9Sstevel@tonic-gate usba_rm_first_pvt_from_list( 40487c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_waitQ[lun])) == NULL) { 40497c478bd9Sstevel@tonic-gate 40507c478bd9Sstevel@tonic-gate return; 40517c478bd9Sstevel@tonic-gate } 40527c478bd9Sstevel@tonic-gate pkt = cmd->cmd_pkt; 40537c478bd9Sstevel@tonic-gate 40547c478bd9Sstevel@tonic-gate /* 40557c478bd9Sstevel@tonic-gate * if device has been disconnected, just complete it 40567c478bd9Sstevel@tonic-gate */ 40577c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_dev_state == USB_DEV_DISCONNECTED) { 40587c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 40597c478bd9Sstevel@tonic-gate "device not accessible"); 40607c478bd9Sstevel@tonic-gate pkt->pkt_reason = CMD_DEV_GONE; 40617c478bd9Sstevel@tonic-gate SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 40627c478bd9Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usbp, pkt); 40637c478bd9Sstevel@tonic-gate 40647c478bd9Sstevel@tonic-gate return; 40657c478bd9Sstevel@tonic-gate } 40667c478bd9Sstevel@tonic-gate 40677c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, 40687c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 40697c478bd9Sstevel@tonic-gate "scsa2usb_transport_request: cmd=0x%p bp=0x%p addr=0x%p", 4070112116d8Sfb209375 (void *)cmd, (void *)cmd->cmd_bp, 4071112116d8Sfb209375 (void *)(cmd->cmd_bp ? cmd->cmd_bp->b_un.b_addr : NULL)); 40727c478bd9Sstevel@tonic-gate 40737c478bd9Sstevel@tonic-gate rval = scsa2usb_cmd_transport(scsa2usbp, cmd); 40747c478bd9Sstevel@tonic-gate 40757c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 40767c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 40777c478bd9Sstevel@tonic-gate "scsa2usb_transport_request: transport rval = %d", 40787c478bd9Sstevel@tonic-gate rval); 40797c478bd9Sstevel@tonic-gate 40807c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_cur_pkt == NULL) { 40817c478bd9Sstevel@tonic-gate 40827c478bd9Sstevel@tonic-gate return; 40837c478bd9Sstevel@tonic-gate } 40847c478bd9Sstevel@tonic-gate 40857c478bd9Sstevel@tonic-gate ASSERT(pkt == scsa2usbp->scsa2usb_cur_pkt); 40867c478bd9Sstevel@tonic-gate 40877c478bd9Sstevel@tonic-gate if (ddi_in_panic()) { 40887c478bd9Sstevel@tonic-gate pkt->pkt_reason = CMD_CMPLT; 40897c478bd9Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usbp, pkt); 40907c478bd9Sstevel@tonic-gate 40917c478bd9Sstevel@tonic-gate return; 40927c478bd9Sstevel@tonic-gate } 40937c478bd9Sstevel@tonic-gate 40947c478bd9Sstevel@tonic-gate /* 40957c478bd9Sstevel@tonic-gate * start an auto-request sense iff 40967c478bd9Sstevel@tonic-gate * there was a check condition, we have enough 40977c478bd9Sstevel@tonic-gate * space in the status block, and we have not 40987c478bd9Sstevel@tonic-gate * faked an auto request sense 40997c478bd9Sstevel@tonic-gate */ 41007c478bd9Sstevel@tonic-gate if ((*(pkt->pkt_scbp) == STATUS_CHECK) && 41017c478bd9Sstevel@tonic-gate (cmd->cmd_scblen >= sizeof (struct scsi_arq_status)) && 41027c478bd9Sstevel@tonic-gate ((pkt->pkt_state & STATE_ARQ_DONE) == 0) && 41037c478bd9Sstevel@tonic-gate (scsa2usb_create_arq_pkt(scsa2usbp, 41047c478bd9Sstevel@tonic-gate &pkt->pkt_address) == USB_SUCCESS)) { 41057c478bd9Sstevel@tonic-gate arqcmd = scsa2usbp->scsa2usb_arq_cmd; 41067c478bd9Sstevel@tonic-gate 41077c478bd9Sstevel@tonic-gate /* 41087c478bd9Sstevel@tonic-gate * copy the timeout from the 41097c478bd9Sstevel@tonic-gate * original packet 41107c478bd9Sstevel@tonic-gate * for lack of a better value 41117c478bd9Sstevel@tonic-gate */ 41127c478bd9Sstevel@tonic-gate arqcmd->cmd_pkt->pkt_time = pkt->pkt_time; 41137c478bd9Sstevel@tonic-gate scsa2usb_prepare_pkt(scsa2usbp, 41147c478bd9Sstevel@tonic-gate arqcmd->cmd_pkt); 41157c478bd9Sstevel@tonic-gate 41167c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cur_pkt = NULL; 41177c478bd9Sstevel@tonic-gate if (scsa2usb_cmd_transport( 41187c478bd9Sstevel@tonic-gate scsa2usbp, arqcmd) == TRAN_ACCEPT) { 41197c478bd9Sstevel@tonic-gate 41207c478bd9Sstevel@tonic-gate /* finish w/ this packet */ 41217c478bd9Sstevel@tonic-gate scsa2usb_complete_arq_pkt( 41227c478bd9Sstevel@tonic-gate scsa2usbp, arqcmd->cmd_pkt, cmd, 41237c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_arq_bp); 41247c478bd9Sstevel@tonic-gate 41257c478bd9Sstevel@tonic-gate /* 41267c478bd9Sstevel@tonic-gate * we have valid request sense 41277c478bd9Sstevel@tonic-gate * data so clear the pkt_reason 41287c478bd9Sstevel@tonic-gate */ 41297c478bd9Sstevel@tonic-gate pkt->pkt_reason = CMD_CMPLT; 41307c478bd9Sstevel@tonic-gate } 41317c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_cur_pkt = pkt; 41327c478bd9Sstevel@tonic-gate scsa2usb_delete_arq_pkt(scsa2usbp); 41337c478bd9Sstevel@tonic-gate } 41347c478bd9Sstevel@tonic-gate 41357c478bd9Sstevel@tonic-gate if ((rval != TRAN_ACCEPT) && 41367c478bd9Sstevel@tonic-gate (pkt->pkt_reason == CMD_CMPLT)) { 41377c478bd9Sstevel@tonic-gate pkt->pkt_reason = CMD_TRAN_ERR; 41387c478bd9Sstevel@tonic-gate } 41397c478bd9Sstevel@tonic-gate 41407c478bd9Sstevel@tonic-gate SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 41417c478bd9Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usbp, pkt); 41427c478bd9Sstevel@tonic-gate 41437c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_cur_pkt == NULL); 41447c478bd9Sstevel@tonic-gate } 41457c478bd9Sstevel@tonic-gate 41467c478bd9Sstevel@tonic-gate 41477c478bd9Sstevel@tonic-gate /* 41487c478bd9Sstevel@tonic-gate * scsa2usb_work_thread: 41497c478bd9Sstevel@tonic-gate * The taskq thread that kicks off the transport (BO and CB/CBI) 41507c478bd9Sstevel@tonic-gate */ 41517c478bd9Sstevel@tonic-gate static void 41527c478bd9Sstevel@tonic-gate scsa2usb_work_thread(void *arg) 41537c478bd9Sstevel@tonic-gate { 41547c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *)arg; 41557c478bd9Sstevel@tonic-gate uint_t lun; 41567c478bd9Sstevel@tonic-gate uint_t count; 41577c478bd9Sstevel@tonic-gate 41587c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 4159496d8c83Sfrits USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 4160112116d8Sfb209375 "scsa2usb_work_thread start: thread_id=0x%p", 4161112116d8Sfb209375 (void *)scsa2usbp->scsa2usb_work_thread_id); 4162496d8c83Sfrits 41637c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_work_thread_id == (kthread_t *)1); 41647c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_work_thread_id = curthread; 41657c478bd9Sstevel@tonic-gate 41667c478bd9Sstevel@tonic-gate /* exclude ugen accesses */ 41677c478bd9Sstevel@tonic-gate while (scsa2usbp->scsa2usb_transport_busy) { 41687c478bd9Sstevel@tonic-gate cv_wait(&scsa2usbp->scsa2usb_transport_busy_cv, 41697c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_mutex); 41707c478bd9Sstevel@tonic-gate } 41717c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_ugen_open_count == 0); 41727c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_transport_busy++; 4173*42cac157SVincent Wang scsa2usbp->scsa2usb_busy_proc = curproc; 41747c478bd9Sstevel@tonic-gate 41757c478bd9Sstevel@tonic-gate scsa2usb_raise_power(scsa2usbp); 41767c478bd9Sstevel@tonic-gate 41777c478bd9Sstevel@tonic-gate /* reopen the pipes if necessary */ 41787c478bd9Sstevel@tonic-gate (void) scsa2usb_open_usb_pipes(scsa2usbp); 41797c478bd9Sstevel@tonic-gate 41807c478bd9Sstevel@tonic-gate for (;;) { 41817c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_ugen_open_count == 0); 41827c478bd9Sstevel@tonic-gate for (lun = 0; lun < scsa2usbp->scsa2usb_n_luns; lun++) { 41837c478bd9Sstevel@tonic-gate scsa2usb_transport_request(scsa2usbp, lun); 41847c478bd9Sstevel@tonic-gate } 41857c478bd9Sstevel@tonic-gate count = 0; 41867c478bd9Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 41877c478bd9Sstevel@tonic-gate count += usba_list_entry_count( 41887c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_waitQ[lun]); 41897c478bd9Sstevel@tonic-gate } 41907c478bd9Sstevel@tonic-gate 41917c478bd9Sstevel@tonic-gate if (count == 0) { 41927c478bd9Sstevel@tonic-gate 41937c478bd9Sstevel@tonic-gate break; 41947c478bd9Sstevel@tonic-gate } 41957c478bd9Sstevel@tonic-gate } 41967c478bd9Sstevel@tonic-gate 41977c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_work_thread_id = 0; 41987c478bd9Sstevel@tonic-gate 41997c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_ugen_open_count == 0); 42007c478bd9Sstevel@tonic-gate 42017c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_transport_busy--; 4202*42cac157SVincent Wang scsa2usbp->scsa2usb_busy_proc = NULL; 42037c478bd9Sstevel@tonic-gate cv_signal(&scsa2usbp->scsa2usb_transport_busy_cv); 42047c478bd9Sstevel@tonic-gate 42057c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 42067c478bd9Sstevel@tonic-gate "scsa2usb_work_thread: exit"); 4207496d8c83Sfrits 4208496d8c83Sfrits mutex_exit(&scsa2usbp->scsa2usb_mutex); 4209496d8c83Sfrits 4210496d8c83Sfrits scsa2usb_pm_idle_component(scsa2usbp); 42117c478bd9Sstevel@tonic-gate } 42127c478bd9Sstevel@tonic-gate 42137c478bd9Sstevel@tonic-gate 42147c478bd9Sstevel@tonic-gate /* 42157c478bd9Sstevel@tonic-gate * scsa2usb_flush_waitQ: 42167c478bd9Sstevel@tonic-gate * empties the entire waitQ with errors asap. 42177c478bd9Sstevel@tonic-gate * 42187c478bd9Sstevel@tonic-gate * It is called from scsa2usb_scsi_reset and scsa2usb_panic_callb. 42197c478bd9Sstevel@tonic-gate * If the device is reset; we should empty the waitQ right away. 42207c478bd9Sstevel@tonic-gate * If the system has paniced; we should empty the waitQ right away. 42217c478bd9Sstevel@tonic-gate * 42227c478bd9Sstevel@tonic-gate * CPR suspend will only succeed if device is idle. No need to call 42237c478bd9Sstevel@tonic-gate * this function for CPR suspend case. 42247c478bd9Sstevel@tonic-gate */ 42257c478bd9Sstevel@tonic-gate static void 42267c478bd9Sstevel@tonic-gate scsa2usb_flush_waitQ(scsa2usb_state_t *scsa2usbp, uint_t lun, 42277c478bd9Sstevel@tonic-gate uchar_t error) 42287c478bd9Sstevel@tonic-gate { 42297c478bd9Sstevel@tonic-gate struct scsi_pkt *pkt; 42307c478bd9Sstevel@tonic-gate struct scsa2usb_cmd *cmd; 42317c478bd9Sstevel@tonic-gate usba_list_entry_t head; 42327c478bd9Sstevel@tonic-gate 42337c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 42347c478bd9Sstevel@tonic-gate 42357c478bd9Sstevel@tonic-gate usba_move_list(&scsa2usbp->scsa2usb_waitQ[lun], &head, 42367c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_data->dev_iblock_cookie); 42377c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 42387c478bd9Sstevel@tonic-gate 42397c478bd9Sstevel@tonic-gate while ((cmd = (scsa2usb_cmd_t *)usba_rm_first_pvt_from_list(&head)) != 42407c478bd9Sstevel@tonic-gate NULL) { 42417c478bd9Sstevel@tonic-gate pkt = cmd->cmd_pkt; 42427c478bd9Sstevel@tonic-gate pkt->pkt_reason = error; /* set error */ 42437c478bd9Sstevel@tonic-gate 42447c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 42457c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_DO_COMP; 42467c478bd9Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usbp, pkt); 42477c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 42487c478bd9Sstevel@tonic-gate } /* end of while */ 42497c478bd9Sstevel@tonic-gate } 42507c478bd9Sstevel@tonic-gate 42517c478bd9Sstevel@tonic-gate 42527c478bd9Sstevel@tonic-gate /* 42537c478bd9Sstevel@tonic-gate * scsa2usb_do_inquiry is performed before INIT CHILD and we have 42547c478bd9Sstevel@tonic-gate * to fake a few things normally done by SCSA 42557c478bd9Sstevel@tonic-gate */ 42567c478bd9Sstevel@tonic-gate static void 42577c478bd9Sstevel@tonic-gate scsa2usb_do_inquiry(scsa2usb_state_t *scsa2usbp, uint_t target, uint_t lun) 42587c478bd9Sstevel@tonic-gate { 42597c478bd9Sstevel@tonic-gate struct buf *bp; 42607c478bd9Sstevel@tonic-gate struct scsi_pkt *pkt; 42617c478bd9Sstevel@tonic-gate struct scsi_address ap; 42627c478bd9Sstevel@tonic-gate int len = SCSA2USB_MAX_INQ_LEN; 42637c478bd9Sstevel@tonic-gate 42647c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 42657c478bd9Sstevel@tonic-gate "scsa2usb_do_inquiry: %d bytes", len); 42667c478bd9Sstevel@tonic-gate 42677c478bd9Sstevel@tonic-gate /* is it inquiry-challenged? */ 42687c478bd9Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_INQUIRY)) { 42693fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic scsa2usb_fake_inquiry(scsa2usbp, 42703fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic &scsa2usbp->scsa2usb_lun_inquiry[lun]); 42717c478bd9Sstevel@tonic-gate return; 42727c478bd9Sstevel@tonic-gate } 42737c478bd9Sstevel@tonic-gate 42747c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 42757c478bd9Sstevel@tonic-gate 42767c478bd9Sstevel@tonic-gate bzero(&ap, sizeof (struct scsi_address)); 42777c478bd9Sstevel@tonic-gate ap.a_hba_tran = scsa2usbp->scsa2usb_tran; 4278d29f5a71Szhigang lu - Sun Microsystems - Beijing China ap.a_target = (ushort_t)target; 4279d29f5a71Szhigang lu - Sun Microsystems - Beijing China ap.a_lun = (uchar_t)lun; 42807c478bd9Sstevel@tonic-gate 42817c478bd9Sstevel@tonic-gate /* limit inquiry to 36 bytes */ 42827c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 42837c478bd9Sstevel@tonic-gate if ((bp = scsi_alloc_consistent_buf(&ap, (struct buf *)NULL, 42847c478bd9Sstevel@tonic-gate len, B_READ, SLEEP_FUNC, NULL)) == NULL) { 42857c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 42867c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 42877c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 42887c478bd9Sstevel@tonic-gate "scsa2usb_do_inquiry: failed"); 42897c478bd9Sstevel@tonic-gate 42907c478bd9Sstevel@tonic-gate return; 42917c478bd9Sstevel@tonic-gate } 42927c478bd9Sstevel@tonic-gate 42937c478bd9Sstevel@tonic-gate pkt = scsi_init_pkt(&ap, NULL, bp, CDB_GROUP0, 1, 42947c478bd9Sstevel@tonic-gate PKT_PRIV_LEN, PKT_CONSISTENT, SLEEP_FUNC, NULL); 42957c478bd9Sstevel@tonic-gate 4296d29f5a71Szhigang lu - Sun Microsystems - Beijing China RQ_MAKECOM_G0(pkt, FLAG_NOINTR, (char)SCMD_INQUIRY, 0, (char)len); 42977c478bd9Sstevel@tonic-gate 42987c478bd9Sstevel@tonic-gate pkt->pkt_comp = NULL; 42997c478bd9Sstevel@tonic-gate pkt->pkt_time = 5; 43007c478bd9Sstevel@tonic-gate bzero(bp->b_un.b_addr, len); 43017c478bd9Sstevel@tonic-gate 43027c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 43037c478bd9Sstevel@tonic-gate "scsa2usb_do_inquiry:INQUIRY"); 43047c478bd9Sstevel@tonic-gate 43057c478bd9Sstevel@tonic-gate (void) scsi_transport(pkt); 43067c478bd9Sstevel@tonic-gate 43077c478bd9Sstevel@tonic-gate if (pkt->pkt_reason) { 4308d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_MASK_SCSA, 43097c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 43107c478bd9Sstevel@tonic-gate "INQUIRY failed, cannot determine device type, " 43117c478bd9Sstevel@tonic-gate "pkt_reason=0x%x", pkt->pkt_reason); 43127c478bd9Sstevel@tonic-gate 43137c478bd9Sstevel@tonic-gate /* not much hope for other cmds, reduce */ 43147c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 43157c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_attrs &= 43167c478bd9Sstevel@tonic-gate ~SCSA2USB_ATTRS_REDUCED_CMD; 43173fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic scsa2usb_fake_inquiry(scsa2usbp, 43183fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic &scsa2usbp->scsa2usb_lun_inquiry[lun]); 43197c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 43207c478bd9Sstevel@tonic-gate } 43217c478bd9Sstevel@tonic-gate 43227c478bd9Sstevel@tonic-gate scsi_destroy_pkt(pkt); 43237c478bd9Sstevel@tonic-gate scsi_free_consistent_buf(bp); 43247c478bd9Sstevel@tonic-gate 43257c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 43267c478bd9Sstevel@tonic-gate } 43277c478bd9Sstevel@tonic-gate 43287c478bd9Sstevel@tonic-gate 43297c478bd9Sstevel@tonic-gate /* 43307c478bd9Sstevel@tonic-gate * scsa2usb_fake_inquiry: 43317c478bd9Sstevel@tonic-gate * build an inquiry for a given device that doesnt like inquiry 43327c478bd9Sstevel@tonic-gate * commands. 43337c478bd9Sstevel@tonic-gate */ 43343fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic static void 43353fbe3e28Svitezslav batrla - Sun Microsystems - Prague Czech Republic scsa2usb_fake_inquiry(scsa2usb_state_t *scsa2usbp, struct scsi_inquiry *inqp) 43367c478bd9Sstevel@tonic-gate { 43377c478bd9Sstevel@tonic-gate usb_client_dev_data_t *dev_data = scsa2usbp->scsa2usb_dev_data; 43387c478bd9Sstevel@tonic-gate int len; 43397c478bd9Sstevel@tonic-gate 43407c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 43417c478bd9Sstevel@tonic-gate "scsa2usb_fake_inquiry:"); 43427c478bd9Sstevel@tonic-gate 43437c478bd9Sstevel@tonic-gate bzero(inqp, sizeof (struct scsi_inquiry)); 43447c478bd9Sstevel@tonic-gate for (len = 0; len < sizeof (inqp->inq_vid); len++) { 43457c478bd9Sstevel@tonic-gate *(inqp->inq_vid + len) = ' '; 43467c478bd9Sstevel@tonic-gate } 43477c478bd9Sstevel@tonic-gate 43487c478bd9Sstevel@tonic-gate for (len = 0; len < sizeof (inqp->inq_pid); len++) { 43497c478bd9Sstevel@tonic-gate *(inqp->inq_pid + len) = ' '; 43507c478bd9Sstevel@tonic-gate } 43517c478bd9Sstevel@tonic-gate 43527c478bd9Sstevel@tonic-gate inqp->inq_dtype = DTYPE_DIRECT; 43537c478bd9Sstevel@tonic-gate inqp->inq_rmb = 1; 43547c478bd9Sstevel@tonic-gate inqp->inq_ansi = 2; 43557c478bd9Sstevel@tonic-gate inqp->inq_rdf = RDF_SCSI2; 43567c478bd9Sstevel@tonic-gate inqp->inq_len = sizeof (struct scsi_inquiry)-4; 43577c478bd9Sstevel@tonic-gate 43587c478bd9Sstevel@tonic-gate /* Fill in the Vendor id/Product id strings */ 43597c478bd9Sstevel@tonic-gate if (dev_data->dev_mfg) { 43607c478bd9Sstevel@tonic-gate if ((len = strlen(dev_data->dev_mfg)) > 43617c478bd9Sstevel@tonic-gate sizeof (inqp->inq_vid)) { 43627c478bd9Sstevel@tonic-gate len = sizeof (inqp->inq_vid); 43637c478bd9Sstevel@tonic-gate } 43647c478bd9Sstevel@tonic-gate bcopy(dev_data->dev_mfg, inqp->inq_vid, len); 43657c478bd9Sstevel@tonic-gate } 43667c478bd9Sstevel@tonic-gate 43677c478bd9Sstevel@tonic-gate if (dev_data->dev_product) { 43687c478bd9Sstevel@tonic-gate if ((len = strlen(dev_data->dev_product)) > 43697c478bd9Sstevel@tonic-gate sizeof (inqp->inq_pid)) { 43707c478bd9Sstevel@tonic-gate len = sizeof (inqp->inq_pid); 43717c478bd9Sstevel@tonic-gate } 43727c478bd9Sstevel@tonic-gate bcopy(dev_data->dev_product, inqp->inq_pid, len); 43737c478bd9Sstevel@tonic-gate } 43747c478bd9Sstevel@tonic-gate 43757c478bd9Sstevel@tonic-gate /* Set the Revision to the Device */ 43767c478bd9Sstevel@tonic-gate inqp->inq_revision[0] = 0x30 + 43777c478bd9Sstevel@tonic-gate ((dev_data->dev_descr->bcdDevice>>12) & 0xF); 43787c478bd9Sstevel@tonic-gate inqp->inq_revision[1] = 0x30 + 43797c478bd9Sstevel@tonic-gate ((dev_data->dev_descr->bcdDevice>>8) & 0xF); 43807c478bd9Sstevel@tonic-gate inqp->inq_revision[2] = 0x30 + 43817c478bd9Sstevel@tonic-gate ((dev_data->dev_descr->bcdDevice>>4) & 0xF); 43827c478bd9Sstevel@tonic-gate inqp->inq_revision[3] = 0x30 + 43837c478bd9Sstevel@tonic-gate ((dev_data->dev_descr->bcdDevice) & 0xF); 43847c478bd9Sstevel@tonic-gate } 43857c478bd9Sstevel@tonic-gate 43867c478bd9Sstevel@tonic-gate 43877c478bd9Sstevel@tonic-gate /* 43887c478bd9Sstevel@tonic-gate * scsa2usb_create_arq_pkt: 43897c478bd9Sstevel@tonic-gate * Create and ARQ packet to get request sense data 43907c478bd9Sstevel@tonic-gate */ 43917c478bd9Sstevel@tonic-gate static int 43927c478bd9Sstevel@tonic-gate scsa2usb_create_arq_pkt(scsa2usb_state_t *scsa2usbp, struct scsi_address *ap) 43937c478bd9Sstevel@tonic-gate { 43947c478bd9Sstevel@tonic-gate struct buf *bp; 43957c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *arq_cmd; 43967c478bd9Sstevel@tonic-gate 43977c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 4398112116d8Sfb209375 "scsa2usb_create_arq_pkt: scsa2usbp: %p, ap: %p", 4399112116d8Sfb209375 (void *)scsa2usbp, (void *)ap); 44007c478bd9Sstevel@tonic-gate 44017c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 44027c478bd9Sstevel@tonic-gate 44037c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 44047c478bd9Sstevel@tonic-gate if ((bp = scsi_alloc_consistent_buf(ap, (struct buf *)NULL, 44057c478bd9Sstevel@tonic-gate SENSE_LENGTH, B_READ, SLEEP_FUNC, NULL)) == NULL) { 44067c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 44077c478bd9Sstevel@tonic-gate 44087c478bd9Sstevel@tonic-gate return (USB_FAILURE); 44097c478bd9Sstevel@tonic-gate } 44107c478bd9Sstevel@tonic-gate 44117c478bd9Sstevel@tonic-gate arq_cmd = PKT2CMD(scsi_init_pkt(ap, NULL, bp, CDB_GROUP0, 1, 44127c478bd9Sstevel@tonic-gate PKT_PRIV_LEN, PKT_CONSISTENT, SLEEP_FUNC, NULL)); 44137c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 44147c478bd9Sstevel@tonic-gate 44157c478bd9Sstevel@tonic-gate RQ_MAKECOM_G0(arq_cmd->cmd_pkt, 44167c478bd9Sstevel@tonic-gate FLAG_SENSING | FLAG_HEAD | FLAG_NODISCON, 44177c478bd9Sstevel@tonic-gate (char)SCMD_REQUEST_SENSE, 0, (char)SENSE_LENGTH); 44187c478bd9Sstevel@tonic-gate 44197c478bd9Sstevel@tonic-gate arq_cmd->cmd_pkt->pkt_ha_private = arq_cmd; 44207c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_arq_cmd = arq_cmd; 44217c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_arq_bp = bp; 44227c478bd9Sstevel@tonic-gate arq_cmd->cmd_pkt->pkt_comp = NULL; 44237c478bd9Sstevel@tonic-gate bzero(bp->b_un.b_addr, SENSE_LENGTH); 44247c478bd9Sstevel@tonic-gate 44257c478bd9Sstevel@tonic-gate return (USB_SUCCESS); 44267c478bd9Sstevel@tonic-gate } 44277c478bd9Sstevel@tonic-gate 44287c478bd9Sstevel@tonic-gate 44297c478bd9Sstevel@tonic-gate /* 44307c478bd9Sstevel@tonic-gate * scsa2usb_delete_arq_pkt: 44317c478bd9Sstevel@tonic-gate * Destroy the ARQ packet 44327c478bd9Sstevel@tonic-gate */ 44337c478bd9Sstevel@tonic-gate static void 44347c478bd9Sstevel@tonic-gate scsa2usb_delete_arq_pkt(scsa2usb_state_t *scsa2usbp) 44357c478bd9Sstevel@tonic-gate { 44367c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 4437112116d8Sfb209375 "scsa2usb_delete_arq_pkt: cmd: 0x%p", 4438112116d8Sfb209375 (void *)scsa2usbp->scsa2usb_arq_cmd); 44397c478bd9Sstevel@tonic-gate 44407c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 44417c478bd9Sstevel@tonic-gate 44427c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_arq_cmd != NULL) { 44437c478bd9Sstevel@tonic-gate scsi_destroy_pkt(scsa2usbp->scsa2usb_arq_cmd->cmd_pkt); 44447c478bd9Sstevel@tonic-gate scsi_free_consistent_buf(scsa2usbp->scsa2usb_arq_bp); 44457c478bd9Sstevel@tonic-gate } 44467c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_arq_cmd = NULL; 44477c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_arq_bp = NULL; 44487c478bd9Sstevel@tonic-gate } 44497c478bd9Sstevel@tonic-gate 44507c478bd9Sstevel@tonic-gate 44517c478bd9Sstevel@tonic-gate /* 44527c478bd9Sstevel@tonic-gate * scsa2usb_complete_arq_pkt: 44537c478bd9Sstevel@tonic-gate * finish processing the arq packet 44547c478bd9Sstevel@tonic-gate */ 44557c478bd9Sstevel@tonic-gate static void 44567c478bd9Sstevel@tonic-gate scsa2usb_complete_arq_pkt(scsa2usb_state_t *scsa2usbp, 44577c478bd9Sstevel@tonic-gate struct scsi_pkt *pkt, scsa2usb_cmd_t *ssp, struct buf *bp) 44587c478bd9Sstevel@tonic-gate { 44597c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *sp = pkt->pkt_ha_private; 44607c478bd9Sstevel@tonic-gate struct scsi_arq_status *arqp; 44617c478bd9Sstevel@tonic-gate 44627c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 44637c478bd9Sstevel@tonic-gate 44647c478bd9Sstevel@tonic-gate arqp = (struct scsi_arq_status *)(ssp->cmd_pkt->pkt_scbp); 44657c478bd9Sstevel@tonic-gate arqp->sts_rqpkt_status = *((struct scsi_status *) 44667c478bd9Sstevel@tonic-gate (sp->cmd_pkt->pkt_scbp)); 44677c478bd9Sstevel@tonic-gate arqp->sts_rqpkt_reason = CMD_CMPLT; 44687c478bd9Sstevel@tonic-gate arqp->sts_rqpkt_state |= STATE_XFERRED_DATA; 44697c478bd9Sstevel@tonic-gate arqp->sts_rqpkt_statistics = arqp->sts_rqpkt_resid = 0; 44707c478bd9Sstevel@tonic-gate 44717c478bd9Sstevel@tonic-gate /* is this meaningful sense data */ 44727c478bd9Sstevel@tonic-gate if (*(bp->b_un.b_addr) != 0) { 4473fae6130aSlh195018 bcopy(bp->b_un.b_addr, &arqp->sts_sensedata, SENSE_LENGTH); 44747c478bd9Sstevel@tonic-gate ssp->cmd_pkt->pkt_state |= STATE_ARQ_DONE; 44757c478bd9Sstevel@tonic-gate } 44767c478bd9Sstevel@tonic-gate 44777c478bd9Sstevel@tonic-gate /* we will not sense start cmd until we receive a NOT READY */ 44787c478bd9Sstevel@tonic-gate if (arqp->sts_sensedata.es_key == KEY_NOT_READY) { 44797c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_rcvd_not_ready = B_TRUE; 44807c478bd9Sstevel@tonic-gate } 44817c478bd9Sstevel@tonic-gate } 44827c478bd9Sstevel@tonic-gate 44837c478bd9Sstevel@tonic-gate 44847c478bd9Sstevel@tonic-gate /* 44857c478bd9Sstevel@tonic-gate * Miscellaneous functions for any command/transport 44867c478bd9Sstevel@tonic-gate */ 44877c478bd9Sstevel@tonic-gate /* 44887c478bd9Sstevel@tonic-gate * scsa2usb_open_usb_pipes: 44897c478bd9Sstevel@tonic-gate * set up a pipe policy 44907c478bd9Sstevel@tonic-gate * open usb bulk pipes (BO and CB/CBI) 44917c478bd9Sstevel@tonic-gate * open usb interrupt pipe (CBI) 44927c478bd9Sstevel@tonic-gate */ 44937c478bd9Sstevel@tonic-gate static int 44947c478bd9Sstevel@tonic-gate scsa2usb_open_usb_pipes(scsa2usb_state_t *scsa2usbp) 44957c478bd9Sstevel@tonic-gate { 44967c478bd9Sstevel@tonic-gate int rval; 44977c478bd9Sstevel@tonic-gate usb_pipe_policy_t policy; /* bulk pipe policy */ 44987c478bd9Sstevel@tonic-gate size_t sz; 44997c478bd9Sstevel@tonic-gate 45007c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp); 45017c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 45027c478bd9Sstevel@tonic-gate 45037c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 45047c478bd9Sstevel@tonic-gate "scsa2usb_open_usb_pipes: dip = 0x%p flag = 0x%x", 4505112116d8Sfb209375 (void *)scsa2usbp->scsa2usb_dip, scsa2usbp->scsa2usb_flags); 45067c478bd9Sstevel@tonic-gate 45077c478bd9Sstevel@tonic-gate if (!(scsa2usbp->scsa2usb_flags & SCSA2USB_FLAGS_PIPES_OPENED)) { 45087c478bd9Sstevel@tonic-gate 45097c478bd9Sstevel@tonic-gate /* 45107c478bd9Sstevel@tonic-gate * one pipe policy for all bulk pipes 45117c478bd9Sstevel@tonic-gate */ 45127c478bd9Sstevel@tonic-gate bzero(&policy, sizeof (usb_pipe_policy_t)); 45137c478bd9Sstevel@tonic-gate /* at least 2, for the normal and exceptional callbacks */ 45147c478bd9Sstevel@tonic-gate policy.pp_max_async_reqs = 1; 45157c478bd9Sstevel@tonic-gate 45167c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 45177c478bd9Sstevel@tonic-gate "scsa2usb_open_usb_pipes: opening bulk pipes"); 45187c478bd9Sstevel@tonic-gate 45197c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 45207c478bd9Sstevel@tonic-gate 45217c478bd9Sstevel@tonic-gate /* Open the USB bulk-in pipe */ 45227c478bd9Sstevel@tonic-gate if ((rval = usb_pipe_open(scsa2usbp->scsa2usb_dip, 45237c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_bulkin_ept, &policy, USB_FLAGS_SLEEP, 45247c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_bulkin_pipe)) != USB_SUCCESS) { 45257c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 45267c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 45277c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 45287c478bd9Sstevel@tonic-gate "scsa2usb_open_usb_pipes: bulk/in pipe open " 45297c478bd9Sstevel@tonic-gate " failed rval = %d", rval); 45307c478bd9Sstevel@tonic-gate 45317c478bd9Sstevel@tonic-gate return (USB_FAILURE); 45327c478bd9Sstevel@tonic-gate } 45337c478bd9Sstevel@tonic-gate 45347c478bd9Sstevel@tonic-gate /* Open the bulk-out pipe using the same policy */ 45357c478bd9Sstevel@tonic-gate if ((rval = usb_pipe_open(scsa2usbp->scsa2usb_dip, 45367c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_bulkout_ept, &policy, USB_FLAGS_SLEEP, 45377c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_bulkout_pipe)) != USB_SUCCESS) { 45387c478bd9Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 45397c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, 45407c478bd9Sstevel@tonic-gate USB_FLAGS_SLEEP, NULL, NULL); 45417c478bd9Sstevel@tonic-gate 45427c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 45437c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe = NULL; 45447c478bd9Sstevel@tonic-gate 45457c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 45467c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 45477c478bd9Sstevel@tonic-gate "scsa2usb_open_usb_pipes: bulk/out pipe open" 45487c478bd9Sstevel@tonic-gate " failed rval = %d", rval); 45497c478bd9Sstevel@tonic-gate 45507c478bd9Sstevel@tonic-gate return (USB_FAILURE); 45517c478bd9Sstevel@tonic-gate } 45527c478bd9Sstevel@tonic-gate 45537c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 45547c478bd9Sstevel@tonic-gate 45557c478bd9Sstevel@tonic-gate /* open interrupt pipe for CBI protocol */ 45567c478bd9Sstevel@tonic-gate if (SCSA2USB_IS_CBI(scsa2usbp)) { 45577c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 45587c478bd9Sstevel@tonic-gate 45597c478bd9Sstevel@tonic-gate if ((rval = usb_pipe_open(scsa2usbp->scsa2usb_dip, 45607c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_intr_ept, &policy, 45617c478bd9Sstevel@tonic-gate USB_FLAGS_SLEEP, &scsa2usbp->scsa2usb_intr_pipe)) != 45627c478bd9Sstevel@tonic-gate USB_SUCCESS) { 45637c478bd9Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 45647c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, 45657c478bd9Sstevel@tonic-gate USB_FLAGS_SLEEP, NULL, NULL); 45667c478bd9Sstevel@tonic-gate 45677c478bd9Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 45687c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkout_pipe, 45697c478bd9Sstevel@tonic-gate USB_FLAGS_SLEEP, NULL, NULL); 45707c478bd9Sstevel@tonic-gate 45717c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 45727c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe = NULL; 45737c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkout_pipe = NULL; 45747c478bd9Sstevel@tonic-gate 45757c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 45767c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 45777c478bd9Sstevel@tonic-gate "scsa2usb_open_usb_pipes: intr pipe open" 45787c478bd9Sstevel@tonic-gate " failed rval = %d", rval); 45797c478bd9Sstevel@tonic-gate 45807c478bd9Sstevel@tonic-gate return (USB_FAILURE); 45817c478bd9Sstevel@tonic-gate } 45827c478bd9Sstevel@tonic-gate 45837c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 45847c478bd9Sstevel@tonic-gate } 45857c478bd9Sstevel@tonic-gate 45867c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 45877c478bd9Sstevel@tonic-gate 45887c478bd9Sstevel@tonic-gate /* get the max transfer size of the bulk pipe */ 45897c478bd9Sstevel@tonic-gate if (usb_pipe_get_max_bulk_transfer_size(scsa2usbp->scsa2usb_dip, 45907c478bd9Sstevel@tonic-gate &sz) == USB_SUCCESS) { 45917c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 45927c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_max_bulk_xfer_size = sz; 45937c478bd9Sstevel@tonic-gate } else { 45947c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 45957c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_max_bulk_xfer_size = DEV_BSIZE; 45967c478bd9Sstevel@tonic-gate } 45977c478bd9Sstevel@tonic-gate 45987c478bd9Sstevel@tonic-gate /* limit the xfer size */ 45997c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_max_bulk_xfer_size = min( 46007c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_max_bulk_xfer_size, 46017c478bd9Sstevel@tonic-gate scsa2usb_max_bulk_xfer_size); 46027c478bd9Sstevel@tonic-gate 46037c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 46047c478bd9Sstevel@tonic-gate "scsa2usb_open_usb_pipes: max bulk transfer size = %lx", 46057c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_max_bulk_xfer_size); 46067c478bd9Sstevel@tonic-gate 46077c478bd9Sstevel@tonic-gate /* Set the pipes opened flag */ 46087c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_flags |= SCSA2USB_FLAGS_PIPES_OPENED; 46097c478bd9Sstevel@tonic-gate 46107c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_NORMAL; 46117c478bd9Sstevel@tonic-gate 46127c478bd9Sstevel@tonic-gate /* Set the state to NONE */ 46137c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_NONE; 46147c478bd9Sstevel@tonic-gate } 46157c478bd9Sstevel@tonic-gate 46167c478bd9Sstevel@tonic-gate return (USB_SUCCESS); 46177c478bd9Sstevel@tonic-gate } 46187c478bd9Sstevel@tonic-gate 46197c478bd9Sstevel@tonic-gate 46207c478bd9Sstevel@tonic-gate /* 46217c478bd9Sstevel@tonic-gate * scsa2usb_close_usb_pipes: 46227c478bd9Sstevel@tonic-gate * close all pipes synchronously 46237c478bd9Sstevel@tonic-gate */ 46247c478bd9Sstevel@tonic-gate void 46257c478bd9Sstevel@tonic-gate scsa2usb_close_usb_pipes(scsa2usb_state_t *scsa2usbp) 46267c478bd9Sstevel@tonic-gate { 46277c478bd9Sstevel@tonic-gate usb_flags_t flags = USB_FLAGS_SLEEP; 46287c478bd9Sstevel@tonic-gate 46297c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 4630112116d8Sfb209375 "scsa2usb_close_usb_pipes: scsa2usb_state = 0x%p", 4631112116d8Sfb209375 (void *)scsa2usbp); 46327c478bd9Sstevel@tonic-gate 46337c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp); 46347c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 46357c478bd9Sstevel@tonic-gate 46367c478bd9Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_flags & SCSA2USB_FLAGS_PIPES_OPENED) == 0) { 46377c478bd9Sstevel@tonic-gate 46387c478bd9Sstevel@tonic-gate return; 46397c478bd9Sstevel@tonic-gate } 46407c478bd9Sstevel@tonic-gate 46417c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_CLOSING; 46427c478bd9Sstevel@tonic-gate /* to avoid races, reset the flag first */ 46437c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_flags &= ~SCSA2USB_FLAGS_PIPES_OPENED; 46447c478bd9Sstevel@tonic-gate 46457c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 46467c478bd9Sstevel@tonic-gate 46477c478bd9Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 46487c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkout_pipe, flags, NULL, NULL); 46497c478bd9Sstevel@tonic-gate 46507c478bd9Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 46517c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, flags, NULL, NULL); 46527c478bd9Sstevel@tonic-gate 46537c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 46547c478bd9Sstevel@tonic-gate if (SCSA2USB_IS_CBI(scsa2usbp)) { 46557c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 46567c478bd9Sstevel@tonic-gate usb_pipe_close(scsa2usbp->scsa2usb_dip, 46577c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_intr_pipe, flags, NULL, NULL); 46587c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 46597c478bd9Sstevel@tonic-gate } 46607c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkout_pipe = NULL; 46617c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe = NULL; 46627c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_intr_pipe = NULL; 46637c478bd9Sstevel@tonic-gate 46647c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_NORMAL; 46657c478bd9Sstevel@tonic-gate } 46667c478bd9Sstevel@tonic-gate 46677c478bd9Sstevel@tonic-gate 46687c478bd9Sstevel@tonic-gate /* 46697c478bd9Sstevel@tonic-gate * scsa2usb_fill_up_cdb_lba: 46707c478bd9Sstevel@tonic-gate * fill up command CDBs' LBA part 46717c478bd9Sstevel@tonic-gate */ 46727c478bd9Sstevel@tonic-gate static void 46737c478bd9Sstevel@tonic-gate scsa2usb_fill_up_cdb_lba(scsa2usb_cmd_t *cmd, int lba) 46747c478bd9Sstevel@tonic-gate { 46757c478bd9Sstevel@tonic-gate /* zero cdb1, lba bits so they won't get copied in the new cdb */ 46767c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LUN] &= 0xE0; 46777c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_0] = lba >> 24; 46787c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_1] = lba >> 16; 46797c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_2] = lba >> 8; 46807c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LBA_3] = (uchar_t)lba; 46817c478bd9Sstevel@tonic-gate cmd->cmd_lba = lba; 46827c478bd9Sstevel@tonic-gate } 46837c478bd9Sstevel@tonic-gate 46847c478bd9Sstevel@tonic-gate 46857c478bd9Sstevel@tonic-gate /* 46867c478bd9Sstevel@tonic-gate * scsa2usb_fill_up_ReadCD_cdb_len: 46877c478bd9Sstevel@tonic-gate * fill up READ_CD command CDBs' len part 46887c478bd9Sstevel@tonic-gate */ 46897c478bd9Sstevel@tonic-gate static void 46907c478bd9Sstevel@tonic-gate scsa2usb_fill_up_ReadCD_cdb_len(scsa2usb_cmd_t *cmd, int len, int actual_len) 46917c478bd9Sstevel@tonic-gate { 46927c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_0] = len >> 16; 46937c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_1] = len >> 8; 46947c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_READ_CD_LEN_2] = (uchar_t)len; 46957c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = (uchar_t)actual_len; 46967c478bd9Sstevel@tonic-gate } 46977c478bd9Sstevel@tonic-gate 46987c478bd9Sstevel@tonic-gate 46997c478bd9Sstevel@tonic-gate /* 47007c478bd9Sstevel@tonic-gate * scsa2usb_fill_up_12byte_cdb_len: 47017c478bd9Sstevel@tonic-gate * fill up generic 12-byte command CDBs' len part 47027c478bd9Sstevel@tonic-gate */ 47037c478bd9Sstevel@tonic-gate static void 47047c478bd9Sstevel@tonic-gate scsa2usb_fill_up_12byte_cdb_len(scsa2usb_cmd_t *cmd, int len, int actual_len) 47057c478bd9Sstevel@tonic-gate { 47067c478bd9Sstevel@tonic-gate cmd->cmd_cdb[6] = len >> 24; 47077c478bd9Sstevel@tonic-gate cmd->cmd_cdb[7] = len >> 16; 47087c478bd9Sstevel@tonic-gate cmd->cmd_cdb[8] = len >> 8; 47097c478bd9Sstevel@tonic-gate cmd->cmd_cdb[9] = (uchar_t)len; 47107c478bd9Sstevel@tonic-gate cmd->cmd_actual_len = (uchar_t)actual_len; 47117c478bd9Sstevel@tonic-gate } 47127c478bd9Sstevel@tonic-gate 47137c478bd9Sstevel@tonic-gate 47147c478bd9Sstevel@tonic-gate /* 47157c478bd9Sstevel@tonic-gate * scsa2usb_fill_up_cdb_len: 47167c478bd9Sstevel@tonic-gate * fill up generic 10-byte command CDBs' len part 47177c478bd9Sstevel@tonic-gate */ 47187c478bd9Sstevel@tonic-gate static void 47197c478bd9Sstevel@tonic-gate scsa2usb_fill_up_cdb_len(scsa2usb_cmd_t *cmd, int len) 47207c478bd9Sstevel@tonic-gate { 47217c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LEN_0] = len >> 8; 47227c478bd9Sstevel@tonic-gate cmd->cmd_cdb[SCSA2USB_LEN_1] = (uchar_t)len; 47237c478bd9Sstevel@tonic-gate } 47247c478bd9Sstevel@tonic-gate 47257c478bd9Sstevel@tonic-gate 47267c478bd9Sstevel@tonic-gate /* 47277c478bd9Sstevel@tonic-gate * scsa2usb_read_cd_blk_size: 47287c478bd9Sstevel@tonic-gate * For SCMD_READ_CD opcode (0xbe). Figure out the 47297c478bd9Sstevel@tonic-gate * block size based on expected sector type field 47307c478bd9Sstevel@tonic-gate * definition. See MMC SCSI Specs section 6.1.15 47317c478bd9Sstevel@tonic-gate * 47327c478bd9Sstevel@tonic-gate * Based on the value of the "expected_sector_type" 47337c478bd9Sstevel@tonic-gate * field, the block size could be different. 47347c478bd9Sstevel@tonic-gate */ 47357c478bd9Sstevel@tonic-gate static int 47367c478bd9Sstevel@tonic-gate scsa2usb_read_cd_blk_size(uchar_t expected_sector_type) 47377c478bd9Sstevel@tonic-gate { 47387c478bd9Sstevel@tonic-gate int blk_size; 47397c478bd9Sstevel@tonic-gate 47407c478bd9Sstevel@tonic-gate switch (expected_sector_type) { 47417c478bd9Sstevel@tonic-gate case READ_CD_EST_CDDA: 47427c478bd9Sstevel@tonic-gate blk_size = CDROM_BLK_2352; 47437c478bd9Sstevel@tonic-gate break; 47447c478bd9Sstevel@tonic-gate case READ_CD_EST_MODE2: 47457c478bd9Sstevel@tonic-gate blk_size = CDROM_BLK_2336; 47467c478bd9Sstevel@tonic-gate break; 47477c478bd9Sstevel@tonic-gate case READ_CD_EST_MODE2FORM2: 47487c478bd9Sstevel@tonic-gate blk_size = CDROM_BLK_2324; 47497c478bd9Sstevel@tonic-gate break; 47507c478bd9Sstevel@tonic-gate case READ_CD_EST_MODE2FORM1: 47517c478bd9Sstevel@tonic-gate case READ_CD_EST_ALLTYPE: 47527c478bd9Sstevel@tonic-gate case READ_CD_EST_MODE1: 47537c478bd9Sstevel@tonic-gate default: 47547c478bd9Sstevel@tonic-gate blk_size = CDROM_BLK_2048; 47557c478bd9Sstevel@tonic-gate } 47567c478bd9Sstevel@tonic-gate 47577c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, NULL, "scsa2usb_read_cd_blk_size: " 47587c478bd9Sstevel@tonic-gate "est = 0x%x blk_size = %d", expected_sector_type, blk_size); 47597c478bd9Sstevel@tonic-gate 47607c478bd9Sstevel@tonic-gate return (blk_size); 47617c478bd9Sstevel@tonic-gate } 47627c478bd9Sstevel@tonic-gate 47637c478bd9Sstevel@tonic-gate 47647c478bd9Sstevel@tonic-gate /* 47657c478bd9Sstevel@tonic-gate * scsa2usb_bp_to_mblk: 47667c478bd9Sstevel@tonic-gate * Convert a bp to mblk_t. USBA framework understands mblk_t. 47677c478bd9Sstevel@tonic-gate */ 47687c478bd9Sstevel@tonic-gate static mblk_t * 47697c478bd9Sstevel@tonic-gate scsa2usb_bp_to_mblk(scsa2usb_state_t *scsa2usbp) 47707c478bd9Sstevel@tonic-gate { 47717c478bd9Sstevel@tonic-gate size_t size; 47727c478bd9Sstevel@tonic-gate mblk_t *mp; 47737c478bd9Sstevel@tonic-gate struct buf *bp; 47747c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd = PKT2CMD(scsa2usbp->scsa2usb_cur_pkt); 47757c478bd9Sstevel@tonic-gate 47767c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 47777c478bd9Sstevel@tonic-gate "scsa2usb_bp_to_mblk: "); 47787c478bd9Sstevel@tonic-gate 47797c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_cur_pkt); 47807c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 47817c478bd9Sstevel@tonic-gate 47827c478bd9Sstevel@tonic-gate bp = cmd->cmd_bp; 47837c478bd9Sstevel@tonic-gate 47847c478bd9Sstevel@tonic-gate if (bp && (bp->b_bcount > 0)) { 47857c478bd9Sstevel@tonic-gate size = ((bp->b_bcount > cmd->cmd_xfercount) ? 47867c478bd9Sstevel@tonic-gate cmd->cmd_xfercount : bp->b_bcount); 47877c478bd9Sstevel@tonic-gate } else { 47887c478bd9Sstevel@tonic-gate 47897c478bd9Sstevel@tonic-gate return (NULL); 47907c478bd9Sstevel@tonic-gate } 47917c478bd9Sstevel@tonic-gate 47927c478bd9Sstevel@tonic-gate mp = esballoc_wait((uchar_t *)bp->b_un.b_addr + cmd->cmd_offset, 47935bb8b905Szl227052 size, BPRI_LO, &frnop); 47947c478bd9Sstevel@tonic-gate 47957c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 47967c478bd9Sstevel@tonic-gate "scsa2usb_bp_to_mblk: " 4797112116d8Sfb209375 "mp=0x%p bp=0x%p pkt=0x%p off=0x%lx sz=%lu add=0x%p", 4798112116d8Sfb209375 (void *)mp, (void *)bp, (void *)scsa2usbp->scsa2usb_cur_pkt, 4799112116d8Sfb209375 cmd->cmd_offset, bp->b_bcount - cmd->cmd_offset, 4800112116d8Sfb209375 (void *)bp->b_un.b_addr); 48017c478bd9Sstevel@tonic-gate 48027c478bd9Sstevel@tonic-gate mp->b_wptr += size; 48037c478bd9Sstevel@tonic-gate cmd->cmd_offset += size; 48047c478bd9Sstevel@tonic-gate 48057c478bd9Sstevel@tonic-gate return (mp); 48067c478bd9Sstevel@tonic-gate } 48077c478bd9Sstevel@tonic-gate 48087c478bd9Sstevel@tonic-gate 48097c478bd9Sstevel@tonic-gate /* 48107c478bd9Sstevel@tonic-gate * scsa2usb_handle_data_start: 48117c478bd9Sstevel@tonic-gate * Initiate the data xfer. It could be IN/OUT direction. 48127c478bd9Sstevel@tonic-gate * 48137c478bd9Sstevel@tonic-gate * Data IN: 48147c478bd9Sstevel@tonic-gate * Send out the bulk-xfer request 48157c478bd9Sstevel@tonic-gate * if rval implies STALL 48167c478bd9Sstevel@tonic-gate * clear endpoint stall and reset bulk-in pipe 48177c478bd9Sstevel@tonic-gate * handle data read in so far; set cmd->cmd_done 48187c478bd9Sstevel@tonic-gate * also adjust data xfer length accordingly 48197c478bd9Sstevel@tonic-gate * else other error 48207c478bd9Sstevel@tonic-gate * report back to transport 48217c478bd9Sstevel@tonic-gate * typically transport will call reset recovery 48227c478bd9Sstevel@tonic-gate * else (no error) 48237c478bd9Sstevel@tonic-gate * return success 48247c478bd9Sstevel@tonic-gate * 48257c478bd9Sstevel@tonic-gate * Data OUT: 48267c478bd9Sstevel@tonic-gate * Send out the bulk-xfer request 48277c478bd9Sstevel@tonic-gate * if rval implies STALL 48287c478bd9Sstevel@tonic-gate * clear endpoint stall and reset bulk-in pipe 48297c478bd9Sstevel@tonic-gate * adjust data xfer length 48307c478bd9Sstevel@tonic-gate * else other error 48317c478bd9Sstevel@tonic-gate * report back to transport 48327c478bd9Sstevel@tonic-gate * typically transport will call reset recovery 48337c478bd9Sstevel@tonic-gate * else (no error) 48347c478bd9Sstevel@tonic-gate * return success 48357c478bd9Sstevel@tonic-gate * 48367c478bd9Sstevel@tonic-gate * NOTE: We call this function only if there is xfercount. 48377c478bd9Sstevel@tonic-gate */ 48387c478bd9Sstevel@tonic-gate int 48397c478bd9Sstevel@tonic-gate scsa2usb_handle_data_start(scsa2usb_state_t *scsa2usbp, 48407c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd, usb_bulk_req_t *req) 48417c478bd9Sstevel@tonic-gate { 48427c478bd9Sstevel@tonic-gate int rval = USB_SUCCESS; 48437c478bd9Sstevel@tonic-gate uint_t ept_addr; 48447c478bd9Sstevel@tonic-gate usb_flags_t flags = USB_FLAGS_SLEEP; 48457c478bd9Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 48467c478bd9Sstevel@tonic-gate usb_req_attrs_t attrs = 0; 48477c478bd9Sstevel@tonic-gate #else 48487c478bd9Sstevel@tonic-gate usb_req_attrs_t attrs = USB_ATTRS_SHORT_XFER_OK; 48497c478bd9Sstevel@tonic-gate #endif 48507c478bd9Sstevel@tonic-gate 48517c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 4852112116d8Sfb209375 "scsa2usb_handle_data_start: BEGIN cmd = %p, req = %p", 4853112116d8Sfb209375 (void *)cmd, (void *)req); 48547c478bd9Sstevel@tonic-gate 48557c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 48567c478bd9Sstevel@tonic-gate 48577c478bd9Sstevel@tonic-gate switch (cmd->cmd_dir) { 48587c478bd9Sstevel@tonic-gate case USB_EP_DIR_IN: 48597c478bd9Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 48607c478bd9Sstevel@tonic-gate /* 48617c478bd9Sstevel@tonic-gate * This case occurs when the host expects to receive 48627c478bd9Sstevel@tonic-gate * more data than the device actually transfers. Hi > Di 48637c478bd9Sstevel@tonic-gate */ 48647c478bd9Sstevel@tonic-gate if (scsa2usb_test_case_5) { 48657c478bd9Sstevel@tonic-gate usb_bulk_req_t *req2; 48667c478bd9Sstevel@tonic-gate 48677c478bd9Sstevel@tonic-gate req->bulk_len = cmd->cmd_xfercount - 1; 48687c478bd9Sstevel@tonic-gate req->bulk_attributes = 0; 48697c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 48707c478bd9Sstevel@tonic-gate SCSA2USB_FREE_MSG(req->bulk_data); 48717c478bd9Sstevel@tonic-gate req->bulk_data = allocb_wait(req->bulk_len, BPRI_LO, 48727c478bd9Sstevel@tonic-gate STR_NOSIG, NULL); 48737c478bd9Sstevel@tonic-gate 48747c478bd9Sstevel@tonic-gate ASSERT(req->bulk_timeout); 48757c478bd9Sstevel@tonic-gate rval = usb_pipe_bulk_xfer( 48767c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, req, flags); 48777c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 48787c478bd9Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, 48797c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, "rval = %x", rval); 48807c478bd9Sstevel@tonic-gate 48817c478bd9Sstevel@tonic-gate req2 = scsa2usb_init_bulk_req(scsa2usbp, 48827c478bd9Sstevel@tonic-gate cmd->cmd_xfercount + 2, 48837c478bd9Sstevel@tonic-gate cmd->cmd_timeout, 0, flags); 48847c478bd9Sstevel@tonic-gate req2->bulk_len = cmd->cmd_xfercount + 2; 48857c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 48867c478bd9Sstevel@tonic-gate 48877c478bd9Sstevel@tonic-gate ASSERT(req2->bulk_timeout); 48887c478bd9Sstevel@tonic-gate rval = usb_pipe_bulk_xfer( 48897c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, req2, flags); 48907c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 48917c478bd9Sstevel@tonic-gate 48927c478bd9Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, 48937c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 48947c478bd9Sstevel@tonic-gate "TEST 5: Hi > Di: rval = 0x%x", rval); 48957c478bd9Sstevel@tonic-gate scsa2usb_test_case_5 = 0; 48967c478bd9Sstevel@tonic-gate usb_free_bulk_req(req2); 48977c478bd9Sstevel@tonic-gate 48987c478bd9Sstevel@tonic-gate return (rval); 48997c478bd9Sstevel@tonic-gate } 49007c478bd9Sstevel@tonic-gate 49017c478bd9Sstevel@tonic-gate /* 49027c478bd9Sstevel@tonic-gate * This happens when the host expects to send data to the 49037c478bd9Sstevel@tonic-gate * device while the device intends to send data to the host. 49047c478bd9Sstevel@tonic-gate */ 49057c478bd9Sstevel@tonic-gate if (scsa2usb_test_case_8 && (cmd->cmd_cdb[0] == SCMD_READ_G1)) { 49067c478bd9Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, 49077c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 49087c478bd9Sstevel@tonic-gate "TEST 8: Hi <> Do: Step 2"); 49097c478bd9Sstevel@tonic-gate scsa2usb_test_mblk(scsa2usbp, B_TRUE); 49107c478bd9Sstevel@tonic-gate scsa2usb_test_case_8 = 0; 49117c478bd9Sstevel@tonic-gate 49127c478bd9Sstevel@tonic-gate return (rval); 49137c478bd9Sstevel@tonic-gate } 49147c478bd9Sstevel@tonic-gate #endif /* SCSA2USB_BULK_ONLY_TEST */ 49157c478bd9Sstevel@tonic-gate 49167c478bd9Sstevel@tonic-gate ept_addr = scsa2usbp->scsa2usb_bulkin_ept.bEndpointAddress; 49177c478bd9Sstevel@tonic-gate req->bulk_len = cmd->cmd_xfercount; 49187c478bd9Sstevel@tonic-gate req->bulk_attributes = attrs; 49197c478bd9Sstevel@tonic-gate SCSA2USB_FREE_MSG(req->bulk_data); 49207c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 49217c478bd9Sstevel@tonic-gate 49227c478bd9Sstevel@tonic-gate req->bulk_data = esballoc_wait( 49237c478bd9Sstevel@tonic-gate (uchar_t *)cmd->cmd_bp->b_un.b_addr + 49247c478bd9Sstevel@tonic-gate cmd->cmd_offset, 49255bb8b905Szl227052 req->bulk_len, BPRI_LO, &frnop); 49267c478bd9Sstevel@tonic-gate 49277c478bd9Sstevel@tonic-gate ASSERT(req->bulk_timeout); 49287c478bd9Sstevel@tonic-gate rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkin_pipe, 49297c478bd9Sstevel@tonic-gate req, flags); 49307c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 49317c478bd9Sstevel@tonic-gate 49327c478bd9Sstevel@tonic-gate break; 49337c478bd9Sstevel@tonic-gate 49347c478bd9Sstevel@tonic-gate case USB_EP_DIR_OUT: 49357c478bd9Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 49367c478bd9Sstevel@tonic-gate /* 49377c478bd9Sstevel@tonic-gate * This happens when the host expects to receive data 49387c478bd9Sstevel@tonic-gate * from the device while the device intends to receive 49397c478bd9Sstevel@tonic-gate * data from the host. 49407c478bd9Sstevel@tonic-gate */ 49417c478bd9Sstevel@tonic-gate if (scsa2usb_test_case_10 && 49427c478bd9Sstevel@tonic-gate (cmd->cmd_cdb[0] == SCMD_WRITE_G1)) { 49437c478bd9Sstevel@tonic-gate req->bulk_len = CSW_LEN; 49447c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 49457c478bd9Sstevel@tonic-gate 49467c478bd9Sstevel@tonic-gate ASSERT(req->bulk_timeout); 49477c478bd9Sstevel@tonic-gate rval = usb_pipe_bulk_xfer( 49487c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_bulkin_pipe, req, flags); 49497c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 49507c478bd9Sstevel@tonic-gate 49517c478bd9Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, 49527c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 49537c478bd9Sstevel@tonic-gate "TEST 10: Ho <> Di: done rval = 0x%x", rval); 49547c478bd9Sstevel@tonic-gate scsa2usb_test_case_10 = 0; 49557c478bd9Sstevel@tonic-gate 49567c478bd9Sstevel@tonic-gate return (rval); 49577c478bd9Sstevel@tonic-gate } 49587c478bd9Sstevel@tonic-gate #endif /* SCSA2USB_BULK_ONLY_TEST */ 49597c478bd9Sstevel@tonic-gate 49607c478bd9Sstevel@tonic-gate req->bulk_data = scsa2usb_bp_to_mblk(scsa2usbp); 49617c478bd9Sstevel@tonic-gate if (req->bulk_data == NULL) { 49627c478bd9Sstevel@tonic-gate 49637c478bd9Sstevel@tonic-gate return (USB_FAILURE); 49647c478bd9Sstevel@tonic-gate } 49657c478bd9Sstevel@tonic-gate 49667c478bd9Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 49677c478bd9Sstevel@tonic-gate if (scsa2usb_test_case_11) { 49687c478bd9Sstevel@tonic-gate /* 49697c478bd9Sstevel@tonic-gate * Host expects to send data to the device and 49707c478bd9Sstevel@tonic-gate * device doesn't expect to receive any data 49717c478bd9Sstevel@tonic-gate */ 49727c478bd9Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, 49737c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, "TEST 11: Ho > Do"); 49747c478bd9Sstevel@tonic-gate 49757c478bd9Sstevel@tonic-gate scsa2usb_test_mblk(scsa2usbp, B_FALSE); 49767c478bd9Sstevel@tonic-gate scsa2usb_test_case_11 = 0; 49777c478bd9Sstevel@tonic-gate } 49787c478bd9Sstevel@tonic-gate #endif /* SCSA2USB_BULK_ONLY_TEST */ 49797c478bd9Sstevel@tonic-gate 49807c478bd9Sstevel@tonic-gate ept_addr = scsa2usbp->scsa2usb_bulkout_ept.bEndpointAddress; 4981d29f5a71Szhigang lu - Sun Microsystems - Beijing China req->bulk_len = MBLKL(req->bulk_data); 49827c478bd9Sstevel@tonic-gate req->bulk_timeout = scsa2usb_bulk_timeout(cmd->cmd_timeout); 49837c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 49847c478bd9Sstevel@tonic-gate 49857c478bd9Sstevel@tonic-gate ASSERT(req->bulk_timeout); 49867c478bd9Sstevel@tonic-gate rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkout_pipe, 49877c478bd9Sstevel@tonic-gate req, flags); 49887c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 49897c478bd9Sstevel@tonic-gate break; 49907c478bd9Sstevel@tonic-gate } 49917c478bd9Sstevel@tonic-gate 49927c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 49937c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 49947c478bd9Sstevel@tonic-gate "scsa2usb_handle_data_start: rval=%d cr=%d", rval, 49957c478bd9Sstevel@tonic-gate req->bulk_completion_reason); 49967c478bd9Sstevel@tonic-gate 49977c478bd9Sstevel@tonic-gate if (rval != USB_SUCCESS) { 49987c478bd9Sstevel@tonic-gate /* Handle Errors now */ 49997c478bd9Sstevel@tonic-gate if (req->bulk_completion_reason == USB_CR_STALL) { 50007c478bd9Sstevel@tonic-gate if (cmd->cmd_dir == USB_EP_DIR_IN) { 50017c478bd9Sstevel@tonic-gate (void) scsa2usb_clear_ept_stall( 50027c478bd9Sstevel@tonic-gate scsa2usbp, ept_addr, 50037c478bd9Sstevel@tonic-gate scsa2usbp-> scsa2usb_bulkin_pipe, 50047c478bd9Sstevel@tonic-gate "bulk-in"); 50057c478bd9Sstevel@tonic-gate } else { 50067c478bd9Sstevel@tonic-gate (void) scsa2usb_clear_ept_stall( 50077c478bd9Sstevel@tonic-gate scsa2usbp, ept_addr, 50087c478bd9Sstevel@tonic-gate scsa2usbp-> scsa2usb_bulkout_pipe, 50097c478bd9Sstevel@tonic-gate "bulk-out"); 50107c478bd9Sstevel@tonic-gate } 50117c478bd9Sstevel@tonic-gate } 50127c478bd9Sstevel@tonic-gate 50137c478bd9Sstevel@tonic-gate /* no more data to transfer after this */ 50147c478bd9Sstevel@tonic-gate cmd->cmd_done = 1; 50157c478bd9Sstevel@tonic-gate } 50167c478bd9Sstevel@tonic-gate 50177c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 50187c478bd9Sstevel@tonic-gate "scsa2usb_handle_data_start: END %s data rval = %d", 50197c478bd9Sstevel@tonic-gate (cmd->cmd_dir == USB_EP_DIR_IN) ? "bulk-in" : "bulk-out", rval); 50207c478bd9Sstevel@tonic-gate 50217c478bd9Sstevel@tonic-gate return (rval); 50227c478bd9Sstevel@tonic-gate } 50237c478bd9Sstevel@tonic-gate 50247c478bd9Sstevel@tonic-gate 50257c478bd9Sstevel@tonic-gate /* 50267c478bd9Sstevel@tonic-gate * scsa2usb_handle_data_done: 50277c478bd9Sstevel@tonic-gate * This function handles the completion of the data xfer. 50287c478bd9Sstevel@tonic-gate * It also massages the inquiry data. This function may 50297c478bd9Sstevel@tonic-gate * also be called after a stall. 50307c478bd9Sstevel@tonic-gate */ 50317c478bd9Sstevel@tonic-gate void 50327c478bd9Sstevel@tonic-gate scsa2usb_handle_data_done(scsa2usb_state_t *scsa2usbp, 50337c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd, usb_bulk_req_t *req) 50347c478bd9Sstevel@tonic-gate { 50357c478bd9Sstevel@tonic-gate struct buf *bp = cmd->cmd_bp; 50367c478bd9Sstevel@tonic-gate struct scsi_pkt *pkt = scsa2usbp->scsa2usb_cur_pkt; 50377c478bd9Sstevel@tonic-gate mblk_t *data = req->bulk_data; 5038d29f5a71Szhigang lu - Sun Microsystems - Beijing China int len = data ? MBLKL(data) : 0; 503963602c90Sfb209375 uint32_t max_lba; 50407c478bd9Sstevel@tonic-gate 50417c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 50427c478bd9Sstevel@tonic-gate 50437c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 50447c478bd9Sstevel@tonic-gate "scsa2usb_handle_data_done:\n\tcmd = 0x%p data = 0x%p len = 0x%x", 5045112116d8Sfb209375 (void *)cmd, (void *)data, len); 50467c478bd9Sstevel@tonic-gate 50477c478bd9Sstevel@tonic-gate cmd->cmd_resid_xfercount = cmd->cmd_xfercount - len; 50487c478bd9Sstevel@tonic-gate 50497c478bd9Sstevel@tonic-gate if (len) { 50507c478bd9Sstevel@tonic-gate uchar_t *p; 505172d9a10cSlg150142 uchar_t dtype; 50527c478bd9Sstevel@tonic-gate scsa2usb_read_cap_t *cap; 505372d9a10cSlg150142 struct scsi_inquiry *inq; 50547c478bd9Sstevel@tonic-gate 50557c478bd9Sstevel@tonic-gate switch (cmd->cmd_cdb[SCSA2USB_OPCODE]) { 50567c478bd9Sstevel@tonic-gate case SCMD_INQUIRY: 50577c478bd9Sstevel@tonic-gate /* 50587c478bd9Sstevel@tonic-gate * cache a copy of the inquiry data for our own use 50597c478bd9Sstevel@tonic-gate * but ensure that we have at least up to 50607c478bd9Sstevel@tonic-gate * inq_revision, inq_serial is not required. 50617c478bd9Sstevel@tonic-gate * ignore inquiry data returned for inquiry commands 50627c478bd9Sstevel@tonic-gate * with SCSI-3 EVPD, CmdDt bits set. 50637c478bd9Sstevel@tonic-gate */ 50647c478bd9Sstevel@tonic-gate if (((cmd->cmd_cdb[SCSA2USB_LUN] & 0x1f) == 0) && 50657c478bd9Sstevel@tonic-gate (len >= SCSA2USB_MAX_INQ_LEN)) { 506672d9a10cSlg150142 inq = (struct scsi_inquiry *)data->b_rptr; 506772d9a10cSlg150142 dtype = inq->inq_dtype & DTYPE_MASK; 506872d9a10cSlg150142 /* 506972d9a10cSlg150142 * scsi framework sends zero byte write(10) cmd 507072d9a10cSlg150142 * to (Simplified) direct-access devices with 507172d9a10cSlg150142 * inquiry version > 2 for reservation changes. 507272d9a10cSlg150142 * But some USB devices don't support zero byte 507372d9a10cSlg150142 * write(10) even though they have inquiry 507472d9a10cSlg150142 * version > 2. Considering scsa2usb driver 507572d9a10cSlg150142 * doesn't support reservation and all the 507672d9a10cSlg150142 * reservation cmds are being faked, we fake 507772d9a10cSlg150142 * the inquiry version to 0 to make scsi 507872d9a10cSlg150142 * framework send test unit ready cmd which is 507972d9a10cSlg150142 * supported by all the usb devices. 508072d9a10cSlg150142 */ 508172d9a10cSlg150142 if (((dtype == DTYPE_DIRECT) || 508272d9a10cSlg150142 (dtype == DTYPE_RBC)) && 508372d9a10cSlg150142 (inq->inq_ansi > 2)) { 508472d9a10cSlg150142 inq->inq_ansi = 0; 508572d9a10cSlg150142 } 508672d9a10cSlg150142 50877c478bd9Sstevel@tonic-gate bzero(&scsa2usbp->scsa2usb_lun_inquiry 50887c478bd9Sstevel@tonic-gate [pkt->pkt_address.a_lun], 50897c478bd9Sstevel@tonic-gate sizeof (struct scsi_inquiry)); 50907c478bd9Sstevel@tonic-gate bcopy(data->b_rptr, 50917c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_lun_inquiry 50927c478bd9Sstevel@tonic-gate [pkt->pkt_address.a_lun], len); 50937c478bd9Sstevel@tonic-gate } 50947c478bd9Sstevel@tonic-gate 50957c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 50967c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 50977c478bd9Sstevel@tonic-gate "scsi inquiry type = 0x%x", 50987c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_lun_inquiry 50997c478bd9Sstevel@tonic-gate [pkt->pkt_address.a_lun].inq_dtype); 51007c478bd9Sstevel@tonic-gate 51017c478bd9Sstevel@tonic-gate cmd->cmd_done = 1; 51027c478bd9Sstevel@tonic-gate goto handle_data; 51037c478bd9Sstevel@tonic-gate 51047c478bd9Sstevel@tonic-gate case SCMD_READ_CAPACITY: 51057c478bd9Sstevel@tonic-gate cap = (scsa2usb_read_cap_t *)data->b_rptr; 51067c478bd9Sstevel@tonic-gate 51077c478bd9Sstevel@tonic-gate /* Figure out the logical block size */ 51087c478bd9Sstevel@tonic-gate if ((len >= sizeof (struct scsa2usb_read_cap)) && 51097c478bd9Sstevel@tonic-gate (req->bulk_completion_reason == USB_CR_OK)) { 51107c478bd9Sstevel@tonic-gate scsa2usbp-> 51117c478bd9Sstevel@tonic-gate scsa2usb_lbasize[pkt->pkt_address.a_lun] = 51127c478bd9Sstevel@tonic-gate SCSA2USB_MK_32BIT( 51137c478bd9Sstevel@tonic-gate cap->scsa2usb_read_cap_blen3, 51147c478bd9Sstevel@tonic-gate cap->scsa2usb_read_cap_blen2, 51157c478bd9Sstevel@tonic-gate cap->scsa2usb_read_cap_blen1, 51167c478bd9Sstevel@tonic-gate cap->scsa2usb_read_cap_blen0); 51177c478bd9Sstevel@tonic-gate 511863602c90Sfb209375 max_lba = SCSA2USB_MK_32BIT( 511963602c90Sfb209375 cap->scsa2usb_read_cap_lba3, 512063602c90Sfb209375 cap->scsa2usb_read_cap_lba2, 512163602c90Sfb209375 cap->scsa2usb_read_cap_lba1, 512263602c90Sfb209375 cap->scsa2usb_read_cap_lba0); 512363602c90Sfb209375 512463602c90Sfb209375 /* 512563602c90Sfb209375 * Some devices return total logical block 512663602c90Sfb209375 * number instead of highest logical block 512763602c90Sfb209375 * address. Adjust the value by minus 1. 512863602c90Sfb209375 */ 512963602c90Sfb209375 if (max_lba > 0 && (scsa2usbp->scsa2usb_attrs & 513063602c90Sfb209375 SCSA2USB_ATTRS_NO_CAP_ADJUST) == 0) { 513163602c90Sfb209375 max_lba -= 1; 513263602c90Sfb209375 cap->scsa2usb_read_cap_lba0 = 513363602c90Sfb209375 (uchar_t)(max_lba & 0xFF); 513463602c90Sfb209375 cap->scsa2usb_read_cap_lba1 = 513563602c90Sfb209375 (uchar_t)(max_lba >> 8 & 0xFF); 513663602c90Sfb209375 cap->scsa2usb_read_cap_lba2 = 513763602c90Sfb209375 (uchar_t)(max_lba >> 16 & 0xFF); 513863602c90Sfb209375 cap->scsa2usb_read_cap_lba3 = 513963602c90Sfb209375 (uchar_t)(max_lba >> 24 & 0xFF); 514063602c90Sfb209375 } 514163602c90Sfb209375 514263602c90Sfb209375 USB_DPRINTF_L2(DPRINT_MASK_SCSA, 51437c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 5144112116d8Sfb209375 "bytes in each logical block=0x%lx," 514563602c90Sfb209375 "number of total logical blocks=0x%x", 514663602c90Sfb209375 scsa2usbp-> 514763602c90Sfb209375 scsa2usb_lbasize[pkt->pkt_address.a_lun], 514863602c90Sfb209375 max_lba + 1); 51497c478bd9Sstevel@tonic-gate } 51507c478bd9Sstevel@tonic-gate cmd->cmd_done = 1; 51517c478bd9Sstevel@tonic-gate goto handle_data; 51527c478bd9Sstevel@tonic-gate 51537c478bd9Sstevel@tonic-gate case SCMD_REQUEST_SENSE: 51547c478bd9Sstevel@tonic-gate p = data->b_rptr; 51557c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_SCSA, 51567c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 51577c478bd9Sstevel@tonic-gate "cdb: %x rqsense: " 51587c478bd9Sstevel@tonic-gate "%x %x %x %x %x %x %x %x %x %x\n\t" 51597c478bd9Sstevel@tonic-gate "%x %x %x %x %x %x %x %x %x %x", 51607c478bd9Sstevel@tonic-gate cmd->cmd_cdb[0], 51617c478bd9Sstevel@tonic-gate p[0], p[1], p[2], p[3], p[4], 51627c478bd9Sstevel@tonic-gate p[5], p[6], p[7], p[8], p[9], 51637c478bd9Sstevel@tonic-gate p[10], p[11], p[12], p[13], p[14], 51647c478bd9Sstevel@tonic-gate p[15], p[16], p[17], p[18], p[19]); 51657c478bd9Sstevel@tonic-gate 51667c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_last_cmd.status = p[2]; 51677c478bd9Sstevel@tonic-gate cmd->cmd_done = 1; 51687c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 51697c478bd9Sstevel@tonic-gate 51707c478bd9Sstevel@tonic-gate default: 51717c478bd9Sstevel@tonic-gate handle_data: 51727c478bd9Sstevel@tonic-gate if (bp && len && (cmd->cmd_dir == USB_EP_DIR_IN)) { 51737c478bd9Sstevel@tonic-gate /* 51747c478bd9Sstevel@tonic-gate * we don't have to copy the data, the 51757c478bd9Sstevel@tonic-gate * data pointers for the mblk_t for 51767c478bd9Sstevel@tonic-gate * the bulk-in xfer points to the 51777c478bd9Sstevel@tonic-gate * struct buf * data. 51787c478bd9Sstevel@tonic-gate */ 51797c478bd9Sstevel@tonic-gate cmd->cmd_offset += len; 51807c478bd9Sstevel@tonic-gate } 51817c478bd9Sstevel@tonic-gate 51827c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, 51837c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 51843fbbb872Ssl147100 "len = 0x%x total = 0x%lx offset = 0x%lx", 51853fbbb872Ssl147100 len, cmd->cmd_total_xfercount, cmd->cmd_offset); 51867c478bd9Sstevel@tonic-gate 51877c478bd9Sstevel@tonic-gate /* 51887c478bd9Sstevel@tonic-gate * update total_xfercount now but it may be 51897c478bd9Sstevel@tonic-gate * adjusted after receiving the residue 51907c478bd9Sstevel@tonic-gate */ 51917c478bd9Sstevel@tonic-gate cmd->cmd_total_xfercount -= len; 51927c478bd9Sstevel@tonic-gate 51937c478bd9Sstevel@tonic-gate if ((req->bulk_completion_reason != USB_CR_OK) || 51947c478bd9Sstevel@tonic-gate (cmd->cmd_resid_xfercount != 0) || 51957c478bd9Sstevel@tonic-gate (cmd->cmd_total_xfercount == 0)) { 51967c478bd9Sstevel@tonic-gate /* set pkt_resid to total to be sure */ 51977c478bd9Sstevel@tonic-gate pkt->pkt_resid = cmd->cmd_total_xfercount; 51987c478bd9Sstevel@tonic-gate cmd->cmd_done = 1; 51997c478bd9Sstevel@tonic-gate } 52007c478bd9Sstevel@tonic-gate 52017c478bd9Sstevel@tonic-gate break; 52027c478bd9Sstevel@tonic-gate } 52037c478bd9Sstevel@tonic-gate } else { 52047c478bd9Sstevel@tonic-gate if (cmd->cmd_dir == USB_EP_DIR_OUT) { 52057c478bd9Sstevel@tonic-gate if (cmd->cmd_total_xfercount == 0) { 52067c478bd9Sstevel@tonic-gate cmd->cmd_done = 1; 52077c478bd9Sstevel@tonic-gate } 52087c478bd9Sstevel@tonic-gate } 52097c478bd9Sstevel@tonic-gate } 52107c478bd9Sstevel@tonic-gate } 52117c478bd9Sstevel@tonic-gate 52127c478bd9Sstevel@tonic-gate 52137c478bd9Sstevel@tonic-gate /* 52147c478bd9Sstevel@tonic-gate * scsa2usb_init_bulk_req: 52157c478bd9Sstevel@tonic-gate * Allocate (synchronously) and fill in a bulk-request 52167c478bd9Sstevel@tonic-gate */ 52177c478bd9Sstevel@tonic-gate usb_bulk_req_t * 52187c478bd9Sstevel@tonic-gate scsa2usb_init_bulk_req(scsa2usb_state_t *scsa2usbp, size_t length, 52197c478bd9Sstevel@tonic-gate uint_t timeout, usb_req_attrs_t attrs, usb_flags_t flags) 52207c478bd9Sstevel@tonic-gate { 52217c478bd9Sstevel@tonic-gate usb_bulk_req_t *req; 52227c478bd9Sstevel@tonic-gate 52237c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 52247c478bd9Sstevel@tonic-gate 52257c478bd9Sstevel@tonic-gate req = usb_alloc_bulk_req(scsa2usbp->scsa2usb_dip, length, 52267c478bd9Sstevel@tonic-gate flags | USB_FLAGS_SLEEP); 52277c478bd9Sstevel@tonic-gate 5228d29f5a71Szhigang lu - Sun Microsystems - Beijing China req->bulk_len = (uint_t)length; /* xfer length */ 52297c478bd9Sstevel@tonic-gate req->bulk_timeout = scsa2usb_bulk_timeout(timeout); /* xfer timeout */ 52307c478bd9Sstevel@tonic-gate req->bulk_attributes = attrs; /* xfer attrs */ 52317c478bd9Sstevel@tonic-gate req->bulk_client_private = (usb_opaque_t)scsa2usbp; /* statep */ 52327c478bd9Sstevel@tonic-gate 52337c478bd9Sstevel@tonic-gate return (req); 52347c478bd9Sstevel@tonic-gate } 52357c478bd9Sstevel@tonic-gate 52367c478bd9Sstevel@tonic-gate 52377c478bd9Sstevel@tonic-gate /* 52387c478bd9Sstevel@tonic-gate * scsa2usb_bulk_timeout: 52397c478bd9Sstevel@tonic-gate * ensure that bulk requests do not have infinite timeout values 52407c478bd9Sstevel@tonic-gate */ 52417c478bd9Sstevel@tonic-gate int 52427c478bd9Sstevel@tonic-gate scsa2usb_bulk_timeout(int timeout) 52437c478bd9Sstevel@tonic-gate { 52447c478bd9Sstevel@tonic-gate return ((timeout == 0) ? scsa2usb_long_timeout : timeout); 52457c478bd9Sstevel@tonic-gate } 52467c478bd9Sstevel@tonic-gate 52477c478bd9Sstevel@tonic-gate 52487c478bd9Sstevel@tonic-gate /* 52497c478bd9Sstevel@tonic-gate * scsa2usb_clear_ept_stall: 52507c478bd9Sstevel@tonic-gate * clear endpoint stall and reset pipes 52517c478bd9Sstevel@tonic-gate */ 52527c478bd9Sstevel@tonic-gate int 52537c478bd9Sstevel@tonic-gate scsa2usb_clear_ept_stall(scsa2usb_state_t *scsa2usbp, uint_t ept_addr, 52547c478bd9Sstevel@tonic-gate usb_pipe_handle_t ph, char *what) 52557c478bd9Sstevel@tonic-gate { 52567c478bd9Sstevel@tonic-gate int rval; 52577c478bd9Sstevel@tonic-gate dev_info_t *dip = scsa2usbp->scsa2usb_dip; 52587c478bd9Sstevel@tonic-gate 52597c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 52607c478bd9Sstevel@tonic-gate if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 52617c478bd9Sstevel@tonic-gate 52627c478bd9Sstevel@tonic-gate return (USB_FAILURE); 52637c478bd9Sstevel@tonic-gate } 52647c478bd9Sstevel@tonic-gate 52657c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 52667c478bd9Sstevel@tonic-gate rval = usb_clr_feature(dip, USB_DEV_REQ_RCPT_EP, 0, ept_addr, 52677c478bd9Sstevel@tonic-gate USB_FLAGS_SLEEP, NULL, NULL); 52687c478bd9Sstevel@tonic-gate 52697c478bd9Sstevel@tonic-gate usb_pipe_reset(dip, ph, USB_FLAGS_SLEEP, NULL, NULL); 52707c478bd9Sstevel@tonic-gate 52717c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 52727c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 52737c478bd9Sstevel@tonic-gate "scsa2usb_clear_ept_stall: on %s: ept = 0x%x rval = %d", 52747c478bd9Sstevel@tonic-gate what, ept_addr, rval); 52757c478bd9Sstevel@tonic-gate 52767c478bd9Sstevel@tonic-gate return (rval); 52777c478bd9Sstevel@tonic-gate } 52787c478bd9Sstevel@tonic-gate 52797c478bd9Sstevel@tonic-gate 52807c478bd9Sstevel@tonic-gate /* 52817c478bd9Sstevel@tonic-gate * scsa2usb_pkt_completion: 52827c478bd9Sstevel@tonic-gate * Handle pkt completion. 52837c478bd9Sstevel@tonic-gate */ 52847c478bd9Sstevel@tonic-gate static void 52857c478bd9Sstevel@tonic-gate scsa2usb_pkt_completion(scsa2usb_state_t *scsa2usbp, struct scsi_pkt *pkt) 52867c478bd9Sstevel@tonic-gate { 52877c478bd9Sstevel@tonic-gate scsa2usb_cmd_t *cmd = PKT2CMD(pkt); 5288d94492edSfb209375 size_t len; 52897c478bd9Sstevel@tonic-gate 52907c478bd9Sstevel@tonic-gate ASSERT(pkt); 52917c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 52927c478bd9Sstevel@tonic-gate 52937c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 52947c478bd9Sstevel@tonic-gate "scsa2usb_pkt_completion:\n\tscsa2usbp = 0x%p " 52957c478bd9Sstevel@tonic-gate "reason=%d, status=%d state=0x%x stats=0x%x resid=0x%lx", 5296112116d8Sfb209375 (void *)scsa2usbp, pkt->pkt_reason, *(pkt->pkt_scbp), 52977c478bd9Sstevel@tonic-gate pkt->pkt_state, pkt->pkt_statistics, pkt->pkt_resid); 52987c478bd9Sstevel@tonic-gate 52997c478bd9Sstevel@tonic-gate if (pkt->pkt_reason == CMD_CMPLT) { 53007c478bd9Sstevel@tonic-gate pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | 53017c478bd9Sstevel@tonic-gate STATE_SENT_CMD | STATE_GOT_STATUS; 53027c478bd9Sstevel@tonic-gate if (cmd->cmd_xfercount) { 53037c478bd9Sstevel@tonic-gate pkt->pkt_state |= STATE_XFERRED_DATA; 53047c478bd9Sstevel@tonic-gate } 53057c478bd9Sstevel@tonic-gate } else { 53067c478bd9Sstevel@tonic-gate pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | 53077c478bd9Sstevel@tonic-gate STATE_SENT_CMD; 53087c478bd9Sstevel@tonic-gate } 53097c478bd9Sstevel@tonic-gate 53107c478bd9Sstevel@tonic-gate /* 53117c478bd9Sstevel@tonic-gate * don't zap the current state when in panic as this will 53127c478bd9Sstevel@tonic-gate * make debugging harder 53137c478bd9Sstevel@tonic-gate */ 53147c478bd9Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_cur_pkt == pkt) && !ddi_in_panic()) { 53157c478bd9Sstevel@tonic-gate SCSA2USB_RESET_CUR_PKT(scsa2usbp); 53167c478bd9Sstevel@tonic-gate 5317d94492edSfb209375 len = sizeof (scsa2usbp->scsa2usb_last_cmd.cdb); 5318d94492edSfb209375 bzero(scsa2usbp->scsa2usb_last_cmd.cdb, len); 5319d94492edSfb209375 5320d94492edSfb209375 len = (len < cmd->cmd_cdblen) ? len : cmd->cmd_cdblen; 5321d94492edSfb209375 USB_DPRINTF_L3(DPRINT_MASK_SCSA, 5322d94492edSfb209375 scsa2usbp->scsa2usb_log_handle, 5323112116d8Sfb209375 "scsa2usb_pkt_completion: save last cmd, len=%ld", len); 5324d94492edSfb209375 53257c478bd9Sstevel@tonic-gate /* save the last command */ 5326d94492edSfb209375 bcopy(pkt->pkt_cdbp, scsa2usbp->scsa2usb_last_cmd.cdb, len); 53277c478bd9Sstevel@tonic-gate 53287c478bd9Sstevel@tonic-gate /* reset the scsa2usb_last_cmd.status value */ 53297c478bd9Sstevel@tonic-gate if ((pkt->pkt_cdbp[0] != SCMD_REQUEST_SENSE) && 53307c478bd9Sstevel@tonic-gate (pkt->pkt_cdbp[0] != SCMD_INQUIRY)) { 53317c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_last_cmd.status = 0; 53327c478bd9Sstevel@tonic-gate } 53337c478bd9Sstevel@tonic-gate 53347c478bd9Sstevel@tonic-gate /* 53357c478bd9Sstevel@tonic-gate * set pkt state to NONE *before* calling back as the target 53367c478bd9Sstevel@tonic-gate * driver will immediately submit the next packet 53377c478bd9Sstevel@tonic-gate */ 53387c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pkt_state = SCSA2USB_PKT_NONE; 53397c478bd9Sstevel@tonic-gate } 53407c478bd9Sstevel@tonic-gate 53417c478bd9Sstevel@tonic-gate if (pkt->pkt_comp) { 53427c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 53439c57abc8Ssrivijitha dugganapalli scsi_hba_pkt_comp(pkt); 53447c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 53457c478bd9Sstevel@tonic-gate 53467c478bd9Sstevel@tonic-gate } 53477c478bd9Sstevel@tonic-gate } 53487c478bd9Sstevel@tonic-gate 53497c478bd9Sstevel@tonic-gate 53507c478bd9Sstevel@tonic-gate /* 53517c478bd9Sstevel@tonic-gate * Even handling functions: 53527c478bd9Sstevel@tonic-gate * 53537c478bd9Sstevel@tonic-gate * scsa2usb_reconnect_event_cb: 53547c478bd9Sstevel@tonic-gate * event handling 53557c478bd9Sstevel@tonic-gate */ 53567c478bd9Sstevel@tonic-gate static int 53577c478bd9Sstevel@tonic-gate scsa2usb_reconnect_event_cb(dev_info_t *dip) 53587c478bd9Sstevel@tonic-gate { 53597c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = 53607c478bd9Sstevel@tonic-gate ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 53617c478bd9Sstevel@tonic-gate dev_info_t *cdip; 53627c478bd9Sstevel@tonic-gate int circ; 53637c478bd9Sstevel@tonic-gate int rval = USB_SUCCESS; 53647c478bd9Sstevel@tonic-gate 53657c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 53667c478bd9Sstevel@tonic-gate 53677c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 5368112116d8Sfb209375 "scsa2usb_reconnect_event_cb: dip = 0x%p", (void *)dip); 53697c478bd9Sstevel@tonic-gate 53707c478bd9Sstevel@tonic-gate scsa2usb_restore_device_state(dip, scsa2usbp); 53717c478bd9Sstevel@tonic-gate 53724610e4a0Sfrits USB_DPRINTF_L0(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 53734610e4a0Sfrits "Reinserted device is accessible again."); 53744610e4a0Sfrits 53757c478bd9Sstevel@tonic-gate ndi_devi_enter(dip, &circ); 53767c478bd9Sstevel@tonic-gate for (cdip = ddi_get_child(dip); cdip; ) { 53777c478bd9Sstevel@tonic-gate dev_info_t *next = ddi_get_next_sibling(cdip); 53787c478bd9Sstevel@tonic-gate 53797c478bd9Sstevel@tonic-gate mutex_enter(&DEVI(cdip)->devi_lock); 53807c478bd9Sstevel@tonic-gate DEVI_SET_DEVICE_REINSERTED(cdip); 53817c478bd9Sstevel@tonic-gate mutex_exit(&DEVI(cdip)->devi_lock); 53827c478bd9Sstevel@tonic-gate 53837c478bd9Sstevel@tonic-gate cdip = next; 53847c478bd9Sstevel@tonic-gate } 53857c478bd9Sstevel@tonic-gate ndi_devi_exit(dip, circ); 53867c478bd9Sstevel@tonic-gate 53877c478bd9Sstevel@tonic-gate /* stop suppressing warnings */ 53887c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 53897c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_warning_given = B_FALSE; 53907c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 53917c478bd9Sstevel@tonic-gate 53927c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_ugen_hdl) { 53937c478bd9Sstevel@tonic-gate rval = usb_ugen_reconnect_ev_cb( 53947c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_ugen_hdl); 53957c478bd9Sstevel@tonic-gate } 53967c478bd9Sstevel@tonic-gate 53977c478bd9Sstevel@tonic-gate return (rval); 53987c478bd9Sstevel@tonic-gate } 53997c478bd9Sstevel@tonic-gate 54007c478bd9Sstevel@tonic-gate 54017c478bd9Sstevel@tonic-gate /* 54027c478bd9Sstevel@tonic-gate * scsa2usb_all_waitQs_empty: 54037c478bd9Sstevel@tonic-gate * check if all waitQs empty 54047c478bd9Sstevel@tonic-gate */ 54057c478bd9Sstevel@tonic-gate static int 54067c478bd9Sstevel@tonic-gate scsa2usb_all_waitQs_empty(scsa2usb_state_t *scsa2usbp) 54077c478bd9Sstevel@tonic-gate { 54087c478bd9Sstevel@tonic-gate uint_t lun; 54097c478bd9Sstevel@tonic-gate 54107c478bd9Sstevel@tonic-gate for (lun = 0; lun < SCSA2USB_MAX_LUNS; lun++) { 54117c478bd9Sstevel@tonic-gate if (usba_list_entry_count( 54127c478bd9Sstevel@tonic-gate &scsa2usbp->scsa2usb_waitQ[lun])) { 54137c478bd9Sstevel@tonic-gate 54147c478bd9Sstevel@tonic-gate return (USB_FAILURE); 54157c478bd9Sstevel@tonic-gate } 54167c478bd9Sstevel@tonic-gate } 54177c478bd9Sstevel@tonic-gate 54187c478bd9Sstevel@tonic-gate return (USB_SUCCESS); 54197c478bd9Sstevel@tonic-gate } 54207c478bd9Sstevel@tonic-gate 54217c478bd9Sstevel@tonic-gate 54227c478bd9Sstevel@tonic-gate /* 54237c478bd9Sstevel@tonic-gate * scsa2usb_disconnect_event_cb: 54247c478bd9Sstevel@tonic-gate * callback for disconnect events 54257c478bd9Sstevel@tonic-gate */ 54267c478bd9Sstevel@tonic-gate static int 54277c478bd9Sstevel@tonic-gate scsa2usb_disconnect_event_cb(dev_info_t *dip) 54287c478bd9Sstevel@tonic-gate { 54297c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp = 54307c478bd9Sstevel@tonic-gate ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 54317c478bd9Sstevel@tonic-gate dev_info_t *cdip; 54327c478bd9Sstevel@tonic-gate int circ, i; 54337c478bd9Sstevel@tonic-gate int rval = USB_SUCCESS; 54347c478bd9Sstevel@tonic-gate 54357c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp != NULL); 54367c478bd9Sstevel@tonic-gate 54377c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 5438112116d8Sfb209375 "scsa2usb_disconnect_event_cb: dip = 0x%p", (void *)dip); 54397c478bd9Sstevel@tonic-gate 54407c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 54417c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_DISCONNECTED; 54427c478bd9Sstevel@tonic-gate 54437c478bd9Sstevel@tonic-gate /* 54447c478bd9Sstevel@tonic-gate * wait till the work thread is done, carry on regardless 54457c478bd9Sstevel@tonic-gate * if not. 54467c478bd9Sstevel@tonic-gate */ 54477c478bd9Sstevel@tonic-gate for (i = 0; i < SCSA2USB_DRAIN_TIMEOUT; i++) { 54487c478bd9Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_work_thread_id == NULL) && 54497c478bd9Sstevel@tonic-gate (scsa2usbp->scsa2usb_cur_pkt == NULL) && 54507c478bd9Sstevel@tonic-gate (scsa2usb_all_waitQs_empty(scsa2usbp) == 54517c478bd9Sstevel@tonic-gate USB_SUCCESS)) { 54527c478bd9Sstevel@tonic-gate 54537c478bd9Sstevel@tonic-gate break; 54547c478bd9Sstevel@tonic-gate } 54557c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 54567c478bd9Sstevel@tonic-gate delay(drv_usectohz(1000000)); 54577c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 54587c478bd9Sstevel@tonic-gate } 54597c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 54607c478bd9Sstevel@tonic-gate 54617c478bd9Sstevel@tonic-gate ndi_devi_enter(dip, &circ); 54627c478bd9Sstevel@tonic-gate for (cdip = ddi_get_child(dip); cdip; ) { 54637c478bd9Sstevel@tonic-gate dev_info_t *next = ddi_get_next_sibling(cdip); 54647c478bd9Sstevel@tonic-gate 54657c478bd9Sstevel@tonic-gate mutex_enter(&DEVI(cdip)->devi_lock); 54667c478bd9Sstevel@tonic-gate DEVI_SET_DEVICE_REMOVED(cdip); 54677c478bd9Sstevel@tonic-gate mutex_exit(&DEVI(cdip)->devi_lock); 54687c478bd9Sstevel@tonic-gate 54697c478bd9Sstevel@tonic-gate cdip = next; 54707c478bd9Sstevel@tonic-gate } 54717c478bd9Sstevel@tonic-gate ndi_devi_exit(dip, circ); 54727c478bd9Sstevel@tonic-gate 54737c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_ugen_hdl) { 54747c478bd9Sstevel@tonic-gate rval = usb_ugen_disconnect_ev_cb( 54757c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_ugen_hdl); 54767c478bd9Sstevel@tonic-gate } 54777c478bd9Sstevel@tonic-gate 54787c478bd9Sstevel@tonic-gate return (rval); 54797c478bd9Sstevel@tonic-gate } 54807c478bd9Sstevel@tonic-gate 54817c478bd9Sstevel@tonic-gate 54827c478bd9Sstevel@tonic-gate /* 54837c478bd9Sstevel@tonic-gate * PM support 54847c478bd9Sstevel@tonic-gate * 54857c478bd9Sstevel@tonic-gate * scsa2usb_create_pm_components: 54867c478bd9Sstevel@tonic-gate * create the pm components required for power management 54877c478bd9Sstevel@tonic-gate * no mutex is need when calling USBA interfaces 54887c478bd9Sstevel@tonic-gate */ 54897c478bd9Sstevel@tonic-gate static void 54907c478bd9Sstevel@tonic-gate scsa2usb_create_pm_components(dev_info_t *dip, scsa2usb_state_t *scsa2usbp) 54917c478bd9Sstevel@tonic-gate { 54927c478bd9Sstevel@tonic-gate scsa2usb_power_t *pm; 54937c478bd9Sstevel@tonic-gate uint_t pwr_states; 54947c478bd9Sstevel@tonic-gate 54957c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 54967c478bd9Sstevel@tonic-gate 54977c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 54987c478bd9Sstevel@tonic-gate "scsa2usb_create_pm_components: dip = 0x%p, scsa2usbp = 0x%p", 5499112116d8Sfb209375 (void *)dip, (void *)scsa2usbp); 55007c478bd9Sstevel@tonic-gate 55017c478bd9Sstevel@tonic-gate /* 55027c478bd9Sstevel@tonic-gate * determine if this device is on the blacklist 55037c478bd9Sstevel@tonic-gate * or if a conf file entry has disabled PM 55047c478bd9Sstevel@tonic-gate */ 55057c478bd9Sstevel@tonic-gate if ((scsa2usbp->scsa2usb_attrs & SCSA2USB_ATTRS_PM) == 0) { 55067c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 55077c478bd9Sstevel@tonic-gate "device cannot be power managed"); 55087c478bd9Sstevel@tonic-gate 55097c478bd9Sstevel@tonic-gate return; 55107c478bd9Sstevel@tonic-gate } 55117c478bd9Sstevel@tonic-gate 55127c478bd9Sstevel@tonic-gate /* Allocate the PM state structure */ 55137c478bd9Sstevel@tonic-gate pm = kmem_zalloc(sizeof (scsa2usb_power_t), KM_SLEEP); 55147c478bd9Sstevel@tonic-gate 55157c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pm = pm; 55167c478bd9Sstevel@tonic-gate pm->scsa2usb_current_power = USB_DEV_OS_FULL_PWR; 55177c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 55187c478bd9Sstevel@tonic-gate 55197c478bd9Sstevel@tonic-gate if (usb_create_pm_components(dip, &pwr_states) == 55207c478bd9Sstevel@tonic-gate USB_SUCCESS) { 55217c478bd9Sstevel@tonic-gate if (usb_handle_remote_wakeup(dip, 55227c478bd9Sstevel@tonic-gate USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) { 55237c478bd9Sstevel@tonic-gate pm->scsa2usb_wakeup_enabled = 1; 55247c478bd9Sstevel@tonic-gate } 55257c478bd9Sstevel@tonic-gate 55267c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 55277c478bd9Sstevel@tonic-gate pm->scsa2usb_pwr_states = (uint8_t)pwr_states; 5528496d8c83Sfrits scsa2usb_raise_power(scsa2usbp); 55297c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 55307c478bd9Sstevel@tonic-gate } 55317c478bd9Sstevel@tonic-gate 55327c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 55337c478bd9Sstevel@tonic-gate } 55347c478bd9Sstevel@tonic-gate 55357c478bd9Sstevel@tonic-gate 55367c478bd9Sstevel@tonic-gate /* 55377c478bd9Sstevel@tonic-gate * scsa2usb_raise_power: 55387c478bd9Sstevel@tonic-gate * check if the device is using full power or not 55397c478bd9Sstevel@tonic-gate */ 55407c478bd9Sstevel@tonic-gate static void 55417c478bd9Sstevel@tonic-gate scsa2usb_raise_power(scsa2usb_state_t *scsa2usbp) 55427c478bd9Sstevel@tonic-gate { 55437c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 55447c478bd9Sstevel@tonic-gate "scsa2usb_raise_power:"); 55457c478bd9Sstevel@tonic-gate 55467c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 55477c478bd9Sstevel@tonic-gate 55487c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_pm) { 55497c478bd9Sstevel@tonic-gate scsa2usb_pm_busy_component(scsa2usbp); 5550496d8c83Sfrits if (scsa2usbp->scsa2usb_pm->scsa2usb_current_power != 5551496d8c83Sfrits USB_DEV_OS_FULL_PWR) { 55527c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 55537c478bd9Sstevel@tonic-gate (void) pm_raise_power(scsa2usbp->scsa2usb_dip, 55547c478bd9Sstevel@tonic-gate 0, USB_DEV_OS_FULL_PWR); 55557c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 55567c478bd9Sstevel@tonic-gate } 55577c478bd9Sstevel@tonic-gate } 55587c478bd9Sstevel@tonic-gate } 55597c478bd9Sstevel@tonic-gate 55607c478bd9Sstevel@tonic-gate 55617c478bd9Sstevel@tonic-gate /* 55627c478bd9Sstevel@tonic-gate * functions to handle power transition for OS levels 0 -> 3 55637c478bd9Sstevel@tonic-gate */ 55647c478bd9Sstevel@tonic-gate static int 55657c478bd9Sstevel@tonic-gate scsa2usb_pwrlvl0(scsa2usb_state_t *scsa2usbp) 55667c478bd9Sstevel@tonic-gate { 55677c478bd9Sstevel@tonic-gate int rval; 55687c478bd9Sstevel@tonic-gate 55697c478bd9Sstevel@tonic-gate switch (scsa2usbp->scsa2usb_dev_state) { 55707c478bd9Sstevel@tonic-gate case USB_DEV_ONLINE: 55717c478bd9Sstevel@tonic-gate /* Deny the powerdown request if the device is busy */ 55727c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy != 0) { 55737c478bd9Sstevel@tonic-gate 55747c478bd9Sstevel@tonic-gate return (USB_FAILURE); 55757c478bd9Sstevel@tonic-gate } 55767c478bd9Sstevel@tonic-gate 55777c478bd9Sstevel@tonic-gate /* 55787c478bd9Sstevel@tonic-gate * stop polling on interrupt pipe 55797c478bd9Sstevel@tonic-gate */ 55807c478bd9Sstevel@tonic-gate scsa2usb_cbi_stop_intr_polling(scsa2usbp); 55817c478bd9Sstevel@tonic-gate 55827c478bd9Sstevel@tonic-gate /* Issue USB D3 command to the device here */ 55837c478bd9Sstevel@tonic-gate rval = usb_set_device_pwrlvl3(scsa2usbp->scsa2usb_dip); 55847c478bd9Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS); 55857c478bd9Sstevel@tonic-gate 55867c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_PWRED_DOWN; 55877c478bd9Sstevel@tonic-gate 55887c478bd9Sstevel@tonic-gate /* FALLTHRU */ 55897c478bd9Sstevel@tonic-gate case USB_DEV_DISCONNECTED: 55907c478bd9Sstevel@tonic-gate case USB_DEV_SUSPENDED: 55917c478bd9Sstevel@tonic-gate case USB_DEV_PWRED_DOWN: 55927c478bd9Sstevel@tonic-gate default: 55937c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pm->scsa2usb_current_power = 55947c478bd9Sstevel@tonic-gate USB_DEV_OS_PWR_OFF; 55957c478bd9Sstevel@tonic-gate 55967c478bd9Sstevel@tonic-gate return (USB_SUCCESS); 55977c478bd9Sstevel@tonic-gate } 55987c478bd9Sstevel@tonic-gate } 55997c478bd9Sstevel@tonic-gate 56007c478bd9Sstevel@tonic-gate 56017c478bd9Sstevel@tonic-gate static int 56027c478bd9Sstevel@tonic-gate scsa2usb_pwrlvl1(scsa2usb_state_t *scsa2usbp) 56037c478bd9Sstevel@tonic-gate { 56047c478bd9Sstevel@tonic-gate int rval; 56057c478bd9Sstevel@tonic-gate 56067c478bd9Sstevel@tonic-gate /* Issue USB D2 command to the device here */ 56077c478bd9Sstevel@tonic-gate rval = usb_set_device_pwrlvl2(scsa2usbp->scsa2usb_dip); 56087c478bd9Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS); 56097c478bd9Sstevel@tonic-gate 56107c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 56117c478bd9Sstevel@tonic-gate } 56127c478bd9Sstevel@tonic-gate 56137c478bd9Sstevel@tonic-gate 56147c478bd9Sstevel@tonic-gate static int 56157c478bd9Sstevel@tonic-gate scsa2usb_pwrlvl2(scsa2usb_state_t *scsa2usbp) 56167c478bd9Sstevel@tonic-gate { 56177c478bd9Sstevel@tonic-gate int rval; 56187c478bd9Sstevel@tonic-gate 56197c478bd9Sstevel@tonic-gate /* Issue USB D1 command to the device here */ 56207c478bd9Sstevel@tonic-gate rval = usb_set_device_pwrlvl1(scsa2usbp->scsa2usb_dip); 56217c478bd9Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS); 56227c478bd9Sstevel@tonic-gate 56237c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 56247c478bd9Sstevel@tonic-gate } 56257c478bd9Sstevel@tonic-gate 56267c478bd9Sstevel@tonic-gate 56277c478bd9Sstevel@tonic-gate static int 56287c478bd9Sstevel@tonic-gate scsa2usb_pwrlvl3(scsa2usb_state_t *scsa2usbp) 56297c478bd9Sstevel@tonic-gate { 56307c478bd9Sstevel@tonic-gate int rval; 56317c478bd9Sstevel@tonic-gate 56327c478bd9Sstevel@tonic-gate /* 56337c478bd9Sstevel@tonic-gate * PM framework tries to put us in full power 56347c478bd9Sstevel@tonic-gate * during system shutdown. If we are disconnected 56357c478bd9Sstevel@tonic-gate * return success anyways 56367c478bd9Sstevel@tonic-gate */ 56377c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_dev_state != USB_DEV_DISCONNECTED) { 56387c478bd9Sstevel@tonic-gate /* Issue USB D0 command to the device here */ 56397c478bd9Sstevel@tonic-gate rval = usb_set_device_pwrlvl0(scsa2usbp->scsa2usb_dip); 56407c478bd9Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS); 56417c478bd9Sstevel@tonic-gate 56427c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_dev_state = USB_DEV_ONLINE; 56437c478bd9Sstevel@tonic-gate } 56447c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pm->scsa2usb_current_power = USB_DEV_OS_FULL_PWR; 56457c478bd9Sstevel@tonic-gate 56467c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 56477c478bd9Sstevel@tonic-gate } 56487c478bd9Sstevel@tonic-gate 56497c478bd9Sstevel@tonic-gate 56507c478bd9Sstevel@tonic-gate /* 56517c478bd9Sstevel@tonic-gate * scsa2usb_power: 56527c478bd9Sstevel@tonic-gate * power entry point 56537c478bd9Sstevel@tonic-gate */ 56547c478bd9Sstevel@tonic-gate /* ARGSUSED */ 56557c478bd9Sstevel@tonic-gate static int 56567c478bd9Sstevel@tonic-gate scsa2usb_power(dev_info_t *dip, int comp, int level) 56577c478bd9Sstevel@tonic-gate { 56587c478bd9Sstevel@tonic-gate scsa2usb_state_t *scsa2usbp; 56597c478bd9Sstevel@tonic-gate scsa2usb_power_t *pm; 56607c478bd9Sstevel@tonic-gate int rval = DDI_FAILURE; 56617c478bd9Sstevel@tonic-gate 56627c478bd9Sstevel@tonic-gate scsa2usbp = ddi_get_soft_state(scsa2usb_statep, ddi_get_instance(dip)); 56637c478bd9Sstevel@tonic-gate 56647c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 56657c478bd9Sstevel@tonic-gate "scsa2usb_power: Begin scsa2usbp (%p): level = %d", 5666112116d8Sfb209375 (void *)scsa2usbp, level); 56677c478bd9Sstevel@tonic-gate 56687c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 56697c478bd9Sstevel@tonic-gate if (SCSA2USB_BUSY(scsa2usbp)) { 56707c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 56717c478bd9Sstevel@tonic-gate "scsa2usb_power: busy"); 56727c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 56737c478bd9Sstevel@tonic-gate 56747c478bd9Sstevel@tonic-gate return (rval); 56757c478bd9Sstevel@tonic-gate } 56767c478bd9Sstevel@tonic-gate 56777c478bd9Sstevel@tonic-gate pm = scsa2usbp->scsa2usb_pm; 56787c478bd9Sstevel@tonic-gate if (pm == NULL) { 56797c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 56807c478bd9Sstevel@tonic-gate "scsa2usb_power: pm NULL"); 56817c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 56827c478bd9Sstevel@tonic-gate 56837c478bd9Sstevel@tonic-gate return (rval); 56847c478bd9Sstevel@tonic-gate } 56857c478bd9Sstevel@tonic-gate 56867c478bd9Sstevel@tonic-gate /* check if we are transitioning to a legal power level */ 56877c478bd9Sstevel@tonic-gate if (USB_DEV_PWRSTATE_OK(pm->scsa2usb_pwr_states, level)) { 56887c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(DPRINT_MASK_PM, scsa2usbp->scsa2usb_log_handle, 56897c478bd9Sstevel@tonic-gate "scsa2usb_power: illegal power level = %d " 56907c478bd9Sstevel@tonic-gate "pwr_states: %x", level, pm->scsa2usb_pwr_states); 56917c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 56927c478bd9Sstevel@tonic-gate 56937c478bd9Sstevel@tonic-gate return (rval); 56947c478bd9Sstevel@tonic-gate } 56957c478bd9Sstevel@tonic-gate 56967c478bd9Sstevel@tonic-gate switch (level) { 56977c478bd9Sstevel@tonic-gate case USB_DEV_OS_PWR_OFF : 56987c478bd9Sstevel@tonic-gate rval = scsa2usb_pwrlvl0(scsa2usbp); 56997c478bd9Sstevel@tonic-gate break; 57007c478bd9Sstevel@tonic-gate case USB_DEV_OS_PWR_1 : 57017c478bd9Sstevel@tonic-gate rval = scsa2usb_pwrlvl1(scsa2usbp); 57027c478bd9Sstevel@tonic-gate break; 57037c478bd9Sstevel@tonic-gate case USB_DEV_OS_PWR_2 : 57047c478bd9Sstevel@tonic-gate rval = scsa2usb_pwrlvl2(scsa2usbp); 57057c478bd9Sstevel@tonic-gate break; 57067c478bd9Sstevel@tonic-gate case USB_DEV_OS_FULL_PWR : 57077c478bd9Sstevel@tonic-gate rval = scsa2usb_pwrlvl3(scsa2usbp); 57087c478bd9Sstevel@tonic-gate break; 57097c478bd9Sstevel@tonic-gate } 57107c478bd9Sstevel@tonic-gate 57117c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 57127c478bd9Sstevel@tonic-gate 57137c478bd9Sstevel@tonic-gate return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 57147c478bd9Sstevel@tonic-gate } 57157c478bd9Sstevel@tonic-gate 57167c478bd9Sstevel@tonic-gate 57177c478bd9Sstevel@tonic-gate static void 5718496d8c83Sfrits scsa2usb_pm_busy_component(scsa2usb_state_t *scsa2usbp) 57197c478bd9Sstevel@tonic-gate { 5720496d8c83Sfrits ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 57217c478bd9Sstevel@tonic-gate 5722496d8c83Sfrits if (scsa2usbp->scsa2usb_pm) { 5723496d8c83Sfrits scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy++; 57247c478bd9Sstevel@tonic-gate 5725496d8c83Sfrits USB_DPRINTF_L4(DPRINT_MASK_PM, 5726496d8c83Sfrits scsa2usbp->scsa2usb_log_handle, 5727496d8c83Sfrits "scsa2usb_pm_busy_component: %d", 5728496d8c83Sfrits scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy); 5729496d8c83Sfrits 5730496d8c83Sfrits mutex_exit(&scsa2usbp->scsa2usb_mutex); 5731496d8c83Sfrits 5732496d8c83Sfrits if (pm_busy_component(scsa2usbp->scsa2usb_dip, 0) != 57337c478bd9Sstevel@tonic-gate DDI_SUCCESS) { 5734496d8c83Sfrits mutex_enter(&scsa2usbp->scsa2usb_mutex); 5735496d8c83Sfrits ASSERT(scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy > 0); 5736496d8c83Sfrits scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy--; 5737496d8c83Sfrits 5738496d8c83Sfrits USB_DPRINTF_L2(DPRINT_MASK_PM, 5739496d8c83Sfrits scsa2usbp->scsa2usb_log_handle, 5740496d8c83Sfrits "scsa2usb_pm_busy_component failed: %d", 5741496d8c83Sfrits scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy); 5742496d8c83Sfrits 5743496d8c83Sfrits return; 57447c478bd9Sstevel@tonic-gate } 5745496d8c83Sfrits mutex_enter(&scsa2usbp->scsa2usb_mutex); 5746496d8c83Sfrits } 57477c478bd9Sstevel@tonic-gate } 57487c478bd9Sstevel@tonic-gate 57497c478bd9Sstevel@tonic-gate 57507c478bd9Sstevel@tonic-gate /* 57517c478bd9Sstevel@tonic-gate * scsa2usb_pm_idle_component: 57527c478bd9Sstevel@tonic-gate * idles the device 57537c478bd9Sstevel@tonic-gate */ 57547c478bd9Sstevel@tonic-gate static void 57557c478bd9Sstevel@tonic-gate scsa2usb_pm_idle_component(scsa2usb_state_t *scsa2usbp) 57567c478bd9Sstevel@tonic-gate { 5757496d8c83Sfrits ASSERT(!mutex_owned(&scsa2usbp->scsa2usb_mutex)); 5758496d8c83Sfrits 57597c478bd9Sstevel@tonic-gate if (scsa2usbp->scsa2usb_pm) { 57607c478bd9Sstevel@tonic-gate if (pm_idle_component(scsa2usbp->scsa2usb_dip, 0) == 57617c478bd9Sstevel@tonic-gate DDI_SUCCESS) { 57627c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 57637c478bd9Sstevel@tonic-gate ASSERT(scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy > 0); 57647c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy--; 5765496d8c83Sfrits 57667c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(DPRINT_MASK_PM, 57677c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_log_handle, 5768496d8c83Sfrits "scsa2usb_pm_idle_component: %d", 57697c478bd9Sstevel@tonic-gate scsa2usbp->scsa2usb_pm->scsa2usb_pm_busy); 5770496d8c83Sfrits 5771496d8c83Sfrits mutex_exit(&scsa2usbp->scsa2usb_mutex); 5772496d8c83Sfrits } 57737c478bd9Sstevel@tonic-gate } 57747c478bd9Sstevel@tonic-gate } 57757c478bd9Sstevel@tonic-gate 57767c478bd9Sstevel@tonic-gate 57777c478bd9Sstevel@tonic-gate #ifdef DEBUG 57787c478bd9Sstevel@tonic-gate /* 57797c478bd9Sstevel@tonic-gate * scsa2usb_print_cdb: 57807c478bd9Sstevel@tonic-gate * prints CDB 57817c478bd9Sstevel@tonic-gate */ 57827c478bd9Sstevel@tonic-gate void 57837c478bd9Sstevel@tonic-gate scsa2usb_print_cdb(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) 57847c478bd9Sstevel@tonic-gate { 57857c478bd9Sstevel@tonic-gate uchar_t *c = (uchar_t *)&cmd->cmd_cdb; 57867c478bd9Sstevel@tonic-gate 57877c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 57887c478bd9Sstevel@tonic-gate "cmd = 0x%p opcode=%s " 57897c478bd9Sstevel@tonic-gate "cdb: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", 5790112116d8Sfb209375 (void *)cmd, 5791112116d8Sfb209375 scsi_cname(cmd->cmd_cdb[SCSA2USB_OPCODE], scsa2usb_cmds), 57927c478bd9Sstevel@tonic-gate c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], 57937c478bd9Sstevel@tonic-gate c[9], c[10], c[11], c[12], c[13], c[14], c[15]); 57947c478bd9Sstevel@tonic-gate } 57957c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 57967c478bd9Sstevel@tonic-gate 57977c478bd9Sstevel@tonic-gate 57987c478bd9Sstevel@tonic-gate #ifdef SCSA2USB_BULK_ONLY_TEST 57997c478bd9Sstevel@tonic-gate /* 58007c478bd9Sstevel@tonic-gate * scsa2usb_test_mblk: 58017c478bd9Sstevel@tonic-gate * This function sends a dummy data mblk_t to simulate 58027c478bd9Sstevel@tonic-gate * the following test cases: 5 and 11. 58037c478bd9Sstevel@tonic-gate */ 58047c478bd9Sstevel@tonic-gate static void 58057c478bd9Sstevel@tonic-gate scsa2usb_test_mblk(scsa2usb_state_t *scsa2usbp, boolean_t large) 58067c478bd9Sstevel@tonic-gate { 58077c478bd9Sstevel@tonic-gate int i, rval; 58087c478bd9Sstevel@tonic-gate size_t len; 58097c478bd9Sstevel@tonic-gate usb_flags_t flags = USB_FLAGS_SLEEP; 58107c478bd9Sstevel@tonic-gate usb_bulk_req_t *req; 58117c478bd9Sstevel@tonic-gate 58127c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 58137c478bd9Sstevel@tonic-gate 58147c478bd9Sstevel@tonic-gate /* should we create a larger mblk? */ 58157c478bd9Sstevel@tonic-gate len = (large == B_TRUE) ? DEV_BSIZE : USB_BULK_CBWCMD_LEN; 58167c478bd9Sstevel@tonic-gate 58177c478bd9Sstevel@tonic-gate req = scsa2usb_init_bulk_req(scsa2usbp, len, 58187c478bd9Sstevel@tonic-gate SCSA2USB_BULK_PIPE_TIMEOUT, 0, flags); 58197c478bd9Sstevel@tonic-gate 58207c478bd9Sstevel@tonic-gate /* fill up the data mblk */ 58217c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) { 58227c478bd9Sstevel@tonic-gate *req->bulk_data->b_wptr++ = (uchar_t)i; 58237c478bd9Sstevel@tonic-gate } 58247c478bd9Sstevel@tonic-gate 58257c478bd9Sstevel@tonic-gate mutex_exit(&scsa2usbp->scsa2usb_mutex); 58267c478bd9Sstevel@tonic-gate ASSERT(req->bulk_timeout); 58277c478bd9Sstevel@tonic-gate rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkout_pipe, req, flags); 58287c478bd9Sstevel@tonic-gate mutex_enter(&scsa2usbp->scsa2usb_mutex); 58297c478bd9Sstevel@tonic-gate 58307c478bd9Sstevel@tonic-gate USB_DPRINTF_L1(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 58317c478bd9Sstevel@tonic-gate "scsa2usb_test_mblk: Sent Data Out rval = 0x%x", rval); 58327c478bd9Sstevel@tonic-gate 58337c478bd9Sstevel@tonic-gate usb_free_bulk_req(req); 58347c478bd9Sstevel@tonic-gate } 58357c478bd9Sstevel@tonic-gate #endif /* SCSA2USB_BULK_ONLY_TEST */ 5836