182fda49eSJérôme Duval /* 282fda49eSJérôme Duval * Copyright 2013, Jérôme Duval, korli@users.berlios.de. 382fda49eSJérôme Duval * Distributed under the terms of the MIT License. 482fda49eSJérôme Duval */ 582fda49eSJérôme Duval #ifndef VIRTIO_SCSI_PRIVATE_H 682fda49eSJérôme Duval #define VIRTIO_SCSI_PRIVATE_H 782fda49eSJérôme Duval 882fda49eSJérôme Duval 982fda49eSJérôme Duval #include <bus/SCSI.h> 1082fda49eSJérôme Duval #include <condition_variable.h> 1182fda49eSJérôme Duval #include <lock.h> 1282fda49eSJérôme Duval #include <scsi_cmds.h> 1382fda49eSJérôme Duval #include <virtio.h> 1482fda49eSJérôme Duval 1582fda49eSJérôme Duval #include "virtio_scsi.h" 1682fda49eSJérôme Duval 1782fda49eSJérôme Duval 1882fda49eSJérôme Duval //#define TRACE_VIRTIO_SCSI 1982fda49eSJérôme Duval #ifdef TRACE_VIRTIO_SCSI 2082fda49eSJérôme Duval # define TRACE(x...) dprintf("virtio_scsi: " x) 2182fda49eSJérôme Duval #else 2282fda49eSJérôme Duval # define TRACE(x...) ; 2382fda49eSJérôme Duval #endif 2482fda49eSJérôme Duval #define ERROR(x...) dprintf("\33[33mvirtio_scsi:\33[0m " x) 2582fda49eSJérôme Duval #define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 2682fda49eSJérôme Duval 2782fda49eSJérôme Duval extern device_manager_info* gDeviceManager; 2882fda49eSJérôme Duval extern scsi_for_sim_interface *gSCSI; 2982fda49eSJérôme Duval 3082fda49eSJérôme Duval bool copy_sg_data(scsi_ccb *ccb, uint offset, uint allocationLength, 3182fda49eSJérôme Duval void *buffer, int size, bool toBuffer); 3282fda49eSJérôme Duval void swap_words(void *data, size_t size); 3382fda49eSJérôme Duval 3482fda49eSJérôme Duval 3582fda49eSJérôme Duval #define VIRTIO_SCSI_STANDARD_TIMEOUT 10 * 1000 * 1000 3682fda49eSJérôme Duval #define VIRTIO_SCSI_INITIATOR_ID 7 3782fda49eSJérôme Duval 38e598dee7SJérôme Duval #define VIRTIO_SCSI_NUM_EVENTS 4 39e598dee7SJérôme Duval 4082fda49eSJérôme Duval 4182fda49eSJérôme Duval class VirtioSCSIRequest; 4282fda49eSJérôme Duval 4382fda49eSJérôme Duval 4482fda49eSJérôme Duval class VirtioSCSIController { 4582fda49eSJérôme Duval public: 4682fda49eSJérôme Duval VirtioSCSIController(device_node* node); 4782fda49eSJérôme Duval ~VirtioSCSIController(); 4882fda49eSJérôme Duval 4982fda49eSJérôme Duval status_t InitCheck(); 5082fda49eSJérôme Duval 5182fda49eSJérôme Duval void SetBus(scsi_bus bus); 5282fda49eSJérôme Duval scsi_bus Bus() const { return fBus; } 5382fda49eSJérôme Duval 5482fda49eSJérôme Duval void PathInquiry(scsi_path_inquiry* info); 5582fda49eSJérôme Duval void GetRestrictions(uint8 targetID, bool* isATAPI, 5682fda49eSJérôme Duval bool* noAutoSense, uint32* maxBlocks); 5782fda49eSJérôme Duval uchar ResetDevice(uchar targetID, uchar targetLUN); 5882fda49eSJérôme Duval status_t ExecuteRequest(scsi_ccb* request); 5982fda49eSJérôme Duval uchar AbortRequest(scsi_ccb* request); 6082fda49eSJérôme Duval uchar TerminateRequest(scsi_ccb* request); 6182fda49eSJérôme Duval status_t Control(uint8 targetID, uint32 op, 6282fda49eSJérôme Duval void* buffer, size_t length); 6382fda49eSJérôme Duval 6482fda49eSJérôme Duval private: 65ed4a8e4dSJérôme Duval static void _RequestCallback(void* driverCookie, 66ed4a8e4dSJérôme Duval void *cookie); 67ed4a8e4dSJérôme Duval void _RequestInterrupt(); 68d2fecacdSMichael Lotz static void _EventCallback(void *driverCookie, 69d2fecacdSMichael Lotz void *cookie); 70d2fecacdSMichael Lotz void _EventInterrupt( 71d2fecacdSMichael Lotz struct virtio_scsi_event* event); 72e598dee7SJérôme Duval static void _RescanChildBus(void *cookie); 73e598dee7SJérôme Duval 74e598dee7SJérôme Duval void _SubmitEvent(uint32 event); 7582fda49eSJérôme Duval 7682fda49eSJérôme Duval device_node* fNode; 7782fda49eSJérôme Duval scsi_bus fBus; 7882fda49eSJérôme Duval 7982fda49eSJérôme Duval virtio_device_interface* fVirtio; 8082fda49eSJérôme Duval virtio_device* fVirtioDevice; 8182fda49eSJérôme Duval 8282fda49eSJérôme Duval status_t fStatus; 8382fda49eSJérôme Duval struct virtio_scsi_config fConfig; 8482fda49eSJérôme Duval uint32 fFeatures; 8582fda49eSJérôme Duval ::virtio_queue fControlVirtioQueue; 8682fda49eSJérôme Duval ::virtio_queue fEventVirtioQueue; 8782fda49eSJérôme Duval ::virtio_queue fRequestVirtioQueue; 8882fda49eSJérôme Duval 8982fda49eSJérôme Duval area_id fArea; 9082fda49eSJérôme Duval struct virtio_scsi_event* fEvents; 9182fda49eSJérôme Duval 9282fda49eSJérôme Duval VirtioSCSIRequest* fRequest; 9382fda49eSJérôme Duval 94*66d6afecSMichael Lotz int32 fCurrentRequest; 9582fda49eSJérôme Duval ConditionVariable fInterruptCondition; 9682fda49eSJérôme Duval ConditionVariableEntry fInterruptConditionEntry; 9782fda49eSJérôme Duval 98e598dee7SJérôme Duval scsi_dpc_cookie fEventDPC; 99e598dee7SJérôme Duval struct virtio_scsi_event fEventBuffers[VIRTIO_SCSI_NUM_EVENTS]; 10082fda49eSJérôme Duval }; 10182fda49eSJérôme Duval 10282fda49eSJérôme Duval 10382fda49eSJérôme Duval class VirtioSCSIRequest { 10482fda49eSJérôme Duval public: 10582fda49eSJérôme Duval VirtioSCSIRequest(bool hasLock); 10682fda49eSJérôme Duval ~VirtioSCSIRequest(); 10782fda49eSJérôme Duval 10882fda49eSJérôme Duval void SetStatus(uint8 status); 10982fda49eSJérôme Duval uint8 Status() const { return fStatus; } 11082fda49eSJérôme Duval 11182fda49eSJérôme Duval void SetTimeout(bigtime_t timeout); 11282fda49eSJérôme Duval bigtime_t Timeout() const { return fTimeout; } 11382fda49eSJérôme Duval 11482fda49eSJérôme Duval bool HasSense() { 11582fda49eSJérôme Duval return (fResponse->sense_len > 0); } 11682fda49eSJérôme Duval 11782fda49eSJérôme Duval void SetIsWrite(bool isWrite); 11882fda49eSJérôme Duval bool IsWrite() const { return fIsWrite; } 11982fda49eSJérôme Duval 12082fda49eSJérôme Duval void SetBytesLeft(uint32 bytesLeft); 12182fda49eSJérôme Duval size_t* BytesLeft() { return &fBytesLeft; } 12282fda49eSJérôme Duval 12382fda49eSJérôme Duval bool HasData() const 12482fda49eSJérôme Duval { return fCCB->data_length > 0; } 12582fda49eSJérôme Duval 12682fda49eSJérôme Duval status_t Finish(bool resubmit); 127*66d6afecSMichael Lotz void Abort(); 12882fda49eSJérôme Duval 12982fda49eSJérôme Duval // SCSI stuff 13082fda49eSJérôme Duval status_t Start(scsi_ccb *ccb); 13182fda49eSJérôme Duval scsi_ccb* CCB() { return fCCB; } 13282fda49eSJérôme Duval 13382fda49eSJérôme Duval void RequestSense(); 13482fda49eSJérôme Duval 13582fda49eSJérôme Duval void FillRequest(uint32 inCount, uint32 outCount, 13682fda49eSJérôme Duval physical_entry *entries); 13782fda49eSJérôme Duval 13882fda49eSJérôme Duval private: 13982fda49eSJérôme Duval void _FillSense(scsi_sense *sense); 14082fda49eSJérôme Duval uchar _ResponseStatus(); 14182fda49eSJérôme Duval 14282fda49eSJérôme Duval mutex fLock; 14382fda49eSJérôme Duval bool fHasLock; 14482fda49eSJérôme Duval 14582fda49eSJérôme Duval uint8 fStatus; 14682fda49eSJérôme Duval 14782fda49eSJérôme Duval bigtime_t fTimeout; 14882fda49eSJérôme Duval size_t fBytesLeft; 14982fda49eSJérôme Duval bool fIsWrite; 15082fda49eSJérôme Duval scsi_ccb* fCCB; 15182fda49eSJérôme Duval 15282fda49eSJérôme Duval // virtio scsi 15382fda49eSJérôme Duval void* fBuffer; 15482fda49eSJérôme Duval struct virtio_scsi_cmd_req *fRequest; 15582fda49eSJérôme Duval struct virtio_scsi_cmd_resp *fResponse; 15682fda49eSJérôme Duval }; 15782fda49eSJérôme Duval 15882fda49eSJérôme Duval 15982fda49eSJérôme Duval #endif // VIRTIO_SCSI_PRIVATE_H 16082fda49eSJérôme Duval 161