1 /* 2 * Copyright 2004-2013, Haiku, Inc. All RightsReserved. 3 * Copyright 2002/03, Thomas Kurschel. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 #ifndef _SCSI_PERIPH_H 8 #define _SCSI_PERIPH_H 9 10 11 /*! Use this module to minimize work required to write a SCSI 12 peripheral driver. 13 14 It takes care of: 15 - error handling 16 - medium changes (including restarting the medium) 17 - detection of medium capacity 18 */ 19 20 21 #include <bus/SCSI.h> 22 #include <scsi_cmds.h> 23 #include <Drivers.h> 24 25 // cookie issued by module per device 26 typedef struct scsi_periph_device_info *scsi_periph_device; 27 // cookie issued by module per file handle 28 typedef struct scsi_periph_handle_info *scsi_periph_handle; 29 30 // "standardized" error code to simplify handling of scsi errors 31 typedef enum { 32 err_act_ok, // executed successfully 33 err_act_retry, // failed, retry 3 times 34 err_act_fail, // failed, don't retry 35 err_act_many_retries, // failed, retry multiple times (currently 10 times) 36 err_act_start, // devices requires a "start" command 37 err_act_invalid_req // request is invalid 38 } err_act; 39 40 // packed scsi command result 41 typedef struct err_res { 42 status_t error_code : 32; // Be error code 43 uint32 action : 8; // err_act code 44 } err_res; 45 46 #define MK_ERROR( aaction, code ) ({ \ 47 err_res _res = {error_code: (code), action: (aaction) }; \ 48 _res; \ 49 }) 50 51 // cookie issued by driver to identify itself 52 //typedef struct periph_info *periph_cookie; 53 // cookie issued by driver per device 54 typedef struct periph_device_info *periph_device_cookie; 55 // cookie issued by driver per file handle 56 typedef struct periph_handle_info *periph_handle_cookie; 57 58 typedef struct IOOperation io_operation; 59 60 // callbacks to be provided by peripheral driver 61 typedef struct scsi_periph_callbacks { 62 // *** block devices *** 63 // informs of new size of medium 64 // (set to NULL if not a block device) 65 void (*set_capacity)(periph_device_cookie cookie, uint64 capacity, 66 uint32 blockSize, uint32 physicalBlockSize); 67 68 // *** removable devices 69 // called when media got changed (can be NULL if medium is not changable) 70 // (you don't need to call periph->media_changed, but it's doesn't if you do) 71 // ccb - request at your disposal 72 void (*media_changed)(periph_device_cookie cookie, scsi_ccb *request); 73 } scsi_periph_callbacks; 74 75 typedef struct scsi_block_range { 76 // values are in blocks 77 uint64 lba; 78 uint64 size; 79 } scsi_block_range; 80 81 // functions provided by this module 82 typedef struct scsi_periph_interface { 83 module_info info; 84 85 // *** init/cleanup *** 86 // preferred_ccb_size - preferred command size; if zero, the shortest is used 87 status_t (*register_device)(periph_device_cookie cookie, 88 scsi_periph_callbacks *callbacks, scsi_device scsiDevice, 89 scsi_device_interface *scsi, device_node *node, bool removable, 90 int preferredCcbSize, scsi_periph_device *driver); 91 status_t (*unregister_device)(scsi_periph_device driver); 92 93 // *** basic command execution *** 94 // exec command, retrying on problems 95 status_t (*safe_exec)(scsi_periph_device periphCookie, scsi_ccb *request); 96 // exec simple command 97 status_t (*simple_exec)(scsi_periph_device device, void *cdb, 98 uint8 cdbLength, void *data, size_t dataLength, int ccbFlags); 99 100 // *** file handling *** 101 // to be called when a new file is opened 102 status_t (*handle_open)(scsi_periph_device device, 103 periph_handle_cookie periph_handle, scsi_periph_handle *_handle); 104 // to be called when a file is closed 105 status_t (*handle_close)(scsi_periph_handle handle); 106 // to be called when a file is freed 107 status_t (*handle_free)(scsi_periph_handle handle); 108 109 // *** default implementation for block devices *** 110 status_t (*read_write)(scsi_periph_device_info *device, scsi_ccb *request, 111 uint64 offset, size_t numBlocks, physical_entry* vecs, size_t vecCount, 112 bool isWrite, size_t* _bytesTransferred); 113 status_t (*io)(scsi_periph_device device, io_operation *operation, 114 size_t *_bytesTransferred); 115 116 // block ioctls 117 status_t (*ioctl)(scsi_periph_handle handle, int op, void *buffer, 118 size_t length); 119 // check medium capacity (calls set_capacity callback on success) 120 // request - ccb for this device; is used to talk to device 121 status_t (*check_capacity)(scsi_periph_device device, scsi_ccb *request); 122 123 // synchronizes (flush) the device cache 124 err_res (*synchronize_cache)(scsi_periph_device device, scsi_ccb *request); 125 126 status_t (*trim_device)(scsi_periph_device_info *device, scsi_ccb *request, 127 scsi_block_range* ranges, uint32 rangeCount, uint64* trimmedBlocks); 128 129 // *** removable media *** 130 // to be called when a medium change is detected to block subsequent commands 131 void (*media_changed)(scsi_periph_device device); 132 // convert result of *request to err_res 133 err_res (*check_error)(scsi_periph_device device, scsi_ccb *request); 134 // send start or stop command to device 135 // withLoadEject = true - include loading/ejecting, 136 // false - only do allow/deny 137 err_res (*send_start_stop)(scsi_periph_device device, scsi_ccb *request, 138 bool start, bool withLoadEject); 139 // checks media status and waits for device to become ready 140 // returns: B_OK, B_DEV_MEDIA_CHANGE_REQUESTED, B_NO_MEMORY or 141 // pending error reported by handle_get_error 142 status_t (*get_media_status)(scsi_periph_handle handle); 143 144 // compose device name consisting of prefix and path/target/LUN 145 // (result must be freed by caller) 146 char *(*compose_device_name)(device_node *device_node, const char *prefix); 147 } scsi_periph_interface; 148 149 #define SCSI_PERIPH_MODULE_NAME "generic/scsi_periph/v1" 150 151 #endif /* _SCSI_PERIPH_H */ 152