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
27extern device_manager_info* gDeviceManager;
28extern scsi_for_sim_interface *gSCSI;
29
30bool copy_sg_data(scsi_ccb *ccb, uint offset, uint allocationLength,
31	void *buffer, int size, bool toBuffer);
32void 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
41class VirtioSCSIRequest;
42
43
44class VirtioSCSIController {
45public:
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
64private:
65	static	void				_RequestCallback(void* driverCookie,
66									void *cookie);
67			void				_RequestInterrupt();
68	static	void				_EventCallback(void *driverCookie,
69									void *cookie);
70			void				_EventInterrupt(
71									struct virtio_scsi_event* event);
72	static	void				_RescanChildBus(void *cookie);
73
74			void				_SubmitEvent(uint32 event);
75
76			device_node*		fNode;
77			scsi_bus			fBus;
78
79			virtio_device_interface* fVirtio;
80			virtio_device*		fVirtioDevice;
81
82			status_t			fStatus;
83			struct virtio_scsi_config	fConfig;
84			uint64				fFeatures;
85			::virtio_queue		fControlVirtioQueue;
86			::virtio_queue		fEventVirtioQueue;
87			::virtio_queue		fRequestVirtioQueue;
88
89			area_id				fArea;
90			struct virtio_scsi_event*	fEvents;
91
92			VirtioSCSIRequest*	fRequest;
93
94			int32				fCurrentRequest;
95			ConditionVariable	fInterruptCondition;
96			ConditionVariableEntry fInterruptConditionEntry;
97
98			scsi_dpc_cookie		fEventDPC;
99			struct virtio_scsi_event fEventBuffers[VIRTIO_SCSI_NUM_EVENTS];
100};
101
102
103class VirtioSCSIRequest {
104public:
105								VirtioSCSIRequest(bool hasLock);
106								~VirtioSCSIRequest();
107
108			void				SetStatus(uint8 status);
109			uint8				Status() const { return fStatus; }
110
111			void				SetTimeout(bigtime_t timeout);
112			bigtime_t			Timeout() const { return fTimeout; }
113
114			bool				HasSense() {
115									return (fResponse->sense_len > 0); }
116
117			void				SetIsWrite(bool isWrite);
118			bool				IsWrite() const { return fIsWrite; }
119
120			void				SetBytesLeft(uint32 bytesLeft);
121			size_t*				BytesLeft() { return &fBytesLeft; }
122
123			bool				HasData() const
124									{ return fCCB->data_length > 0; }
125
126			status_t			Finish(bool resubmit);
127			void				Abort();
128
129			// SCSI stuff
130			status_t			Start(scsi_ccb *ccb);
131			scsi_ccb*			CCB() { return fCCB; }
132
133			void				RequestSense();
134
135			void				FillRequest(uint32 inCount, uint32 outCount,
136									physical_entry *entries);
137
138private:
139			void				_FillSense(scsi_sense *sense);
140			uchar				_ResponseStatus();
141
142			mutex				fLock;
143			bool				fHasLock;
144
145			uint8				fStatus;
146
147			bigtime_t			fTimeout;
148			size_t				fBytesLeft;
149			bool				fIsWrite;
150			scsi_ccb*			fCCB;
151
152			// virtio scsi
153			void*				fBuffer;
154			struct virtio_scsi_cmd_req *fRequest;
155			struct virtio_scsi_cmd_resp *fResponse;
156};
157
158
159#endif // VIRTIO_SCSI_PRIVATE_H
160
161