1 /* 2 * Copyright 2013, Jérôme Duval, korli@users.berlios.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef VIRTIO_SCSI_PRIVATE_H 6 #define VIRTIO_SCSI_PRIVATE_H 7 8 9 #include <bus/SCSI.h> 10 #include <condition_variable.h> 11 #include <lock.h> 12 #include <scsi_cmds.h> 13 #include <virtio.h> 14 15 #include "virtio_scsi.h" 16 17 18 //#define TRACE_VIRTIO_SCSI 19 #ifdef TRACE_VIRTIO_SCSI 20 # define TRACE(x...) dprintf("virtio_scsi: " x) 21 #else 22 # define TRACE(x...) ; 23 #endif 24 #define ERROR(x...) dprintf("\33[33mvirtio_scsi:\33[0m " x) 25 #define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 26 27 extern device_manager_info* gDeviceManager; 28 extern scsi_for_sim_interface *gSCSI; 29 30 bool copy_sg_data(scsi_ccb *ccb, uint offset, uint allocationLength, 31 void *buffer, int size, bool toBuffer); 32 void swap_words(void *data, size_t size); 33 34 35 #define VIRTIO_SCSI_STANDARD_TIMEOUT 10 * 1000 * 1000 36 #define VIRTIO_SCSI_INITIATOR_ID 7 37 38 #define VIRTIO_SCSI_NUM_EVENTS 4 39 40 41 class VirtioSCSIRequest; 42 43 44 class VirtioSCSIController { 45 public: 46 VirtioSCSIController(device_node* node); 47 ~VirtioSCSIController(); 48 49 status_t InitCheck(); 50 51 void SetBus(scsi_bus bus); 52 scsi_bus Bus() const { return fBus; } 53 54 void PathInquiry(scsi_path_inquiry* info); 55 void GetRestrictions(uint8 targetID, bool* isATAPI, 56 bool* noAutoSense, uint32* maxBlocks); 57 uchar ResetDevice(uchar targetID, uchar targetLUN); 58 status_t ExecuteRequest(scsi_ccb* request); 59 uchar AbortRequest(scsi_ccb* request); 60 uchar TerminateRequest(scsi_ccb* request); 61 status_t Control(uint8 targetID, uint32 op, 62 void* buffer, size_t length); 63 64 private: 65 static void _RequestCallback(void* driverCookie, 66 void *cookie); 67 void _RequestInterrupt(); 68 static void _EventCallback(void *driverCookie, void *cookie); 69 void _EventInterrupt(struct virtio_scsi_event* event); 70 static void _RescanChildBus(void *cookie); 71 72 void _SubmitEvent(uint32 event); 73 74 device_node* fNode; 75 scsi_bus fBus; 76 77 virtio_device_interface* fVirtio; 78 virtio_device* fVirtioDevice; 79 80 status_t fStatus; 81 struct virtio_scsi_config fConfig; 82 uint32 fFeatures; 83 ::virtio_queue fControlVirtioQueue; 84 ::virtio_queue fEventVirtioQueue; 85 ::virtio_queue fRequestVirtioQueue; 86 87 area_id fArea; 88 struct virtio_scsi_event* fEvents; 89 90 VirtioSCSIRequest* fRequest; 91 92 spinlock fInterruptLock; 93 ConditionVariable fInterruptCondition; 94 ConditionVariableEntry fInterruptConditionEntry; 95 bool fExpectsInterrupt; 96 97 scsi_dpc_cookie fEventDPC; 98 struct virtio_scsi_event fEventBuffers[VIRTIO_SCSI_NUM_EVENTS]; 99 }; 100 101 102 class VirtioSCSIRequest { 103 public: 104 VirtioSCSIRequest(bool hasLock); 105 ~VirtioSCSIRequest(); 106 107 void SetStatus(uint8 status); 108 uint8 Status() const { return fStatus; } 109 110 void SetTimeout(bigtime_t timeout); 111 bigtime_t Timeout() const { return fTimeout; } 112 113 bool HasSense() { 114 return (fResponse->sense_len > 0); } 115 116 void SetIsWrite(bool isWrite); 117 bool IsWrite() const { return fIsWrite; } 118 119 void SetBytesLeft(uint32 bytesLeft); 120 size_t* BytesLeft() { return &fBytesLeft; } 121 122 bool HasData() const 123 { return fCCB->data_length > 0; } 124 125 status_t Finish(bool resubmit); 126 127 // SCSI stuff 128 status_t Start(scsi_ccb *ccb); 129 scsi_ccb* CCB() { return fCCB; } 130 131 void RequestSense(); 132 133 void FillRequest(uint32 inCount, uint32 outCount, 134 physical_entry *entries); 135 136 private: 137 void _FillSense(scsi_sense *sense); 138 uchar _ResponseStatus(); 139 140 mutex fLock; 141 bool fHasLock; 142 143 uint8 fStatus; 144 145 bigtime_t fTimeout; 146 size_t fBytesLeft; 147 bool fIsWrite; 148 scsi_ccb* fCCB; 149 150 // virtio scsi 151 void* fBuffer; 152 struct virtio_scsi_cmd_req *fRequest; 153 struct virtio_scsi_cmd_resp *fResponse; 154 }; 155 156 157 #endif // VIRTIO_SCSI_PRIVATE_H 158 159