|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
24: *
25: * IOATAHDCommand.cpp - Performs ATA command processing.
26: *
27: * HISTORY
28: * Aug 27, 1999 jliu - Ported from AppleATADrive.
29: */
30:
31: #include <IOKit/assert.h>
32: #include <IOKit/IOSyncer.h>
33: #include <IOKit/storage/ata/IOATAHDDrive.h>
34:
35: // Enable this define to generate debugging messages.
36: // #define DEBUG_LOG 1
37:
38: // --------------------------------------------------------------------------
39: // Set the device timings.
40:
41: bool
42: IOATAHDDrive::selectTimingProtocol(ATATimingProtocol protocol)
43: {
44: bool ret;
45: UInt8 ataReadCmd;
46: UInt8 ataWriteCmd;
47:
48: if (protocol >= ataMaxTimings)
49: {
50: // If protocol override is invalid, get the list of supported timing
51: // protocols from the device, and use the 'best' one. If the device
52: // cannot report the available protocols, default to PIO mode.
53:
54: ret = _ataDevice->getTimingsSupported(&protocol);
55: if (!ret)
56: {
57: IOLog("%s: getTimingsSupported() error\n", getName());
58: protocol = ataTimingPIO;
59: }
60: }
61:
62: // IOLog("%s: timing protocols: %08x\n", getName(), protocol);
63:
64: if (protocol & (ataTimingUltraDMA66 | ataTimingUltraDMA33 | ataTimingDMA))
65: {
66: if (protocol & ataTimingUltraDMA66)
67: {
68: IOLog("%s: Using U-DMA/66 transfers\n", getName());
69: protocol = ataTimingUltraDMA66;
70: }
71: else if (protocol & ataTimingUltraDMA33)
72: {
73: IOLog("%s: Using U-DMA/33 transfers\n", getName());
74: protocol = ataTimingUltraDMA33;
75: }
76: else
77: {
78: IOLog("%s: Using DMA transfers\n", getName());
79: protocol = ataTimingDMA;
80: }
81:
82: ataReadCmd = kIOATACommandReadDMA;
83: ataWriteCmd = kIOATACommandWriteDMA;
84: selectCommandProtocol(true);
85: }
86: else
87: {
88: IOLog("%s: Using PIO transfers\n", getName());
89: protocol = ataTimingPIO;
90: ataReadCmd = kIOATACommandReadPIO;
91: ataWriteCmd = kIOATACommandWritePIO;
92: selectCommandProtocol(false);
93: }
94:
95: ret = _ataDevice->selectTiming(protocol);
96: if (!ret) {
97: IOLog("%s: selectTiming() failed\n", getName());
98: }
99: else {
100: _timingProtocol = protocol;
101: _ataReadCmd = ataReadCmd;
102: _ataWriteCmd = ataWriteCmd;
103: }
104:
105: return ret;
106: }
107:
108: // --------------------------------------------------------------------------
109: // Returns the Command protocol to use (e.g. ataProtocolPIO, ataProtocolDMA).
110:
111: void
112: IOATAHDDrive::selectCommandProtocol(bool useDMA)
113: {
114: if (useDMA)
115: _ataProtocol = ataProtocolDMA;
116: else
117: _ataProtocol = ataProtocolPIO;
118: }
119:
120: // --------------------------------------------------------------------------
121: // Setup an ATATaskFile from the parameters given, and write the taskfile
122: // to the ATATaskfile structure pointer provided.
123: //
124: // taskfile - pointer to a taskfile structure.
125: // protocol - An ATA transfer protocol (ataProtocolPIO, ataProtocolDMA, etc)
126: // command - ATA command byte.
127: // block - Initial transfer block.
128: // nblks - Number of blocks to transfer.
129:
130: void
131: IOATAHDDrive::setupReadWriteTaskFile(ATATaskfile * taskfile,
132: ATAProtocol protocol,
133: UInt8 command,
134: UInt32 block,
135: UInt32 nblks)
136: {
137: taskfile->protocol = protocol;
138:
139: // Mask of all taskfile registers that shall contain valid
140: // data and should be written to the hardware registers.
141: //
142: taskfile->regmask = ATARegtoMask(ataRegSectorNumber) |
143: ATARegtoMask(ataRegCylinderLow) |
144: ATARegtoMask(ataRegCylinderHigh) |
145: ATARegtoMask(ataRegDriveHead) |
146: ATARegtoMask(ataRegSectorCount) |
147: ATARegtoMask(ataRegCommand);
148:
149: taskfile->resultmask = 0;
150:
151: taskfile->ataRegs[ataRegSectorNumber] = block & 0x0ff;
152: taskfile->ataRegs[ataRegCylinderLow] = (block >> 8) & 0xff;
153: taskfile->ataRegs[ataRegCylinderHigh] = (block >> 16) & 0xff;
154: taskfile->ataRegs[ataRegDriveHead] = ((block >> 24) & 0x0f) |
155: ataModeLBA | (_unit << 4);
156: taskfile->ataRegs[ataRegSectorCount] = (nblks == kIOATAMaxBlocksPerXfer) ?
157: 0 : nblks;
158: taskfile->ataRegs[ataRegCommand] = command;
159: }
160:
161: // --------------------------------------------------------------------------
162: // Allocate and return an IOATACommand that is initialized to perform
163: // a read/write operation.
164: //
165: // buffer - IOMemoryDescriptor object describing this transfer.
166: // block - Initial transfer block.
167: // nblks - Number of blocks to transfer.
168:
169: IOATACommand *
170: IOATAHDDrive::ataCommandReadWrite(IOMemoryDescriptor * buffer,
171: UInt32 block,
172: UInt32 nblks)
173: {
174: ATATaskfile taskfile;
175: bool isWrite;
176:
177: assert(buffer);
178:
179: IOATACommand * cmd = allocateCommand();
180: if (!cmd) return 0; // error, command allocation failed.
181:
182: isWrite = (buffer->getDirection() == kIODirectionOut) ?
183: true : false;
184:
185: #ifdef DEBUG_LOG
186: IOLog("%s: ataCommandReadWrite %08x (%d) %s %d %d\n",
187: getName(),
188: buffer,
189: buffer->getLength(),
190: isWrite ? "WR" : "RD",
191: block,
192: nblks);
193: #endif
194:
195: #if 0 // used for testing - force PIO mode
196: setupReadWriteTaskFile(&taskfile,
197: ataProtocolPIO,
198: isWrite ? kIOATACommandWritePIO :
199: kIOATACommandReadPIO,
200: block,
201: nblks);
202: #else
203:
204: // Setup the taskfile structure with the size and direction of the
205: // transfer. This structure will be written to the actual taskfile
206: // registers when this command is processed.
207: //
208: setupReadWriteTaskFile(&taskfile,
209: _ataProtocol,
210: isWrite ? _ataWriteCmd : _ataReadCmd,
211: block,
212: nblks);
213: #endif
214:
215: // Get a pointer to the client data buffer, and record parameters
216: // which shall be later used by the completion routine.
217: //
218: IOATAClientData * clientData = ATA_CLIENT_DATA(cmd);
219: assert(clientData);
220:
221: clientData->buffer = buffer;
222:
223: cmd->setTaskfile(&taskfile);
224:
225: cmd->setPointers(buffer, /* (IOMemoryDescriptor *) */
226: buffer->getLength(), /* transferCount (bytes) */
227: isWrite); /* isWrite */
228:
229: return cmd;
230: }
231:
232: // --------------------------------------------------------------------------
233: // Allocate and return a ATA SetFeatures command.
234:
235: IOATACommand *
236: IOATAHDDrive::ataCommandSetFeatures(UInt8 features,
237: UInt8 SectorCount,
238: UInt8 SectorNumber,
239: UInt8 CylinderLow,
240: UInt8 CyclinderHigh)
241: {
242: ATATaskfile taskfile;
243:
244: IOATACommand * cmd = allocateCommand();
245: if (!cmd) return 0; // error, command allocation failed.
246:
247: taskfile.protocol = ataProtocolSetRegs;
248:
249: taskfile.regmask = ATARegtoMask(ataRegSectorNumber) |
250: ATARegtoMask(ataRegCylinderLow) |
251: ATARegtoMask(ataRegCylinderHigh) |
252: ATARegtoMask(ataRegDriveHead) |
253: ATARegtoMask(ataRegSectorCount) |
254: ATARegtoMask(ataRegCommand);
255:
256: taskfile.resultmask = ATARegtoMask(ataRegError) |
257: ATARegtoMask(ataRegStatus);
258:
259: taskfile.ataRegs[ataRegFeatures] = features;
260: taskfile.ataRegs[ataRegSectorNumber] = SectorNumber;
261: taskfile.ataRegs[ataRegCylinderLow] = CylinderLow;
262: taskfile.ataRegs[ataRegCylinderHigh] = CyclinderHigh;
263: taskfile.ataRegs[ataRegDriveHead] = ataModeLBA | (_unit << 4);
264: taskfile.ataRegs[ataRegSectorCount] = SectorCount;
265: taskfile.ataRegs[ataRegCommand] = kIOATACommandSetFeatures;
266:
267: cmd->setTaskfile(&taskfile);
268:
269: return cmd;
270: }
271:
272: // --------------------------------------------------------------------------
273: // This method is responsible for calling the client's completion routine
274: // for an async command.
275:
276: void
277: IOATAHDDrive::completionCallback(IOService * target,
278: gdCompletionFunction action,
279: void * param,
280: UInt32 bytesTransferred,
281: IOReturn status)
282: {
283: (*action)(target, param, bytesTransferred, status);
284: }
285:
286: // --------------------------------------------------------------------------
287: // This routine is called by our provider when a command processing has
288: // completed. We currently do not use the 'refcon' argument.
289:
290: void
291: IOATAHDDrive::completionHandler(IOService * device,
292: IOATACommand * cmd,
293: void * refcon)
294: {
295: assert(cmd && device);
296:
297: ATAResults results;
298: IOATAClientData * clientData = ATA_CLIENT_DATA(cmd);
299:
300: assert(clientData);
301:
302: if ((cmd->getResults(&results) != ataReturnNoError) &&
303: (clientData->maxRetries-- > 0) &&
304: enqueueCommand(cmd))
305: return;
306:
307: #if 0
308: // Force command retry to test retry logic.
309: // Controller will reset the IOMemoryDescriptor's position, right?
310: //
311: cmd->getResults(&results);
312: if (clientData->maxRetries-- > 2) {
313: enqueueCommand(cmd);
314: return;
315: }
316: #endif
317:
318: #ifdef DEBUG_LOG
319: IOLog("%s: completionHandler %08x %08x %08x %08x %d\n",
320: getName(), device, cmd, refcon, getIOReturn(&results),
321: results.bytesTransferred);
322: #endif
323:
324: // Return ATAReturnCode for sync commands.
325: //
326: clientData->returnCode = results.returnCode;
327:
328: if (clientData->isSync) {
329: // For sync commands, unblock the client thread.
330: //
331: assert(clientData->completion.syncLock);
332: clientData->completion.syncLock->signal(); // unblock the client.
333: }
334: else {
335: // The TAP fields must be set for an async command.
336: // Signal the completion routine that the request has been completed.
337: //
338: assert(clientData->completion.async.action &&
339: clientData->completion.async.target);
340:
341: completionCallback(clientData->completion.async.target,
342: clientData->completion.async.action,
343: clientData->completion.async.param,
344: results.bytesTransferred,
345: getIOReturn(&results));
346: }
347:
348: // Release the IOMemoryDescriptor.
349: //
350: if (clientData->buffer)
351: clientData->buffer->release();
352:
353: // Command processing is complete, release the command object.
354: //
355: cmd->release();
356: }
357:
358: // --------------------------------------------------------------------------
359: // Issue a synchronous ATA command.
360:
361: ATAReturnCode
362: IOATAHDDrive::syncExecute(IOATACommand * cmd, /* command object */
363: UInt32 timeout, /* timeout in ms */
364: UInt retries) /* max retries */
365: {
366: IOATAClientData * clientData = ATA_CLIENT_DATA(cmd);
367:
368: // Bump the retain count on the command. The completion handler
369: // will decrement the retain count.
370: //
371: cmd->retain();
372:
373: // Set timeout and register the completion handler.
374: //
375: cmd->setTimeout(timeout);
376: cmd->setCallback(this,
377: (ATACallback) &IOATAHDDrive::completionHandler,
378: (void *) 0);
379:
380: // Increment the retain count on the IOMemoryDescriptor.
381: // Release when the completion routine gets called.
382: //
383: if (clientData->buffer)
384: clientData->buffer->retain();
385:
386: // Set the max retry count. If retry count is 0, then the command shall
387: // not be retried if an error occurs.
388: //
389: clientData->maxRetries = retries;
390: clientData->completion.syncLock = IOSyncer::create();
391: clientData->isSync = true;
392:
393: cmd->execute();
394: // enqueueCommand(cmd); // queue command and kick off workloop.
395:
396: // Block client thread on lock until the completion handler
397: // receives an indication that the processing is complete.
398: //
399: clientData->completion.syncLock->wait();
400:
401: return clientData->returnCode;
402: }
403:
404: // --------------------------------------------------------------------------
405: // Issue an asynchronous ATA command.
406:
407: ATAReturnCode
408: IOATAHDDrive::asyncExecute(IOATACommand * cmd, /* command object */
409: IOService * target,
410: gdCompletionFunction action,
411: void * param,
412: UInt32 timeout, /* timeout in ms */
413: UInt retries) /* max retries */
414: {
415: IOATAClientData * clientData = ATA_CLIENT_DATA(cmd);
416:
417: // For async commands, the completion target/action must have
418: // not be 0.
419: //
420: if ((target && action) == 0)
421: return ataReturnNotSupported;
422:
423: // Bump the retain count on the command. The completion handler
424: // will decrement the retain count.
425: //
426: cmd->retain();
427:
428: // Set timeout and register the completion handler.
429: //
430: cmd->setTimeout(timeout);
431: cmd->setCallback(this,
432: (ATACallback) &IOATAHDDrive::completionHandler,
433: (void *) 0);
434:
435: // Increment the retain count on the IOMemoryDescriptor.
436: // Release when the completion routine gets called.
437: //
438: if (clientData->buffer)
439: clientData->buffer->retain();
440:
441: // Set the max retry count. If retry count is 0, then the command shall
442: // not be retried if an error occurs.
443: //
444: clientData->maxRetries = retries;
445: clientData->isSync = false;
446:
447: clientData->completion.async.target = target;
448: clientData->completion.async.action = action;
449: clientData->completion.async.param = param;
450:
451: return (cmd->execute() ? ataReturnNoError : ataReturnNoResource);
452: }
453:
454: // --------------------------------------------------------------------------
455: // Add a command to the retry/sync queue.
456:
457: bool
458: IOATAHDDrive::enqueueCommand(IOATACommand * cmd)
459: {
460: // Add command to the queue.
461: //
462: _retryQueue->enqueueCommand(cmd);
463:
464: // wake up the workloop.
465: //
466: _evSource->interruptOccurred(0, 0, 0);
467:
468: return true;
469: }
470:
471: // --------------------------------------------------------------------------
472: // Dequeues commands from the queue and executes them.
473:
474: void
475: IOATAHDDrive::dequeueCommands(IOInterruptEventSource * /*source*/,
476: int /*count*/)
477: {
478: _retryQueue->executeCommands();
479: }
480:
481: // --------------------------------------------------------------------------
482: // Allocate an IOATACommand object.
483:
484: IOATACommand *
485: IOATAHDDrive::allocateCommand()
486: {
487: IOATACommand * cmd;
488:
489: cmd = _ataDevice->allocCommand(sizeof(IOATAClientData));
490: return cmd;
491: }
492:
493: // ==========================================================================
494: // IOATACommandQueue
495: // ==========================================================================
496:
497: #define super OSObject
498: OSDefineMetaClassAndStructors(IOATACommandQueue, OSObject)
499:
500: // --------------------------------------------------------------------------
501: // Static member function which allocates and returns a queue object.
502:
503: IOATACommandQueue * IOATACommandQueue::commmandQueue()
504: {
505: IOATACommandQueue * queue = new IOATACommandQueue;
506:
507: if (queue && !queue->init()) {
508: queue->release();
509: queue = 0;
510: }
511:
512: return queue;
513: }
514:
515: // --------------------------------------------------------------------------
516: // Initializes the queue object.
517:
518: bool IOATACommandQueue::init()
519: {
520: _enabled = false;
521: _cmdLock = 0;
522: _qLock = 0;
523:
524: if (!super::init())
525: return false;
526:
527: // Initialize the queue.
528: //
529: queue_init(&_queue);
530:
531: _cmdLock = IORecursiveLockAlloc();
532: if (!_cmdLock)
533: return false;
534:
535: // Queue access is protected by a spinlock.
536: //
537: _qLock = IOSimpleLockAlloc();
538: if (!_qLock)
539: return false;
540:
541: return true;
542: }
543:
544: // --------------------------------------------------------------------------
545: // Frees the queue object.
546:
547: void IOATACommandQueue::free()
548: {
549: if (_qLock) {
550: IOSimpleLockFree(_qLock);
551: _qLock = 0;
552: }
553:
554: if (_cmdLock) {
555: IORecursiveLockFree(_cmdLock);
556: _cmdLock = 0;
557: }
558:
559: //
560: // What about IOATACommand objects in the queue?
561: //
562:
563: super::free();
564: }
565:
566: // --------------------------------------------------------------------------
567: // Dequeues and executes all IOATACommand objects in the queue.
568:
569: void IOATACommandQueue::executeCommands()
570: {
571: IOATAClientData * clientData;
572: IOATACommand * cmd;
573:
574: IORecursiveLockLock(_cmdLock);
575:
576: while (_enabled && !queue_empty(&_queue)) {
577: IOSimpleLockLock(_qLock);
578: queue_remove_first(&_queue, clientData, IOATAClientData *, link);
579: IOSimpleLockUnlock(_qLock);
580:
581: assert(clientData);
582:
583: cmd = clientData->command;
584:
585: #ifdef DEBUG_LOG
586: IOLog("cmd:%08x clientData:%08x ATA_CLIENT_DATA(cmd):%08x\n",
587: cmd, clientData, ATA_CLIENT_DATA(cmd));
588: #endif
589:
590: assert(cmd && (ATA_CLIENT_DATA(cmd) == clientData));
591:
592: cmd->execute();
593: }
594:
595: IORecursiveLockUnlock(_cmdLock);
596: }
597:
598: // --------------------------------------------------------------------------
599: // Enqueues an IOATACommand object to the queue.
600: // Returns true if the command specifed was enqueued.
601:
602: bool IOATACommandQueue::enqueueCommand(IOATACommand * cmd)
603: {
604: assert(cmd);
605:
606: IOATAClientData * clientData = ATA_CLIENT_DATA(cmd);
607:
608: // Make sure the clientData to IOATACommand linkage is correct.
609: //
610: clientData->command = cmd;
611:
612: #ifdef DEBUG_LOG
613: IOLog("enqueueCommand: %08x\n", (UInt) cmd);
614: #endif
615:
616: IOSimpleLockLock(_qLock);
617: queue_enter(&_queue, clientData, IOATAClientData *, link);
618: IOSimpleLockUnlock(_qLock);
619:
620: return true;
621: }
622:
623: // --------------------------------------------------------------------------
624: // Enable/disable the queue.
625:
626: void IOATACommandQueue::setEnabled(bool enable)
627: {
628: IORecursiveLockLock(_cmdLock);
629: _enabled = enable;
630: IORecursiveLockUnlock(_cmdLock);
631: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.