18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for USB Mass Storage compliant devices 48c2ecf20Sopenharmony_ci * Main Header File 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Current development and maintenance by: 78c2ecf20Sopenharmony_ci * (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Initial work by: 108c2ecf20Sopenharmony_ci * (c) 1999 Michael Gee (michael@linuxspecific.com) 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This driver is based on the 'USB Mass Storage Class' document. This 138c2ecf20Sopenharmony_ci * describes in detail the protocol used to communicate with such 148c2ecf20Sopenharmony_ci * devices. Clearly, the designers had SCSI and ATAPI commands in 158c2ecf20Sopenharmony_ci * mind when they created this document. The commands are all very 168c2ecf20Sopenharmony_ci * similar to commands in the SCSI-II and ATAPI specifications. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * It is important to note that in a number of cases this class 198c2ecf20Sopenharmony_ci * exhibits class-specific exemptions from the USB specification. 208c2ecf20Sopenharmony_ci * Notably the usage of NAK, STALL and ACK differs from the norm, in 218c2ecf20Sopenharmony_ci * that they are used to communicate wait, failed and OK on commands. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Also, for certain devices, the interrupt endpoint is used to convey 248c2ecf20Sopenharmony_ci * status of a command. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#ifndef _USB_H_ 288c2ecf20Sopenharmony_ci#define _USB_H_ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include <linux/usb.h> 318c2ecf20Sopenharmony_ci#include <linux/usb_usual.h> 328c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 338c2ecf20Sopenharmony_ci#include <linux/completion.h> 348c2ecf20Sopenharmony_ci#include <linux/mutex.h> 358c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 368c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h> 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistruct us_data; 398c2ecf20Sopenharmony_cistruct scsi_cmnd; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* 428c2ecf20Sopenharmony_ci * Unusual device list definitions 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct us_unusual_dev { 468c2ecf20Sopenharmony_ci const char* vendorName; 478c2ecf20Sopenharmony_ci const char* productName; 488c2ecf20Sopenharmony_ci __u8 useProtocol; 498c2ecf20Sopenharmony_ci __u8 useTransport; 508c2ecf20Sopenharmony_ci int (*initFunction)(struct us_data *); 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* Dynamic bitflag definitions (us->dflags): used in set_bit() etc. */ 558c2ecf20Sopenharmony_ci#define US_FLIDX_URB_ACTIVE 0 /* current_urb is in use */ 568c2ecf20Sopenharmony_ci#define US_FLIDX_SG_ACTIVE 1 /* current_sg is in use */ 578c2ecf20Sopenharmony_ci#define US_FLIDX_ABORTING 2 /* abort is in progress */ 588c2ecf20Sopenharmony_ci#define US_FLIDX_DISCONNECTING 3 /* disconnect in progress */ 598c2ecf20Sopenharmony_ci#define US_FLIDX_RESETTING 4 /* device reset in progress */ 608c2ecf20Sopenharmony_ci#define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */ 618c2ecf20Sopenharmony_ci#define US_FLIDX_SCAN_PENDING 6 /* scanning not yet done */ 628c2ecf20Sopenharmony_ci#define US_FLIDX_REDO_READ10 7 /* redo READ(10) command */ 638c2ecf20Sopenharmony_ci#define US_FLIDX_READ10_WORKED 8 /* previous READ(10) succeeded */ 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#define USB_STOR_STRING_LEN 32 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* 688c2ecf20Sopenharmony_ci * We provide a DMA-mapped I/O buffer for use with small USB transfers. 698c2ecf20Sopenharmony_ci * It turns out that CB[I] needs a 12-byte buffer and Bulk-only needs a 708c2ecf20Sopenharmony_ci * 31-byte buffer. But Freecom needs a 64-byte buffer, so that's the 718c2ecf20Sopenharmony_ci * size we'll allocate. 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#define US_IOBUF_SIZE 64 /* Size of the DMA-mapped I/O buffer */ 758c2ecf20Sopenharmony_ci#define US_SENSE_SIZE 18 /* Size of the autosense data buffer */ 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_citypedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*); 788c2ecf20Sopenharmony_citypedef int (*trans_reset)(struct us_data*); 798c2ecf20Sopenharmony_citypedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*); 808c2ecf20Sopenharmony_citypedef void (*extra_data_destructor)(void *); /* extra data destructor */ 818c2ecf20Sopenharmony_citypedef void (*pm_hook)(struct us_data *, int); /* power management hook */ 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define US_SUSPEND 0 848c2ecf20Sopenharmony_ci#define US_RESUME 1 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/* we allocate one of these for every device that we remember */ 878c2ecf20Sopenharmony_cistruct us_data { 888c2ecf20Sopenharmony_ci /* 898c2ecf20Sopenharmony_ci * The device we're working with 908c2ecf20Sopenharmony_ci * It's important to note: 918c2ecf20Sopenharmony_ci * (o) you must hold dev_mutex to change pusb_dev 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_ci struct mutex dev_mutex; /* protect pusb_dev */ 948c2ecf20Sopenharmony_ci struct usb_device *pusb_dev; /* this usb_device */ 958c2ecf20Sopenharmony_ci struct usb_interface *pusb_intf; /* this interface */ 968c2ecf20Sopenharmony_ci const struct us_unusual_dev *unusual_dev; 978c2ecf20Sopenharmony_ci /* device-filter entry */ 988c2ecf20Sopenharmony_ci unsigned long fflags; /* fixed flags from filter */ 998c2ecf20Sopenharmony_ci unsigned long dflags; /* dynamic atomic bitflags */ 1008c2ecf20Sopenharmony_ci unsigned int send_bulk_pipe; /* cached pipe values */ 1018c2ecf20Sopenharmony_ci unsigned int recv_bulk_pipe; 1028c2ecf20Sopenharmony_ci unsigned int send_ctrl_pipe; 1038c2ecf20Sopenharmony_ci unsigned int recv_ctrl_pipe; 1048c2ecf20Sopenharmony_ci unsigned int recv_intr_pipe; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci /* information about the device */ 1078c2ecf20Sopenharmony_ci char *transport_name; 1088c2ecf20Sopenharmony_ci char *protocol_name; 1098c2ecf20Sopenharmony_ci __le32 bcs_signature; 1108c2ecf20Sopenharmony_ci u8 subclass; 1118c2ecf20Sopenharmony_ci u8 protocol; 1128c2ecf20Sopenharmony_ci u8 max_lun; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci u8 ifnum; /* interface number */ 1158c2ecf20Sopenharmony_ci u8 ep_bInterval; /* interrupt interval */ 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* function pointers for this device */ 1188c2ecf20Sopenharmony_ci trans_cmnd transport; /* transport function */ 1198c2ecf20Sopenharmony_ci trans_reset transport_reset; /* transport device reset */ 1208c2ecf20Sopenharmony_ci proto_cmnd proto_handler; /* protocol handler */ 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci /* SCSI interfaces */ 1238c2ecf20Sopenharmony_ci struct scsi_cmnd *srb; /* current srb */ 1248c2ecf20Sopenharmony_ci unsigned int tag; /* current dCBWTag */ 1258c2ecf20Sopenharmony_ci char scsi_name[32]; /* scsi_host name */ 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* control and bulk communications data */ 1288c2ecf20Sopenharmony_ci struct urb *current_urb; /* USB requests */ 1298c2ecf20Sopenharmony_ci struct usb_ctrlrequest *cr; /* control requests */ 1308c2ecf20Sopenharmony_ci struct usb_sg_request current_sg; /* scatter-gather req. */ 1318c2ecf20Sopenharmony_ci unsigned char *iobuf; /* I/O buffer */ 1328c2ecf20Sopenharmony_ci dma_addr_t iobuf_dma; /* buffer DMA addresses */ 1338c2ecf20Sopenharmony_ci struct task_struct *ctl_thread; /* the control thread */ 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci /* mutual exclusion and synchronization structures */ 1368c2ecf20Sopenharmony_ci struct completion cmnd_ready; /* to sleep thread on */ 1378c2ecf20Sopenharmony_ci struct completion notify; /* thread begin/end */ 1388c2ecf20Sopenharmony_ci wait_queue_head_t delay_wait; /* wait during reset */ 1398c2ecf20Sopenharmony_ci struct delayed_work scan_dwork; /* for async scanning */ 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* subdriver information */ 1428c2ecf20Sopenharmony_ci void *extra; /* Any extra data */ 1438c2ecf20Sopenharmony_ci extra_data_destructor extra_destructor;/* extra data destructor */ 1448c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 1458c2ecf20Sopenharmony_ci pm_hook suspend_resume_hook; 1468c2ecf20Sopenharmony_ci#endif 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci /* hacks for READ CAPACITY bug handling */ 1498c2ecf20Sopenharmony_ci int use_last_sector_hacks; 1508c2ecf20Sopenharmony_ci int last_sector_retries; 1518c2ecf20Sopenharmony_ci}; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci/* Convert between us_data and the corresponding Scsi_Host */ 1548c2ecf20Sopenharmony_cistatic inline struct Scsi_Host *us_to_host(struct us_data *us) { 1558c2ecf20Sopenharmony_ci return container_of((void *) us, struct Scsi_Host, hostdata); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_cistatic inline struct us_data *host_to_us(struct Scsi_Host *host) { 1588c2ecf20Sopenharmony_ci return (struct us_data *) host->hostdata; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci/* Function to fill an inquiry response. See usb.c for details */ 1628c2ecf20Sopenharmony_ciextern void fill_inquiry_response(struct us_data *us, 1638c2ecf20Sopenharmony_ci unsigned char *data, unsigned int data_len); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/* 1668c2ecf20Sopenharmony_ci * The scsi_lock() and scsi_unlock() macros protect the sm_state and the 1678c2ecf20Sopenharmony_ci * single queue element srb for write access 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_ci#define scsi_unlock(host) spin_unlock_irq(host->host_lock) 1708c2ecf20Sopenharmony_ci#define scsi_lock(host) spin_lock_irq(host->host_lock) 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* General routines provided by the usb-storage standard core */ 1738c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 1748c2ecf20Sopenharmony_ciextern int usb_stor_suspend(struct usb_interface *iface, pm_message_t message); 1758c2ecf20Sopenharmony_ciextern int usb_stor_resume(struct usb_interface *iface); 1768c2ecf20Sopenharmony_ciextern int usb_stor_reset_resume(struct usb_interface *iface); 1778c2ecf20Sopenharmony_ci#else 1788c2ecf20Sopenharmony_ci#define usb_stor_suspend NULL 1798c2ecf20Sopenharmony_ci#define usb_stor_resume NULL 1808c2ecf20Sopenharmony_ci#define usb_stor_reset_resume NULL 1818c2ecf20Sopenharmony_ci#endif 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ciextern int usb_stor_pre_reset(struct usb_interface *iface); 1848c2ecf20Sopenharmony_ciextern int usb_stor_post_reset(struct usb_interface *iface); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ciextern int usb_stor_probe1(struct us_data **pus, 1878c2ecf20Sopenharmony_ci struct usb_interface *intf, 1888c2ecf20Sopenharmony_ci const struct usb_device_id *id, 1898c2ecf20Sopenharmony_ci const struct us_unusual_dev *unusual_dev, 1908c2ecf20Sopenharmony_ci struct scsi_host_template *sht); 1918c2ecf20Sopenharmony_ciextern int usb_stor_probe2(struct us_data *us); 1928c2ecf20Sopenharmony_ciextern void usb_stor_disconnect(struct usb_interface *intf); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ciextern void usb_stor_adjust_quirks(struct usb_device *dev, 1958c2ecf20Sopenharmony_ci unsigned long *fflags); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci#define module_usb_stor_driver(__driver, __sht, __name) \ 1988c2ecf20Sopenharmony_cistatic int __init __driver##_init(void) \ 1998c2ecf20Sopenharmony_ci{ \ 2008c2ecf20Sopenharmony_ci usb_stor_host_template_init(&(__sht), __name, THIS_MODULE); \ 2018c2ecf20Sopenharmony_ci return usb_register(&(__driver)); \ 2028c2ecf20Sopenharmony_ci} \ 2038c2ecf20Sopenharmony_cimodule_init(__driver##_init); \ 2048c2ecf20Sopenharmony_cistatic void __exit __driver##_exit(void) \ 2058c2ecf20Sopenharmony_ci{ \ 2068c2ecf20Sopenharmony_ci usb_deregister(&(__driver)); \ 2078c2ecf20Sopenharmony_ci} \ 2088c2ecf20Sopenharmony_cimodule_exit(__driver##_exit) 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci#endif 211