1 /* $NetBSD: umass_quirks.c,v 1.64 2003/11/07 01:04:27 kivinen Exp $ */ 2 3 /* 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by MAEKAWA Masahide (gehenna@NetBSD.org). 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: umass_quirks.c,v 1.64 2003/11/07 01:04:27 kivinen Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/device.h> 45 #include <sys/buf.h> 46 47 #include <dev/scsipi/scsipi_all.h> /* for scsiconf.h below */ 48 #include <dev/scsipi/scsiconf.h> /* for quirks defines */ 49 50 #include <dev/usb/usb.h> 51 #include <dev/usb/usbdi.h> 52 #include <dev/usb/usbdevs.h> 53 54 #include <dev/usb/umassvar.h> 55 #include <dev/usb/umass_quirks.h> 56 57 Static usbd_status umass_init_insystem(struct umass_softc *); 58 Static usbd_status umass_init_shuttle(struct umass_softc *); 59 60 Static void umass_fixup_sony(struct umass_softc *); 61 62 Static const struct umass_quirk umass_quirks[] = { 63 /* 64 * The following 3 In-System Design adapters use a non-standard ATA 65 * over BBB protocol. Force this protocol by quirk entries. 66 */ 67 { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ADAPTERV2 }, 68 UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA, 69 0, 70 0, 71 UMATCH_VENDOR_PRODUCT, 72 NULL, NULL 73 }, 74 { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ATAPI }, 75 UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA, 76 0, 77 0, 78 UMATCH_VENDOR_PRODUCT, 79 NULL, NULL 80 }, 81 { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_DRIVEV2_5 }, 82 UMASS_WPROTO_BBB, UMASS_CPROTO_ISD_ATA, 83 0, 84 0, 85 UMATCH_VENDOR_PRODUCT, 86 NULL, NULL 87 }, 88 89 { { USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE }, 90 UMASS_WPROTO_CBI, UMASS_CPROTO_ATAPI, 91 0, 92 0, 93 UMATCH_VENDOR_PRODUCT, 94 umass_init_insystem, NULL 95 }, 96 97 { { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB }, 98 UMASS_WPROTO_CBI_I, UMASS_CPROTO_ATAPI, 99 0, 100 0, 101 UMATCH_VENDOR_PRODUCT, 102 umass_init_shuttle, NULL 103 }, 104 105 /* 106 * These work around genuine device bugs -- returning the wrong info in 107 * the CSW block. 108 */ 109 { { USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1 }, 110 UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, 111 UMASS_QUIRK_WRONG_CSWSIG, 112 0, 113 UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, 114 NULL, NULL 115 }, 116 { { USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R }, 117 UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, 118 UMASS_QUIRK_WRONG_CSWTAG, 119 0, 120 UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, 121 NULL, NULL 122 }, 123 124 { { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_ORCA }, 125 UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, 126 UMASS_QUIRK_WRONG_CSWTAG, 127 0, 128 UMATCH_VENDOR_PRODUCT, 129 NULL, NULL 130 }, 131 132 /* 133 * Some Sony cameras advertise a subclass code of 0xff, so we force it 134 * to the correct value iff necessary. 135 */ 136 { { USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC }, 137 UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, 138 0, 139 0, 140 UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, 141 NULL, umass_fixup_sony 142 }, 143 144 /* 145 * The DiskOnKey does not reject commands it doesn't recognize in a 146 * sane way -- rather than STALLing the bulk pipe, it continually NAKs 147 * until we time out. To prevent being screwed by this, for now we 148 * disable 10-byte MODE SENSE the klugy way. - mycroft, 2003/10/16 149 */ 150 { { USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY }, 151 UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, 152 0, 153 PQUIRK_NOBIGMODESENSE, 154 UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, 155 NULL, NULL 156 }, 157 { { USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY2 }, 158 UMASS_WPROTO_UNSPEC, UMASS_CPROTO_UNSPEC, 159 0, 160 PQUIRK_NOBIGMODESENSE, 161 UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO, 162 NULL, NULL 163 }, 164 }; 165 166 const struct umass_quirk * 167 umass_lookup(u_int16_t vendor, u_int16_t product) 168 { 169 return ((const struct umass_quirk *) 170 usb_lookup(umass_quirks, vendor, product)); 171 } 172 173 Static usbd_status 174 umass_init_insystem(struct umass_softc *sc) 175 { 176 usbd_status err; 177 178 err = usbd_set_interface(sc->sc_iface, 1); 179 if (err) { 180 DPRINTF(UDMASS_USB, 181 ("%s: could not switch to Alt Interface 1\n", 182 USBDEVNAME(sc->sc_dev))); 183 return (err); 184 } 185 186 return (USBD_NORMAL_COMPLETION); 187 } 188 189 Static usbd_status 190 umass_init_shuttle(struct umass_softc *sc) 191 { 192 usb_device_request_t req; 193 u_int8_t status[2]; 194 195 /* The Linux driver does this */ 196 req.bmRequestType = UT_READ_VENDOR_DEVICE; 197 req.bRequest = 1; 198 USETW(req.wValue, 0); 199 USETW(req.wIndex, sc->sc_ifaceno); 200 USETW(req.wLength, sizeof(status)); 201 202 return (usbd_do_request(sc->sc_udev, &req, &status)); 203 } 204 205 Static void 206 umass_fixup_sony(struct umass_softc *sc) 207 { 208 usb_interface_descriptor_t *id; 209 210 id = usbd_get_interface_descriptor(sc->sc_iface); 211 if (id->bInterfaceSubClass == 0xff) 212 sc->sc_cmd = UMASS_CPROTO_SCSI; 213 } 214