xref: /haiku/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h (revision 22a6e4bb80ac3242749093f607dd4b9d0bd6f34e)
1 /*
2  * Copyright 2009, Michael Lotz, mmlr@mlotz.ch.
3  * Copyright 2008, Marcus Overhagen.
4  * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
5  * Copyright 2002-2003, Thomas Kurschel.
6  *
7  * Distributed under the terms of the MIT License.
8  */
9 #ifndef ATA_PRIVATE_H
10 #define ATA_PRIVATE_H
11 
12 #include <ata_types.h>
13 #include <bus/ATA.h>
14 #include <bus/SCSI.h>
15 #include <device_manager.h>
16 #include <lock.h>
17 #include <new>
18 #include <safemode.h>
19 #include <scsi_cmds.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <util/AutoLock.h>
23 
24 #include "ATACommands.h"
25 #include "ATAInfoblock.h"
26 #include "ATATracing.h"
27 
28 #define ATA_BLOCK_SIZE				512 /* TODO: retrieve */
29 #define ATA_MAX_DMA_FAILURES		3
30 #define ATA_STANDARD_TIMEOUT		10 * 1000 * 1000
31 #define ATA_RELEASE_TIMEOUT			10 * 1000 * 1000
32 #define ATA_SIGNATURE_ATA			0x0000
33 #define ATA_SIGNATURE_ATAPI			0xeb14
34 #define ATA_SIGNATURE_SATA			0xc33c
35 #define ATA_SIM_MODULE_NAME			"bus_managers/ata/sim/driver_v1"
36 #define ATA_CHANNEL_ID_GENERATOR	"ide/channel_id"
37 #define ATA_CHANNEL_ID_ITEM			"ide/channel_id"
38 
39 enum {
40 	ATA_DEVICE_READY_REQUIRED	= 0x01,
41 	ATA_IS_WRITE				= 0x02,
42 	ATA_DMA_TRANSFER			= 0x04,
43 	ATA_CHECK_ERROR_BIT			= 0x08,
44 	ATA_WAIT_FINISH				= 0x10,
45 	ATA_WAIT_ANY_BIT			= 0x20,
46 	ATA_CHECK_DEVICE_FAULT		= 0x40
47 };
48 
49 
50 class ATADevice;
51 class ATARequest;
52 
53 extern scsi_for_sim_interface *gSCSIModule;
54 extern device_manager_info *gDeviceManager;
55 
56 bool copy_sg_data(scsi_ccb *ccb, uint offset, uint allocationLength,
57 	void *buffer, int size, bool toBuffer);
58 
59 class ATAChannel {
60 public:
61 									ATAChannel(device_node *node);
62 									~ATAChannel();
63 
64 		status_t					InitCheck();
65 		uint32						ChannelID() { return fChannelID; };
66 
67 		// SCSI stuff
68 		void						SetBus(scsi_bus bus);
69 		scsi_bus					Bus() { return fSCSIBus; };
70 		status_t					ScanBus();
71 
72 		void						PathInquiry(scsi_path_inquiry *info);
73 		void						GetRestrictions(uint8 targetID,
74 										bool *isATAPI, bool *noAutoSense,
75 										uint32 *maxBlocks);
76 		status_t					ExecuteIO(scsi_ccb *ccb);
77 
78 		// ATA stuff
79 		status_t					SelectDevice(uint8 index);
80 		uint8						SelectedDevice();
81 
82 		status_t					Reset(bool *presence, uint16 *signatures);
83 
84 		bool						UseDMA() { return fUseDMA; };
85 
86 		status_t					Wait(uint8 setBits, uint8 clearedBits,
87 										uint32 flags, bigtime_t timeout);
88 		status_t					WaitDataRequest(bool high);
89 		status_t					WaitDeviceReady();
90 		status_t					WaitForIdle();
91 
92 		void						PrepareWaitingForInterrupt();
93 		status_t					WaitForInterrupt(bigtime_t timeout);
94 
95 		// request handling
96 		status_t					SendRequest(ATARequest *request,
97 										uint32 flags);
98 		status_t					FinishRequest(ATARequest *request,
99 										uint32 flags, uint8 errorMask);
100 
101 		// data transfers
102 		status_t					PrepareDMA(ATARequest *request);
103 		status_t					StartDMA();
104 		status_t					FinishDMA();
105 
106 		status_t					ExecutePIOTransfer(ATARequest *request);
107 
108 		status_t					ReadRegs(ATADevice *device);
109 		uint8						AltStatus();
110 		bool						IsDMAInterruptSet();
111 
112 		status_t					ReadPIO(uint8 *buffer, size_t length);
113 		status_t					WritePIO(uint8 *buffer, size_t length);
114 
115 		status_t					Interrupt(uint8 status);
116 
117 private:
118 		status_t					_ReadRegs(ata_task_file *taskFile,
119 										ata_reg_mask mask);
120 		status_t					_WriteRegs(ata_task_file *taskFile,
121 										ata_reg_mask mask);
122 		status_t					_WriteControl(uint8 value);
123 
124 		void						_FlushAndWait(bigtime_t waitTime);
125 
126 		status_t					_ReadPIOBlock(ATARequest *request,
127 										size_t length);
128 		status_t					_WritePIOBlock(ATARequest *request,
129 										size_t length);
130 		status_t					_TransferPIOBlock(ATARequest *request,
131 										size_t length, size_t *transferred);
132 		status_t					_TransferPIOPhysical(ATARequest *request,
133 										addr_t physicalAddress, size_t length,
134 										size_t *transferred);
135 		status_t					_TransferPIOVirtual(ATARequest *request,
136 										uint8 *virtualAddress, size_t length,
137 										size_t *transferred);
138 
139 		const char *				_DebugContext() { return fDebugContext; };
140 
141 		device_node *				fNode;
142 		uint32						fChannelID;
143 		ata_controller_interface *	fController;
144 		void *						fCookie;
145 
146 		spinlock					fInterruptLock;
147 		ConditionVariable			fInterruptCondition;
148 		ConditionVariableEntry		fInterruptConditionEntry;
149 		bool						fExpectsInterrupt;
150 
151 		status_t					fStatus;
152 		scsi_bus					fSCSIBus;
153 		uint8						fDeviceCount;
154 		ATADevice **				fDevices;
155 		bool						fUseDMA;
156 		ATARequest *				fRequest;
157 
158 		char						fDebugContext[16];
159 };
160 
161 
162 class ATADevice {
163 public:
164 									ATADevice(ATAChannel *channel,
165 										uint8 index);
166 virtual								~ATADevice();
167 
168 		// SCSI stuff
169 		status_t					ModeSense(ATARequest *request);
170 		status_t					TestUnitReady(ATARequest *request);
171 		status_t					SynchronizeCache(ATARequest *request);
172 		status_t					Eject(ATARequest *request);
173 		status_t					Inquiry(ATARequest *request);
174 		status_t					ReadCapacity(ATARequest *request);
175 virtual	status_t					ExecuteIO(ATARequest *request);
176 
177 		void						GetRestrictions(bool *noAutoSense,
178 										uint32 *maxBlocks);
179 
180 		// ATA stuff
181 virtual	bool						IsATAPI() { return false; };
182 
183 		bool						UseDMA() { return fUseDMA; };
184 		bool						Use48Bits() { return fUse48Bits; };
185 
186 		status_t					Select();
187 
188 		ata_task_file *				TaskFile() { return &fTaskFile; };
189 		ata_reg_mask				RegisterMask() { return fRegisterMask; };
190 
191 		status_t					SetFeature(int feature);
192 		status_t					DisableCommandQueueing();
193 		status_t					ConfigureDMA();
194 
195 virtual	status_t					Configure();
196 		status_t					Identify();
197 
198 		status_t					ExecuteReadWrite(ATARequest *request,
199 										uint64 address, uint32 sectorCount);
200 
201 protected:
202 		const char *				_DebugContext() { return fDebugContext; };
203 
204 		ATAChannel *				fChannel;
205 		ata_device_infoblock		fInfoBlock;
206 		ata_task_file				fTaskFile;
207 		ata_reg_mask				fRegisterMask;
208 
209 		bool						fUseDMA;
210 		uint8						fDMAMode;
211 		uint8						fDMAFailures;
212 
213 private:
214 		status_t					_FillTaskFile(ATARequest *request,
215 										uint64 address);
216 
217 		uint8						fIndex;
218 		bool						fUse48Bits;
219 		uint64						fTotalSectors;
220 
221 		char						fDebugContext[16];
222 };
223 
224 
225 class ATAPIDevice : public ATADevice {
226 public:
227 									ATAPIDevice(ATAChannel *channel,
228 										uint8 index);
229 virtual								~ATAPIDevice();
230 
231 		status_t					SendPacket(ATARequest *request);
232 virtual	status_t					ExecuteIO(ATARequest *request);
233 
234 virtual	bool						IsATAPI() { return true; };
235 
236 virtual	status_t					Configure();
237 
238 private:
239 		status_t					_FillTaskFilePacket(ATARequest *request);
240 		status_t					_FinishRequest(ATARequest *request,
241 										uint32 flags);
242 
243 		uint8						fPacket[12];
244 };
245 
246 
247 class ATARequest {
248 public:
249 									ATARequest(bool hasLock);
250 									~ATARequest();
251 
252 		void						SetStatus(uint8 status);
253 		uint8						Status() { return fStatus; };
254 
255 		void						ClearSense();
256 		void						SetSense(uint8 key, uint16 codeQualifier);
257 		uint8						SenseKey() { return fSenseKey; };
258 		uint8						SenseCode() { return fSenseCode; };
259 		uint8						SenseQualifier() { return fSenseQualifier; };
260 
261 		void						SetDevice(ATADevice *device);
262 		ATADevice *					Device() { return fDevice; };
263 
264 		void						SetTimeout(bigtime_t timeout);
265 		bigtime_t					Timeout() { return fTimeout; };
266 
267 		void						SetIsWrite(bool isWrite);
268 		bool						IsWrite() { return fIsWrite; };
269 
270 		void						SetUseDMA(bool useDMA);
271 		bool						UseDMA() { return fUseDMA; };
272 
273 		void						SetBytesLeft(uint32 bytesLeft);
274 		size_t *					BytesLeft() { return &fBytesLeft; };
275 
276 		bool						HasData() { return fCCB->data_length > 0; };
277 		bool						HasSense() { return fSenseKey != 0; };
278 
279 		status_t					Finish(bool resubmit);
280 
281 		// SCSI stuff
282 		status_t					Start(scsi_ccb *ccb);
283 		scsi_ccb *					CCB() { return fCCB; };
284 
285 		void						PrepareSGInfo();
286 		void						AdvanceSG(uint32 bytes);
287 
288 		uint32						SGElementsLeft()
289 										{ return fSGElementsLeft; };
290 		const physical_entry *		CurrentSGElement()
291 										{ return fCurrentSGElement; };
292 		uint32						CurrentSGOffset()
293 										{ return fCurrentSGOffset; };
294 
295 		void						SetOddByte(uint8 byte);
296 		bool						GetOddByte(uint8 *byte);
297 
298 		void						RequestSense();
299 
300 private:
301 		void						_FillSense(scsi_sense *sense);
302 
303 		const char *				_DebugContext() { return " request"; };
304 
305 		mutex						fLock;
306 		bool						fHasLock;
307 
308 		uint8						fStatus;
309 		uint8						fSenseKey;
310 		uint8						fSenseCode;
311 		uint8						fSenseQualifier;
312 
313 		ATADevice *					fDevice;
314 		bigtime_t					fTimeout;
315 		size_t						fBytesLeft;
316 		bool						fIsWrite;
317 		bool						fUseDMA;
318 		scsi_ccb *					fCCB;
319 
320 		uint32						fSGElementsLeft;
321 		const physical_entry *		fCurrentSGElement;
322 		uint32						fCurrentSGOffset;
323 		bool						fHasOddByte;
324 		uint8						fOddByte;
325 };
326 
327 #endif // ATA_PRIVATE_H
328