Annotation of drvEIDE/EIDE.drvproj/EIDE.lksproj/AtapiCnt.m, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.