|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.0 (the 'License'). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License."
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: * Copyright 1997-1998 by Apple Computer, Inc., All rights reserved.
26: * Copyright 1994-1997 NeXT Software, Inc., All rights reserved.
27: *
28: * AtapiCnt.m - Implementation of ATAPI controller class.
29: *
30: * HISTORY
31: *
32: * 4-Jan-1998 Joe Liu at Apple
33: * Modified the ATAPI to SCSI translation routines.
34: *
35: * 31-Aug-1994 Rakesh Dubey at NeXT
36: * Created.
37: */
38:
39: //#define DEBUG
40: //#define COMMAND_HISTORY
41: //#define COMMAND_PRINT
42:
43: #import "IdeCnt.h"
44: #import "AtapiCnt.h"
45: #import "AtapiCntInternal.h"
46: #import <kern/assert.h>
47: #import <driverkit/kernelDriver.h>
48: #import <driverkit/interruptMsg.h>
49: #import <mach/mach_interface.h>
50: #import <driverkit/IODevice.h>
51: #import <driverkit/align.h>
52: #import <machkit/NXLock.h>
53: #import <machdep/i386/io_inline.h>
54: #import <bsd/dev/scsireg.h>
55:
56: /*
57: * opcode groups
58: */
59: #define SCSI_OPGROUP(opcode) ((opcode) & 0xe0)
60:
61: #define OPGROUP_0 0x00 /* six byte commands */
62: #define OPGROUP_1 0x20 /* ten byte commands */
63: #define OPGROUP_2 0x40 /* ten byte commands */
64: #define OPGROUP_5 0xa0 /* twelve byte commands */
65: #define OPGROUP_6 0xc0 /* six byte, vendor unique commands */
66: #define OPGROUP_7 0xe0 /* ten byte, vendor unique commands */
67:
68: #ifdef undef
69: static void testDebug(id driver);
70: #endif undef
71:
72: /*
73: * List of SCSI commands that do not have a counterpart in ATAPI
74: * implementation, or commands which have different command structure.
75: * These commands will need to be specially handled.
76: */
77: #define C10OP_MODESELECT 0x55
78:
79: static unsigned char mapToAtapi[] = {
80: C6OP_MODESELECT,
81: C10OP_MODESELECT,
82: C6OP_MODESENSE
83: };
84:
85: /*
86: * List of controllers that have been already probed. We need this since each
87: * Instance table lists IdeDisk as well as IdeController classes. And we need
88: * to create instances of disks attached to each controller only once.
89: */
90: static int probedControllerCount = 0;
91: static id probedControllers[MAX_IDE_CONTROLLERS];
92:
93: @implementation AtapiController
94:
95: + (BOOL)probe : deviceDescription
96: {
97:
98: int unit, i;
99: id direct;
100: id atapiCnt;
101:
102:
103: direct = [deviceDescription directDevice];
104:
105:
106: #ifdef undef
107: IOLog("AtapiController probed with direct device %x\n", direct);
108: #endif undef
109:
110: for (i = 0; i < probedControllerCount; i++) {
111: if (probedControllers[i] == direct) {
112: {
113: #ifdef undef
114: IOLog("AtapiController already probed for controller %x\n",
115: direct);
116: #endif undef
117: return YES;
118: }
119: }
120: }
121:
122: probedControllers[probedControllerCount++] = direct;
123:
124: for (unit = 0; unit < [direct numDevices]; unit++) {
125:
126: if ([direct isAtapiDevice:unit]) {
127: atapiCnt = [[self alloc]
128: initFromDeviceDescription:deviceDescription];
129:
130: if (atapiCnt == nil) {
131: IOLog("ATAPI: failed to probe device %d.\n", unit);
132: continue;
133: }
134:
135: #ifdef undef
136: IOLog("ATAPI: found ATAPI device %d.\n", unit);
137: #endif undef
138:
139: if ([atapiCnt initResources:direct] == nil) {
140: IOLog("ATAPI: failed to initialize device %d.\n", unit);
141: [atapiCnt free];
142: continue;
143: }
144:
145: /*
146: * To clear pending Unit attention. Not needed.
147: */
148: //[direct atapiRequestSense:NULL];
149:
150: /*
151: * Use this to test before we call registerDevice.
152: */
153: //testDebug(direct);
154:
155: if ([atapiCnt registerDevice] == nil) {
156: IOLog("ATAPI: failed to register device %d.\n", unit);
157: [atapiCnt free];
158: continue;
159: } else {
160: return YES;
161: }
162: }
163: }
164:
165: return NO;
166: }
167:
168: /*
169: * We override IOSCSIController to make ourself look like an indirect device
170: * in order to get connected to IdeController.
171: */
172: + (IODeviceStyle)deviceStyle
173: {
174: return IO_IndirectDevice;
175: }
176:
177: /*
178: * The protocol we need as an indirect device.
179: */
180: static Protocol *protocols[] = {
181: @protocol(AtapiControllerPublic),
182: nil
183: };
184:
185: + (Protocol **)requiredProtocols
186: {
187: return protocols;
188: }
189:
190: - (unsigned short)scsiCmdLen:(IOSCSIRequest *) scsiReq
191: {
192: unsigned char cmdlen;
193: union cdb *cdbp = &scsiReq->cdb;
194:
195: switch (SCSI_OPGROUP(cdbp->cdb_opcode)) {
196:
197: case OPGROUP_0:
198: cmdlen = sizeof(struct cdb_6);
199: break;
200:
201: case OPGROUP_1:
202: case OPGROUP_2:
203: cmdlen = sizeof(struct cdb_10);
204: break;
205:
206: case OPGROUP_5:
207: cmdlen = sizeof(struct cdb_12);
208: break;
209:
210: case OPGROUP_6:
211: if (scsiReq->cdbLength)
212: cmdlen = scsiReq->cdbLength;
213: else
214: cmdlen = sizeof(struct cdb_6);
215: break;
216:
217: case OPGROUP_7:
218: if (scsiReq->cdbLength)
219: cmdlen = scsiReq->cdbLength;
220: else
221: cmdlen = sizeof(struct cdb_10);
222: break;
223:
224: default:
225: scsiReq->driverStatus = SR_IOST_CMDREJ;
226: return 0;
227: }
228:
229: return cmdlen;
230: }
231:
232: #define C10OP_MODESELECT 0x55 /* OPT: set device parameters */
233: #define C10OP_MODESENSE 0x5a /* OPT: get device parameters */
234: #define C10OP_READCAPACITY 0x25 /* read capacity */
235:
236: /*
237: * This will enable us to print last 32 commands in case of an error. The
238: * command that caused the error is printed last.
239: */
240: #ifdef COMMAND_HISTORY
241: #define MAXCMDS 32
242: static atapiIoReq_t cmdBuf[MAXCMDS];
243: static unsigned int cmdPos = 0;
244: static unsigned int cmdsInBuf = 0;
245: #endif COMMAND_HISTORY
246:
247: /*
248: * Do a SCSI command, as specified by an IOSCSIRequest.
249: */
250: - (sc_status_t) executeRequest : (IOSCSIRequest *)scsiReq
251: buffer : (void *)buffer
252: client : (vm_task_t)client
253: {
254: int i;
255: atapiIoReq_t atapiIoReq;
256: atapiBuf_t *atapiBuf;
257: unsigned char *scsiCmd;
258: cdb_t my_cdb;
259: sc_status_t ret;
260: IOReturn driverStatus;
261: BOOL cmdMapped = NO;
262:
263: [_ataController atapiCntrlrLock];
264:
265: my_cdb = scsiReq->cdb;
266:
267: #ifdef DEBUG
268: if ((scsiReq->lun == 0) && (scsiReq->target < 2)) {
269: IOLog("%s: executeRequest %x target %x lun %x Read %d\n",
270: [self name], my_cdb.cdb_opcode, scsiReq->target, scsiReq->lun,
271: scsiReq->read);
272: }
273: #endif DEBUG
274:
275: bzero(&atapiIoReq, sizeof(atapiIoReq_t));
276:
277: atapiIoReq.cmdLen = [_ataController
278: atapiCommandPacketSize:scsiReq->target];
279:
280: atapiIoReq.read = scsiReq->read;
281: atapiIoReq.maxTransfer = scsiReq->maxTransfer;
282: atapiIoReq.drive = scsiReq->target;
283: atapiIoReq.lun = scsiReq->lun;
284: atapiIoReq.timeout = scsiReq->timeoutLength * 1000; // sec to ms
285:
286: // IOLog("max: %d\n", atapiIoReq.maxTransfer);
287:
288: scsiCmd = (unsigned char *) &(my_cdb.cdb_opcode);
289: atapiIoReq.scsiCmd = *scsiCmd;
290:
291: for (i = 0; i < [self scsiCmdLen:scsiReq]; i++) {
292: atapiIoReq.atapiCmd[i] = *scsiCmd;
293: scsiCmd++;
294: }
295:
296: /*
297: * Use this to print SCSI commands being sent to ATA object.
298: */
299:
300: #ifdef COMMAND_PRINT
301: if ((atapiIoReq.atapiCmd[0] == 0x28) && (atapiIoReq.lun == 0)) {
302: IOLog("%s: Command 0x28.\n", [self name]);
303: for (i = 0; i < [self scsiCmdLen:scsiReq]; i+=2) {
304: IOLog("%s: %02x %02x\n", [self name],
305: atapiIoReq.atapiCmd[i], atapiIoReq.atapiCmd[i+1]);
306: }
307:
308: }
309: if ((atapiIoReq.atapiCmd[0] == 0x15) && (atapiIoReq.lun == 0)) {
310: unsigned char *tmp = (unsigned char *)buffer;
311: IOLog("%s: Command 0x15 data.\n", [self name]);
312: for (i = 0; i < 0x1c; i+=2) {
313: IOLog("%s: %02x %02x\n", [self name],
314: tmp[i], tmp[i+1]);
315: }
316: }
317: #endif COMMAND_PRINT
318:
319: #ifdef COMMAND_HISTORY
320: /* Keep history */
321: cmdBuf[cmdPos++] = atapiIoReq;
322: if (cmdsInBuf < MAXCMDS)
323: cmdsInBuf += 1;
324: if (cmdPos == MAXCMDS)
325: cmdPos = 0;
326: #endif COMMAND_HISTORY
327:
328: /*
329: * Map to available ATAPI command if necessary.
330: */
331: for (i = 0; i < sizeof(mapToAtapi)/sizeof(mapToAtapi[0]); i++) {
332: if (atapiIoReq.atapiCmd[0] == mapToAtapi[i]) {
333: //IOLog("%s: Mapping to SCSI command\n", [self name]);
334: bzero((void *)&modeData, sizeof(modeData));
335: if ([self maptoAtapiCmd: &atapiIoReq buffer:buffer
336: newBuffer:&modeData] == NO) {
337: [_ataController atapiCntrlrUnLock];
338: return SR_IOST_CMDREJ;
339: }
340: cmdMapped = YES;
341: break;
342: }
343: }
344:
345: /*
346: * If emulation is successful then return quickly.
347: */
348: if ([self emulateSCSICmd: &atapiIoReq buffer:buffer] == YES) {
349: [_ataController atapiCntrlrUnLock];
350: return SR_IOST_GOOD;
351: }
352:
353: /*
354: * Send the command to the ioThread.
355: */
356: atapiBuf = [self allocAtapiBuf];
357: atapiBuf->atapiIoReq = &atapiIoReq;
358: if (cmdMapped) {
359: atapiBuf->buffer = (void *)&modeData;
360: atapiBuf->client = IOVmTaskSelf();
361: }
362: else {
363: atapiBuf->buffer = buffer;
364: atapiBuf->client = client;
365: }
366: atapiBuf->command = ATAPI_CNT_IOREQ;
367: driverStatus = [self enqueueAtapiBuf:atapiBuf];
368: ret = atapiBuf->status; // SCSI status
369:
370: /*
371: * Re-map to SCSI command if necessary.
372: */
373: if (driverStatus == SR_IOST_GOOD) {
374: for (i = 0; i < sizeof(mapToAtapi)/sizeof(mapToAtapi[0]); i++) {
375: if (atapiIoReq.scsiCmd == mapToAtapi[i]) {
376: if ([self maptoSCSICmd: &atapiIoReq buffer:buffer
377: newBuffer:&modeData] == NO) {
378: [_ataController atapiCntrlrUnLock];
379: return SR_IOST_CMDREJ;
380: }
381: break;
382: }
383: }
384: }
385:
386: [self freeAtapiBuf:atapiBuf];
387:
388: /*
389: * Use this to filter and print data returned from the device.
390: */
391: #ifdef DEBUG
392: {
393: unsigned char *buf = (unsigned char *)buffer;
394: if ((atapiIoReq.atapiCmd[0] == 0x25) && (atapiIoReq.lun == 0)) {
395: IOLog("%s: Returned data.\n", [self name]);
396: for (i = 0; i < atapiIoReq.bytesTransferred; i+=4) {
397: IOLog("%s: %02x %02x %02x %02x\n", [self name], buf[i],
398: buf[i+1], buf[i+2], buf[i+3]);
399: }
400: IOLog("%s: total bytes transferred = %d\n", [self name],
401: atapiIoReq.bytesTransferred);
402: IOLog("%s: scsi status: %x driver status: %x\n", [self name],
403: atapiIoReq.scsiStatus, ret);
404: }
405:
406: }
407: #endif DEBUG
408:
409: /*
410: * This is a workaround for the Mitsumi Read CD-ROM capacity bug. It
411: * reports the block size as 2352 bytes instead of 2048 bytes. It is
412: * including preamble and other info. I have seen this on MITSUMI CD-ROM
413: * !B B02. The workaround is truncate the returned value. Remove this
414: * when it is no longer needed.
415: */
416: {
417: unsigned int blockSize, value;
418: char *buf = (char *)buffer;
419: if ((atapiIoReq.atapiCmd[0] == C10OP_READCAPACITY) &&
420: (atapiIoReq.lun == 0)) {
421: blockSize = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) |
422: buf[7];
423: if (blockSize == 0) /* self defense */
424: blockSize = 2048;
425: for (value = 16; value < blockSize; value *= 2)
426: ;
427: if (value > blockSize) {
428: //IOLog("%s: block size set to %d from %d\n", [self name], value/2, blockSize);
429: blockSize = value / 2;
430: buf[4] = (blockSize >> 24) & 0xff;
431: buf[5] = (blockSize >> 16) & 0xff;
432: buf[6] = (blockSize >> 8) & 0xff;
433: buf[7] = blockSize & 0xff;
434: }
435: }
436: }
437:
438: #ifdef COMMAND_HISTORY
439: {
440: int j, k;
441:
442: /* Print history in case of error. */
443: if ((ret != SR_IOST_GOOD) && (atapiIoReq.atapiCmd[0] != 0x00)
444: && (atapiIoReq.atapiCmd[0] != 0x12)) {
445: IOLog("%s: Command %02x failed. Backtrace..\n", [self name],
446: atapiIoReq.atapiCmd[0]);
447: i = (cmdPos - cmdsInBuf) % MAXCMDS;
448: k = (int) cmdsInBuf;
449: while (--k >= 0) {
450: IOLog("%s: ", [self name]);
451: for (j = 0; j < 12; j++) {
452: IOLog("%02x ", cmdBuf[i].atapiCmd[j]);
453: }
454: IOLog("\n");
455: if (i == MAXCMDS)
456: i = 0;
457: else
458: i += 1;
459: }
460: cmdsInBuf = 0;
461: }
462: }
463: #endif COMMAND_HISTORY
464:
465: scsiReq->bytesTransferred = atapiIoReq.bytesTransferred;
466: scsiReq->scsiStatus = atapiIoReq.scsiStatus;
467: scsiReq->driverStatus = driverStatus;
468:
469: [_ataController atapiCntrlrUnLock];
470:
471: return ret;
472: }
473:
474: #define MPH_SCSI_6_SIZE sizeof(mode_sel_hdr_t)
475: #define MPH_SCSI_10_SIZE 8
476: #define MPH_ATAPI_SIZE sizeof(atapiMPH_t)
477: #define MPH_DELTA (MPH_ATAPI_SIZE - MPH_SCSI_6_SIZE)
478:
479: /*
480: * Map SCSI commands into ATAPI commands.
481: * We use this to modify the SCSI Mode Sense/Select commands to fit
482: * the ATAPI protocol.
483: *
484: * FIXME - We do not handle multiple mode pages. Only the first page is
485: * translated.
486: */
487: - (BOOL) maptoAtapiCmd:(atapiIoReq_t *)atapiIoReq
488: buffer:(void *)buffer
489: newBuffer:(atapiMPL_t *)mode
490: {
491: int i, pageLength, bd_len, page_start, hdr_size, maxTransfer;
492: unsigned char *data = (unsigned char *)buffer;
493:
494: /*
495: * Modify the SCSI mode sense (6) command.
496: *
497: * SCSI mode sense (10) should be fine for ATAPI since it matches
498: * the ATAPI spec very closely.
499: */
500: if (atapiIoReq->scsiCmd == C6OP_MODESENSE) {
501:
502: /*
503: * Our ATAPI buffer must be MPH_DELTA bytes larger than the size
504: * of the SCSI buffer passed in.
505: */
506: if ((atapiIoReq->atapiCmd[4] + MPH_DELTA) > sizeof(atapiMPL_t))
507: return NO;
508:
509: /*
510: * Transform the SCSI mode sense (6) command into a SCSI
511: * mode sense (10) command.
512: */
513: atapiIoReq->atapiCmd[0] = C10OP_MODESENSE;
514: atapiIoReq->atapiCmd[8] = atapiIoReq->atapiCmd[4] + MPH_DELTA;
515: atapiIoReq->atapiCmd[4] = 0;
516: atapiIoReq->atapiCmd[5] = 0;
517:
518: /* Increase the maxTransfer by 4 bytes, since in SCSI Mode
519: * Sense(6), the Mode Parameter Header is only 4 bytes long,
520: * while in ATAPI, it is always 8-bytes. Therefore, we may
521: * need to transfer 4 additional bytes over the set SCSI limit.
522: * We also know that we have enough storage since we did the
523: * check earlier.
524: */
525: atapiIoReq->maxTransfer += MPH_DELTA;
526:
527: return YES;
528: }
529:
530: /*
531: * Modify the SCSI mode select commands.
532: */
533: if ((atapiIoReq->scsiCmd == C6OP_MODESELECT) ||
534: (atapiIoReq->scsiCmd == C10OP_MODESELECT)) {
535:
536: if (atapiIoReq->scsiCmd == C6OP_MODESELECT) {
537: atapiIoReq->atapiCmd[0] = C10OP_MODESELECT;
538: atapiIoReq->atapiCmd[4] = 0;
539: atapiIoReq->atapiCmd[5] = 0; /* reset control field */
540:
541: bd_len = data[3]; /* block descriptor length */
542: hdr_size = MPH_SCSI_6_SIZE; /* mode parameter hdr size */
543: }
544: else { // C10OP_MODESELECT
545: atapiIoReq->atapiCmd[9] = 0; /* reset control field */
546: bd_len = (data[6] << 8) | data[7]; /* block descriptor length */
547: hdr_size = MPH_SCSI_10_SIZE; /* mode parameter hdr size */
548: }
549:
550: page_start = hdr_size + bd_len; /* start of mode page */
551: pageLength = data[page_start + 1] + 2; /* total size of mode page */
552: if (pageLength > MODSEL_DATA_LEN) /* page too large */
553: return NO;
554:
555: /* copy the mode page to our own buffer space */
556: for (i = 0; i < pageLength; i++) {
557: mode->pageData[i] = data[page_start + i];
558: }
559:
560: /* Update allocation length in the mode select command.
561: * length = page size + ATAPI header size
562: */
563: maxTransfer = pageLength + MPH_ATAPI_SIZE;
564: atapiIoReq->atapiCmd[8] = maxTransfer & 0xff; /* LSB */
565: atapiIoReq->atapiCmd[7] = (maxTransfer >> 8) & 0xff; /* MSB */
566:
567: /*
568: * Update the maxTransfer count.
569: */
570: atapiIoReq->maxTransfer = maxTransfer;
571: return YES;
572: }
573:
574: return YES;
575: }
576:
577: /*
578: * Map the result of ATAPI commands into their SCSI counterparts.
579: *
580: * FIXME - We do not handle multiple mode pages. Only the first page is
581: * translated.
582: */
583: - (BOOL) maptoSCSICmd:(atapiIoReq_t *)atapiIoReq
584: buffer:(void *)buffer
585: newBuffer:(atapiMPL_t *)mode
586: {
587: int i, pageLength;
588: unsigned char *data = (unsigned char *)buffer;
589:
590: /*
591: * If the executed command was originally a SCSI Mode Sense(6)
592: * command, we need to modify the result since the returned
593: * Page Parameter Header size is now 8-bytes instead of the
594: * expected 4-bytes.
595: */
596: if ((atapiIoReq->scsiCmd == C6OP_MODESENSE) &&
597: (atapiIoReq->bytesTransferred >= 10)) {
598:
599: // bytesTransferred must be greater than 10 or otherwise the
600: // PageLength field in the page (byte 1) would not be valid.
601:
602: pageLength = mode->pageData[1] + 2;
603:
604: /* Mode Page + Mode Header must fit in the SCSI buffer.
605: * Remember that the value in atapiCmd[8] was
606: * artificially increased by 4 bytes, so we need to
607: * take that into account.
608: */
609: if ((pageLength + MPH_SCSI_6_SIZE) >
610: (atapiIoReq->atapiCmd[8] - MPH_DELTA)) {
611: /* SCSI buffer is too small */
612: #ifdef DEBUG
613: IOLog("maptoSCSICmd: Mode Select buffer too small\n");
614: #endif DEBUG
615: return NO;
616: }
617:
618: data[0] = mode->mph.mdl0; // mode data length
619: data[1] = mode->mph.mt; // medium type
620: data[2] = 0; // device-specific parameter
621: data[3] = 0; // block descriptor length
622:
623: for (i = 0; i < pageLength; i++) {
624: data[4 + i] = mode->pageData[i];
625: }
626:
627: /*
628: * Modify bytesTransferred count to make it appear that
629: * we transferred 4 less bytes.
630: */
631: atapiIoReq->bytesTransferred -= MPH_DELTA;
632: return YES;
633: }
634:
635: return YES;
636: }
637:
638: /*
639: * If this SCSI command is not supported by ATAPI then try to fake its
640: * execution if possible.
641: */
642: - (BOOL) emulateSCSICmd:(atapiIoReq_t *)atapiIoReq buffer:(void *)buffer
643: {
644: unsigned char *data = (unsigned char *)buffer;
645:
646: /*
647: * We need to fake mode sense page 2. Workspace sends that and this page
648: * is reserved in ATAPI. In the SCSI world this page is for
649: * disconnect-reconnect and ATAPI doesn't support that now.
650: */
651: if (atapiIoReq->atapiCmd[0] == C10OP_MODESENSE) {
652: if ((atapiIoReq->atapiCmd[2] & 0x1f) == 0x02) {
653: bzero(data, atapiIoReq->atapiCmd[4]);
654: data[0] = 0x02;
655: data[1] = atapiIoReq->atapiCmd[4];
656: data[2] = 1; /* our preferred size: 2048 bytes */
657: atapiIoReq->bytesTransferred = atapiIoReq->atapiCmd[4];
658: atapiIoReq->scsiStatus = STAT_GOOD;
659:
660: return YES;
661: }
662: }
663:
664: return NO; /* default */
665: }
666:
667:
668: /*
669: * Reset all ATAPI devices connected to this controller. Note that we have
670: * obtain a lock before resetting the controller.
671: */
672: - (sc_status_t)resetSCSIBus
673: {
674: int unit;
675: atapi_return_t ret;
676: sc_status_t status = SR_IOST_GOOD;
677:
678: for (unit = 0; unit < [_ataController numDevices]; unit++) {
679:
680: if ([_ataController isAtapiDevice:unit]) {
681:
682: [_ataController atapiCntrlrLock];
683: ret = [_ataController atapiSoftReset:unit];
684: [_ataController atapiCntrlrUnLock];
685:
686: if (ret != IDER_SUCCESS) {
687: IOLog("%s: ATAPI reset failed.\n", [self name]);
688: status = SR_IOST_HW;
689: }
690: }
691: }
692:
693: return status;
694: }
695:
696: #ifdef undef
697: /* For testing individual commands. */
698: static void testDebug(id driver)
699: {
700: void *buffer;
701: atapiIoReq_t atapiIoReq;
702:
703: buffer = IOMalloc(2048);
704: bzero(&atapiIoReq, sizeof(atapiIoReq_t));
705:
706: atapiIoReq.cmdLen = 12;
707: atapiIoReq.read = 1;
708: atapiIoReq.drive = 0;
709: atapiIoReq.lun = 0;
710:
711: atapiIoReq.atapiCmd[0] = 0x28;
712: atapiIoReq.atapiCmd[2] = 0;
713: atapiIoReq.atapiCmd[3] = 0;
714: atapiIoReq.atapiCmd[4] = 0;
715: atapiIoReq.atapiCmd[5] = 5;
716: atapiIoReq.atapiCmd[7] = 0;
717: atapiIoReq.atapiCmd[8] = 1;
718:
719: [driver atapiExecuteCmd:&atapiIoReq
720: buffer:buffer client:IOVmTaskSelf()];
721:
722: }
723: #endif undef
724:
725: - property_IODeviceClass:(char *)classes length:(unsigned int *)maxLen
726: {
727: strcpy( classes, IOClassATAPIController);
728: return( self);
729: }
730:
731: - property_IODeviceType:(char *)types length:(unsigned int *)maxLen
732: {
733: strcat( types, " "IOTypeATAPI);
734: return( self);
735: }
736:
737: @end
738:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.