xref: /haiku/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h (revision 49271f23837306114f150793d96596b608265ae3)
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);
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;
84*6d42b430SJérôme Duval 			uint64				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 
9466d6afecSMichael Lotz 			int32				fCurrentRequest;
9582fda49eSJérôme Duval 			ConditionVariable	fInterruptCondition;
9682fda49eSJérôme Duval 
97e598dee7SJérôme Duval 			scsi_dpc_cookie		fEventDPC;
98e598dee7SJérôme Duval 			struct virtio_scsi_event fEventBuffers[VIRTIO_SCSI_NUM_EVENTS];
9982fda49eSJérôme Duval };
10082fda49eSJérôme Duval 
10182fda49eSJérôme Duval 
10282fda49eSJérôme Duval class VirtioSCSIRequest {
10382fda49eSJérôme Duval public:
10482fda49eSJérôme Duval 								VirtioSCSIRequest(bool hasLock);
10582fda49eSJérôme Duval 								~VirtioSCSIRequest();
10682fda49eSJérôme Duval 
10782fda49eSJérôme Duval 			void				SetStatus(uint8 status);
Status()10882fda49eSJérôme Duval 			uint8				Status() const { return fStatus; }
10982fda49eSJérôme Duval 
11082fda49eSJérôme Duval 			void				SetTimeout(bigtime_t timeout);
Timeout()11182fda49eSJérôme Duval 			bigtime_t			Timeout() const { return fTimeout; }
11282fda49eSJérôme Duval 
HasSense()11382fda49eSJérôme Duval 			bool				HasSense() {
11482fda49eSJérôme Duval 									return (fResponse->sense_len > 0); }
11582fda49eSJérôme Duval 
11682fda49eSJérôme Duval 			void				SetIsWrite(bool isWrite);
IsWrite()11782fda49eSJérôme Duval 			bool				IsWrite() const { return fIsWrite; }
11882fda49eSJérôme Duval 
11982fda49eSJérôme Duval 			void				SetBytesLeft(uint32 bytesLeft);
BytesLeft()12082fda49eSJérôme Duval 			size_t*				BytesLeft() { return &fBytesLeft; }
12182fda49eSJérôme Duval 
HasData()12282fda49eSJérôme Duval 			bool				HasData() const
12382fda49eSJérôme Duval 									{ return fCCB->data_length > 0; }
12482fda49eSJérôme Duval 
12582fda49eSJérôme Duval 			status_t			Finish(bool resubmit);
12666d6afecSMichael Lotz 			void				Abort();
12782fda49eSJérôme Duval 
12882fda49eSJérôme Duval 			// SCSI stuff
12982fda49eSJérôme Duval 			status_t			Start(scsi_ccb *ccb);
CCB()13082fda49eSJérôme Duval 			scsi_ccb*			CCB() { return fCCB; }
13182fda49eSJérôme Duval 
13282fda49eSJérôme Duval 			void				RequestSense();
13382fda49eSJérôme Duval 
13482fda49eSJérôme Duval 			void				FillRequest(uint32 inCount, uint32 outCount,
13582fda49eSJérôme Duval 									physical_entry *entries);
13682fda49eSJérôme Duval 
13782fda49eSJérôme Duval private:
13882fda49eSJérôme Duval 			void				_FillSense(scsi_sense *sense);
13982fda49eSJérôme Duval 			uchar				_ResponseStatus();
14082fda49eSJérôme Duval 
14182fda49eSJérôme Duval 			mutex				fLock;
14282fda49eSJérôme Duval 			bool				fHasLock;
14382fda49eSJérôme Duval 
14482fda49eSJérôme Duval 			uint8				fStatus;
14582fda49eSJérôme Duval 
14682fda49eSJérôme Duval 			bigtime_t			fTimeout;
14782fda49eSJérôme Duval 			size_t				fBytesLeft;
14882fda49eSJérôme Duval 			bool				fIsWrite;
14982fda49eSJérôme Duval 			scsi_ccb*			fCCB;
15082fda49eSJérôme Duval 
15182fda49eSJérôme Duval 			// virtio scsi
15282fda49eSJérôme Duval 			void*				fBuffer;
15382fda49eSJérôme Duval 			struct virtio_scsi_cmd_req *fRequest;
15482fda49eSJérôme Duval 			struct virtio_scsi_cmd_resp *fResponse;
15582fda49eSJérôme Duval };
15682fda49eSJérôme Duval 
15782fda49eSJérôme Duval 
15882fda49eSJérôme Duval #endif // VIRTIO_SCSI_PRIVATE_H
15982fda49eSJérôme Duval 
160