Annotation of kernel/bsd/dev/ppc/drvPPCATA/AtapiCntCmds.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.1 (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 by Apple Computer, Inc., all rights reserved.
                     26: /*
                     27:  * Copyright (c) 1994-1997 NeXT Software, Inc.  All rights reserved. 
                     28:  *
                     29:  * AtapiCntCmds.m - ATAPI command implementation for ATA interface. 
                     30:  *
                     31:  * HISTORY 
                     32:  *
                     33:  */
                     34: 
                     35: #import "AtapiCntCmds.h"
                     36: #import "IdeCntInit.h"
                     37: #import "IdeCntCmds.h"
                     38: #import "IdeCntDma.h"
                     39: 
                     40: @implementation IdeController(ATAPI)
                     41: 
                     42: #define ATAPI_MAX_WAIT_FOR_NOTBUSY             (5 * 1000)
                     43: 
                     44: /*
                     45:  * We could use the ATA version instead of rolling our own here. 
                     46:  */
                     47: - (atapi_return_t)atapiWaitForNotBusy
                     48: {
                     49:     int i;
                     50:     unsigned char status;
                     51: 
                     52:     for (i = 0; i < ATAPI_MAX_WAIT_FOR_NOTBUSY; i++)  
                     53:     {
                     54:        status = inb(_ideRegsAddrs.status);
                     55:        
                     56:        if (!(status & BUSY)) 
                     57:         {
                     58:            return IDER_SUCCESS;
                     59:        }
                     60:        IOSleep(1);
                     61:     }
                     62:     return IDER_TIMEOUT;
                     63: }
                     64: 
                     65: /*
                     66:  * Before sending a packet to ATAPI device, we test if BSY == 0 and DRQ == 0. 
                     67:  */
                     68: #define ATAPI_MAX_WAIT_READY_FOR_PACKET                (5 * 1000)
                     69: 
                     70: - (atapi_return_t)atapiWaitReadyForPacket
                     71: {
                     72:     int i;
                     73:     unsigned char status;
                     74: 
                     75:     for (i = 0; i < ATAPI_MAX_WAIT_READY_FOR_PACKET; i++)  
                     76:     {
                     77:        status = inb(_ideRegsAddrs.status);
                     78:        
                     79:        if (!(status & BUSY) && !(status & DREQUEST)) 
                     80:         {
                     81:            return IDER_SUCCESS;
                     82:        }
                     83:        IOSleep(1);     
                     84:     }
                     85:     
                     86:     return IDER_DEV_NOT_READY;
                     87: }
                     88: 
                     89: -(void)printAtapiInfo:(ideIdentifyInfo_t *)ideIdentifyInfo 
                     90:                        Device:(unsigned char)unit
                     91: {
                     92:     int                i;
                     93:     char               name[50];
                     94:     char               firmware[9];
                     95:     atapiGenConfig_t   *atapiGenConfig;
                     96:     char               *protocolTypeStr, *deviceTypeStr, *cmdDrqTypeStr;
                     97:     char               *removableStr, *cmdPacketSizeStr;
                     98: 
                     99:     /*
                    100:      * Print drive name with firmware revision number after doing byte swaps. 
                    101:      */
                    102:     for (i = 0; i < 20; i++)   
                    103:     {
                    104:        name[2*i] = ideIdentifyInfo->modelNumber[2*i+1];
                    105:        name[2*i+1] = ideIdentifyInfo->modelNumber[2*i];
                    106:     }
                    107:     name[40] = '\0';
                    108:     
                    109:     for (i = 0; i < 4; i++)    
                    110:     {
                    111:        firmware[2*i] = ideIdentifyInfo->firmwareRevision[2*i+1];
                    112:        firmware[2*i+1] = ideIdentifyInfo->firmwareRevision[2*i];
                    113:     }
                    114:     firmware[8] = '\0';
                    115:     
                    116:     for (i = 38; i >= 0; i--)  {
                    117:        if (name[i] != ' ')
                    118:            break;
                    119:     }
                    120:     strcpy(name+i+2, firmware);
                    121:     
                    122:     /*
                    123:      * This information should be printed since it is not duplicated
                    124:      * elsewhere. 
                    125:      */
                    126:     atapiGenConfig = (atapiGenConfig_t *) &ideIdentifyInfo->genConfig;
                    127:     
                    128:     if (atapiGenConfig->protocolType == 0 || atapiGenConfig->protocolType == 1)
                    129:        protocolTypeStr = "ATA";
                    130:     else if (atapiGenConfig->protocolType == 2)
                    131:        protocolTypeStr = "ATAPI";
                    132:     else 
                    133:        protocolTypeStr = "UNKNOWN PROTOCOL";
                    134:        
                    135:     if (atapiGenConfig->deviceType == 0)
                    136:        deviceTypeStr = "DIRECT ACCESS";
                    137:     else if (atapiGenConfig->deviceType == 5)
                    138:        deviceTypeStr = "CD-ROM";
                    139:     else if (atapiGenConfig->deviceType == 7)
                    140:        deviceTypeStr = "OPTICAL";
                    141:     else if (atapiGenConfig->deviceType == 1)
                    142:        deviceTypeStr = "TAPE";
                    143:     else
                    144:        deviceTypeStr = "UNKNOWN DEVICE TYPE";
                    145:        
                    146:     if (atapiGenConfig->cmdDrqType == 0)
                    147:        cmdDrqTypeStr = "SLOW DRQ";
                    148:     else if (atapiGenConfig->cmdDrqType == 1)
                    149:        cmdDrqTypeStr = "INTR DRQ";
                    150:     else if (atapiGenConfig->cmdDrqType == 2)
                    151:        cmdDrqTypeStr = "FAST DRQ";
                    152:     else 
                    153:        cmdDrqTypeStr = "UNKNOWN DRQ TYPE";
                    154:        
                    155:     if (atapiGenConfig->removable == 0)
                    156:        removableStr = "NOT REMOVABLE";
                    157:     else if (atapiGenConfig->removable == 1)
                    158:        removableStr = "REMOVABLE";
                    159:     
                    160:     if (atapiGenConfig->cmdPacketSize == 0)
                    161:        cmdPacketSizeStr = "CMD PKT LEN=12";
                    162:     else if (atapiGenConfig->cmdPacketSize == 1)
                    163:        cmdPacketSizeStr = "CMD PKT LEN=16";
                    164:     else 
                    165:        cmdPacketSizeStr = "CMD PKT LEN=UNKNOWN";       
                    166: }
                    167: 
                    168: /*
                    169:  * This is a private version for ATAPI Identify command below. It has a short
                    170:  * delay time. 
                    171:  */
                    172: - (ide_return_t)atapiIdentifyDeviceWaitForDataReady
                    173: {
                    174:     int     delay = (100 * 1000);
                    175:     unsigned char status;
                    176: 
                    177:     delay -= 2;
                    178:     while (delay > 0) 
                    179:     {
                    180:        status = inb(_ideRegsAddrs.altStatus);
                    181:        if ((!(status & BUSY)) && (status & DREQUEST))
                    182:            return (IDER_SUCCESS);
                    183:        if (delay % 1000)       
                    184:         {
                    185:            IODelay(2);
                    186:             delay -= 2;
                    187:        } 
                    188:         else 
                    189:         {
                    190:            IOSleep(1);
                    191:            delay -= 1000;
                    192:        }
                    193:     }
                    194:     
                    195:     return IDER_DEV_NOT_READY;
                    196: }
                    197: 
                    198: /*
                    199:  * There are lots of ATAPI CD-ROMs that shadow the task file register and
                    200:  * hence show up as two devices. They also might issue a valid interrupt when
                    201:  * ATAPI Identify Device command is sent so we need to really make sure
                    202:  * whether the device has data for us. 
                    203:  */
                    204: -(atapi_return_t)_atapiIdentifyDevice:(struct vm_map *)client
                    205:                                addr:(caddr_t)xferAddr
                    206: {
                    207:     unsigned int cmd = ATAPI_IDENTIFY_DRIVE;
                    208:     unsigned char dh = ADDRESS_MODE_LBA;       /* ALWAYS */
                    209:     unsigned char status;
                    210:     atapi_return_t rtn;
                    211:     
                    212:     unsigned int oldTimeout;
                    213: 
                    214:     rtn = [self atapiWaitForNotBusy];
                    215:     if (rtn != IDER_SUCCESS) 
                    216:     {
                    217:        return (rtn);
                    218:     }
                    219:     
                    220:     [self setTransferRate: _driveNum UseDMA:NO];
                    221: 
                    222:     dh |= _driveNum ? SEL_DRIVE1 : SEL_DRIVE0;
                    223:     outb(_ideRegsAddrs.driveSelect, dh);
                    224:     
                    225:     bzero(xferAddr, IDE_SECTOR_SIZE);
                    226:     
                    227:     [self enableInterrupts];
                    228:     
                    229:     outb(_ideRegsAddrs.command, ATAPI_IDENTIFY_DRIVE);
                    230: 
                    231:     oldTimeout = [self interruptTimeOut];
                    232:     [self setInterruptTimeOut:4000];           // four seconds
                    233:     
                    234:     rtn = [self ideWaitForInterrupt:cmd ideStatus:&status];
                    235:         
                    236:     if (rtn != IDER_SUCCESS) {
                    237:        [self getIdeRegisters:NULL Print:"Atapi Identify"];
                    238:        [self setInterruptTimeOut:oldTimeout];
                    239:        return rtn;
                    240:     }
                    241: 
                    242:     /*
                    243:      * Let's see if it really has data for us. 
                    244:      */
                    245:     rtn = [self atapiIdentifyDeviceWaitForDataReady];
                    246:     if (rtn != IDER_SUCCESS) 
                    247:     {
                    248:        [self setInterruptTimeOut:oldTimeout];
                    249:        return (rtn);
                    250:     }
                    251: 
                    252:     /*
                    253:      * FIXME: We need to do some sanity check on this data to be really sure
                    254:      * that there is an ATAPI device out here. 
                    255:      */
                    256:     [self xferData:xferAddr read:YES client:client length:IDE_SECTOR_SIZE];
                    257:     
                    258:     [self setInterruptTimeOut:oldTimeout];
                    259:     
                    260:     return IDER_SUCCESS;
                    261: }
                    262: 
                    263: /*
                    264:  * Some CD-ROMS (like SONY CDU-55D) fail the first request so we reset the
                    265:  * device and retry. 
                    266:  */
                    267: #define ATAPI_IDENTIFY_DEVICE_RETRIES          5
                    268: 
                    269: -(atapi_return_t)atapiIdentifyDevice:(struct vm_map *)client
                    270:                                addr:(caddr_t)xferAddr
                    271:                                unit:(unsigned char)unit
                    272: {
                    273:     int i;
                    274:     atapi_return_t ret;
                    275:     
                    276:     for (i = 0; i < ATAPI_IDENTIFY_DEVICE_RETRIES; i++)        
                    277:     {
                    278:        ret = [self _atapiIdentifyDevice:client addr:xferAddr];
                    279:        if (ret == IDER_SUCCESS)
                    280:            break;
                    281:            
                    282:        /* Reset hardware and try again */
                    283:        [self atapiSoftReset:unit];
                    284:        IOSleep(500);
                    285:     }
                    286:     
                    287:     if (i == ATAPI_IDENTIFY_DEVICE_RETRIES)    {
                    288:        IOLog("%s: FATAL: Device %d: ATAPI Identify Device.\n", 
                    289:                [self name], unit);
                    290:     }
                    291: 
                    292:     return ret;
                    293: }
                    294: 
                    295: -(void)atapiInitParameters:(ideIdentifyInfo_t *)infoPtr 
                    296:                Device:(unsigned char)unit
                    297: {
                    298:     atapiGenConfig_t *atapiGenConfig = 
                    299:        (atapiGenConfig_t *) &infoPtr->genConfig;
                    300:     
                    301:     if (atapiGenConfig->cmdPacketSize == 0x01)
                    302:        _atapiCmdLen[unit] = 16;
                    303:     else
                    304:        _atapiCmdLen[unit] = 12;
                    305: 
                    306:     /*
                    307:      * The command len is 12. However some devices think it is 16 which is
                    308:      * actually reserved for SAM compatibility. See page 58, SFF 8020, rev
                    309:      * 1.2. This is a workaround.
                    310:      */
                    311:     if (_atapiCmdLen[unit] != 12)      
                    312:     {
                    313:        IOLog("%s: ATAPI: command len changed to 12 from %d.\n", 
                    314:                [self name], _atapiCmdLen[unit]);
                    315:        _atapiCmdLen[unit] = 12;
                    316:     }
                    317: 
                    318:     _atapiCmdDrqType[unit] = atapiGenConfig->cmdDrqType;
                    319: 
                    320:     if (infoPtr->capabilities & IDE_CAP_DMA_SUPPORTED) 
                    321:     {
                    322:         if ( [self allocDmaMemory] == IDER_SUCCESS )
                    323:         {
                    324:             _dmaSupported[unit] = YES;
                    325:         }
                    326:     }
                    327: 
                    328:     [self getTransferModes:infoPtr Unit:unit];
                    329: 
                    330:     /*
                    331:      * Set the Disk/CDROM transfer mode (Set Features SC=3) 
                    332:      */
                    333:     [self setTransferMode: unit]; 
                    334: }
                    335: 
                    336: /*
                    337:  * Identify ATAPI device must have been executed first before callling this
                    338:  * method. 
                    339:  */
                    340: -(unsigned char)atapiCommandPacketSize:(unsigned char)unit
                    341: {
                    342:     if (unit < MAX_IDE_DRIVES)
                    343:        return _atapiCmdLen[unit];
                    344:     else
                    345:        return 0;
                    346: }
                    347: 
                    348: 
                    349: /*
                    350:  * The amount of time in milliseconds it takes for an ATAPI device to post
                    351:  * its signature after a reset. Some CD-ROMs take a long time to respond. Do
                    352:  * not decrease it without testing with various makes of ATAPI devices. 
                    353:  */
                    354: #define ATAPI_RESET_DELAY              2500
                    355: 
                    356: -(atapi_return_t)atapiSoftReset:(unsigned char)unit
                    357: {
                    358:     int  delay;
                    359:     unsigned char status;
                    360:     atapi_return_t rtn;
                    361:     unsigned char dh = ADDRESS_MODE_LBA;       /* ALWAYS */
                    362: 
                    363:     _driveReset[unit] = YES;
                    364: 
                    365:     dh |= unit ? SEL_DRIVE1 : SEL_DRIVE0;
                    366: 
                    367:     outb(_ideRegsAddrs.driveSelect, dh);
                    368:     outb(_ideRegsAddrs.command, ATAPI_SOFT_RESET);
                    369: 
                    370:     delay = ATAPI_RESET_DELAY;
                    371:     
                    372:     IOSleep(50);                       /* Enough time to assert busy */
                    373:     
                    374:     rtn = IDER_ERROR;
                    375:     
                    376:     while (delay > 0) 
                    377:     {
                    378:        status = inb(_ideRegsAddrs.status);
                    379:        if (!(status & BUSY)) 
                    380:         {
                    381:            rtn = IDER_SUCCESS;
                    382:             break;
                    383:        }
                    384:        
                    385:        IOSleep(10);
                    386:        delay -= 10;
                    387:     }
                    388: 
                    389:     return rtn;
                    390: }
                    391: 
                    392: 
                    393: #define MAX_DRQ_WAIT           (1000 * 2)              // milliseconds
                    394: 
                    395: -(atapi_return_t)atapiPacketCommand
                    396: {
                    397:     int i;
                    398:     atapi_return_t rtn;
                    399:     unsigned char interruptReason;
                    400:     unsigned char status;
                    401:        
                    402:     outb(_ideRegsAddrs.command, ATAPI_PACKET);
                    403: 
                    404:     /*
                    405:      * Some devices might have interrupted so we should take care of that
                    406:      * first.
                    407:      */
                    408:     if (_atapiCmdDrqType[_driveNum] == ATAPI_CMD_DRQ_INT) 
                    409:     {
                    410:        rtn = [self ideWaitForInterrupt:ATAPI_PACKET ideStatus:&status];
                    411:     }
                    412:     
                    413:     /*
                    414:      * Wait till we get okay from the device. 
                    415:      */
                    416:     for (i = 0; i < MAX_DRQ_WAIT; i++) 
                    417:     {
                    418:        interruptReason = inb(_ideRegsAddrs.interruptReason);
                    419:        if ((interruptReason & CMD_OR_DATA) && !(interruptReason & IO_DIRECTION))
                    420:            break;
                    421:        IOSleep(1);
                    422:     }
                    423: 
                    424:     if (i == MAX_DRQ_WAIT)     
                    425:     {
                    426:        IOLog("%s: ATAPI Device %d:  Invalid Interrupt Reason: %x.\n", 
                    427:                [self name], _driveNum, interruptReason);
                    428:        return IDER_ERROR;
                    429:     }
                    430: 
                    431:     /*
                    432:      * Now DRQ should be set. 
                    433:      */
                    434:     status = inb(_ideRegsAddrs.status);
                    435:     if (status & DREQUEST)     
                    436:     {
                    437:        return IDER_SUCCESS;
                    438:     }
                    439:     
                    440:     IOLog("%s: ATAPI Device %d: No Data Request: %x.\n", 
                    441:                [self name], _driveNum, status);
                    442:        
                    443:     return IDER_ERROR;
                    444: }
                    445: 
                    446: /*
                    447:  * Note that the command is sent out as words in little endian format. 
                    448:  */
                    449: - (void) sendAtapiCommand:(unsigned char *)atapiCmd
                    450:        cmdLen:(unsigned char)len
                    451: {
                    452:     int i;
                    453:     
                    454:     for (i = 0; i < len/2; i++)        
                    455:     {
                    456:        outw(_ideRegsAddrs.data, (atapiCmd[2*i] << 8) | atapiCmd[2*i+1]);
                    457:     }
                    458: }
                    459: 
                    460: /*
                    461:  * Prints command and result in case of error. 
                    462:  */
                    463: - (void)dumpStatus:(atapiIoReq_t *)atapiIoReq
                    464: {
                    465:     int i;
                    466:     
                    467:     IOLog("%s: Failed command: drive: %d lun: %d len: %d read: %d\n", 
                    468:        [self name], 
                    469:        atapiIoReq->drive, atapiIoReq->lun, atapiIoReq->cmdLen, 
                    470:        atapiIoReq->read);
                    471:     IOLog("%s: Failed command: ", [self name]); 
                    472:     for (i = 0; i < atapiIoReq->cmdLen; i++)
                    473:        IOLog("%x ", atapiIoReq->atapiCmd[i]);
                    474:     IOLog("\n");
                    475:     
                    476:     [self getIdeRegisters:NULL Print:"dumpStatus"];
                    477: }
                    478: 
                    479: 
                    480: #define        C10OP_MODESELECT        0x55    /* OPT: set device parameters */
                    481: #define        C10OP_MODESENSE         0x5a    /* OPT: get device parameters */
                    482: 
                    483: #define MAX_SENDPACKET_RETRIES         3
                    484: 
                    485: #define MAX_BUSY_WAIT                  (1000*100)
                    486: 
                    487: - (sc_status_t) atapiExecuteCmd:(atapiIoReq_t *)atapiIoReq 
                    488:                    buffer : (void *)buffer 
                    489:                    client : (struct vm_map *)client
                    490: {
                    491:     int                i;
                    492:     atapi_return_t     rtn;
                    493:     unsigned int       offset;
                    494:     unsigned char      dh = ADDRESS_MODE_LBA;  /* ALWAYS */
                    495:     unsigned char       xferType;
                    496:     BOOL               dmaAllowed;
                    497:     
                    498:     /*
                    499:      * Reject command if there are no ATAPI devices detected. 
                    500:      */
                    501:      if ((atapiIoReq->drive >= MAX_IDE_DRIVES) || (atapiIoReq->lun != 0))  
                    502:      {
                    503:        return SR_IOST_SELTO;
                    504:      }
                    505:      
                    506:      if ([self isAtapiDevice:atapiIoReq->drive] == NO) 
                    507:      {
                    508:        return SR_IOST_SELTO;
                    509:      }
                    510:          
                    511:     [self clearInterrupts];
                    512:     
                    513:     _driveNum = atapiIoReq->drive;
                    514: 
                    515:     dmaAllowed = [self atapiDmaAllowed: buffer];
                    516: 
                    517:     if ( atapiIoReq->maxTransfer != 0 )
                    518:     {
                    519:         [self setTransferRate: _driveNum UseDMA:dmaAllowed];
                    520:     }
                    521: 
                    522:     if ( _driveReset[_driveNum] == YES )
                    523:     {
                    524:         [self setTransferMode: _driveNum];
                    525:         _driveReset[_driveNum] = NO;
                    526:     }
                    527: 
                    528:     /* Now execute the SCSI command. */
                    529: 
                    530:     for (i = 0; i < MAX_SENDPACKET_RETRIES; i++)       
                    531:     {
                    532:        rtn = [self atapiWaitReadyForPacket];
                    533:        if (rtn != IDER_SUCCESS) 
                    534:         {
                    535:            IOLog("%s: ATAPI Device %d: Not Ready For Packet command.\n", 
                    536:                [self name], _driveNum);
                    537:            [self atapiSoftReset:_driveNum];
                    538:            continue;
                    539:        }
                    540:        
                    541:        /*
                    542:         * Select the drive first. 
                    543:         */
                    544:        dh |= _driveNum ? SEL_DRIVE1 : SEL_DRIVE0;
                    545:        outb(_ideRegsAddrs.driveSelect, dh);
                    546: 
                    547:        /*
                    548:         * Send our preferred data transfer size (2048 bytes). 
                    549:         */
                    550:        outb(_ideRegsAddrs.byteCountLow, 0x00);
                    551:        outb(_ideRegsAddrs.byteCountHigh, 0x08);
                    552: 
                    553:        /*
                    554:         * Set data transfer mode PIO = 0x00 / DMA = 0x01 
                    555:         */
                    556:         xferType = (dmaAllowed == YES) ? 0x01 : 0x00;
                    557:        outb(_ideRegsAddrs.features, xferType);
                    558:        
                    559:        /*
                    560:         * First tell the ATAPI device that we are going to send it a packet
                    561:         * command. If this command fails the ATAPI device needs to be reset. 
                    562:         */
                    563:        if ([self atapiPacketCommand] == IDER_SUCCESS)  
                    564:         {
                    565:            break;
                    566:        }
                    567:        
                    568:        IOLog("%s: ATAPI Device %d: Packet command failed. Retrying...\n",
                    569:                 [self name], _driveNum);
                    570:        [self atapiSoftReset:_driveNum];
                    571:     }
                    572: 
                    573:     /*
                    574:      * Are we hosed? 
                    575:      */
                    576:     if (i == MAX_SENDPACKET_RETRIES)   
                    577:     {
                    578:        atapiIoReq->scsiStatus = STAT_CHECK;
                    579:        IOLog("%s: ATAPI Device %d: FATAL: Packet command.\n", 
                    580:                [self name], _driveNum);
                    581:        return SR_IOST_CMDREJ;    
                    582:     }
                    583:     
                    584:     /*
                    585:      * Send the actual command to the device. 
                    586:      */
                    587:     [self sendAtapiCommand:atapiIoReq->atapiCmd cmdLen:atapiIoReq->cmdLen];
                    588: 
                    589:     atapiIoReq->bytesTransferred = 0;
                    590:     offset = 0;
                    591:     
                    592:     [self enableInterrupts];
                    593: 
                    594:     if ( dmaAllowed == YES )
                    595:     {
                    596:         rtn = [self atapiXferDMA:(atapiIoReq_t *)atapiIoReq  buffer: (void *)buffer client: (struct vm_map *)client];
                    597:     }
                    598:     else
                    599:     {
                    600:         rtn =[self atapiXferPIO:(atapiIoReq_t *)atapiIoReq  buffer: (void *)buffer client: (struct vm_map *)client];
                    601:     }
                    602: 
                    603: #if 0
                    604:         kprintf("Disk(ATAPI): Cmd = %02x Length = %08x Addr=%08x:%08x Status = %d\n\r", 
                    605:                atapiIoReq->atapiCmd[0], (int)atapiIoReq->maxTransfer, (int)buffer, (int)client, 
                    606:                rtn);
                    607: #endif   
                    608: 
                    609:     return rtn;
                    610: }
                    611: 
                    612: - (sc_status_t) atapiXferPIO:(atapiIoReq_t *)atapiIoReq 
                    613:                    buffer : (void *)buffer 
                    614:                    client : (struct vm_map *)client
                    615: {
                    616:     int                i;
                    617:     atapi_return_t     rtn;
                    618:     unsigned char      status;
                    619:     unsigned int       bytes;
                    620:     unsigned int       offset = 0;
                    621:     unsigned char      cmd = atapiIoReq->atapiCmd[0];
                    622: 
                    623:     for (;;)   
                    624:     {
                    625:        rtn = [self ideWaitForInterrupt:cmd ideStatus:&status];
                    626: 
                    627:        if (rtn != IDER_SUCCESS) 
                    628:         {
                    629:            IOLog("%s: FATAL: ATAPI Device: %d Command %x failed.\n", 
                    630:                [self name], _driveNum, atapiIoReq->atapiCmd[0]);
                    631:            [self getIdeRegisters:NULL Print:"ATAPI Command"];
                    632:            [self atapiSoftReset:_driveNum];
                    633:            atapiIoReq->scsiStatus = STAT_CHECK;
                    634:            return SR_IOST_CHKSNV;
                    635:        }
                    636: 
                    637:        for (i = 0; i < MAX_BUSY_WAIT; i++)     
                    638:         {
                    639:            if (status & BUSY)  
                    640:             {
                    641:                IODelay(10);
                    642:            } 
                    643:             else 
                    644:             {
                    645:                break;
                    646:            }
                    647:            status = inb(_ideRegsAddrs.status); 
                    648:        }
                    649:        
                    650:        /*
                    651:         * If DRQ == 0 then host has terminated the command. 
                    652:         */
                    653:        if (!(status & DREQUEST))       
                    654:         {
                    655:            /*
                    656:             * Check for command completion status. 
                    657:             */
                    658:            if (status & ERROR) 
                    659:             {              
                    660:                atapiIoReq->scsiStatus = STAT_CHECK;
                    661:                return SR_IOST_CHKSNV;
                    662:            } 
                    663:             else 
                    664:             {
                    665:                atapiIoReq->scsiStatus = STAT_GOOD;
                    666:                return SR_IOST_GOOD;
                    667:            }
                    668:        }
                    669: 
                    670:        /*
                    671:         * Command is not completed. We need to transfer data as requested by
                    672:         * the device. 
                    673:         */
                    674:        bytes =  inb(_ideRegsAddrs.byteCountHigh) << 8 | 
                    675:            inb(_ideRegsAddrs.byteCountLow);
                    676: 
                    677:        /*
                    678:         * If the device requests more data to be transferred than required
                    679:         * by the command protocol, then we should transfer null data. 
                    680:         */
                    681: 
                    682:        
                    683:        if (atapiIoReq->bytesTransferred + bytes > atapiIoReq->maxTransfer)
                    684:         {
                    685:            IOLog("%s: ATAPI Device %d: "
                    686:                "ERROR: Transfer limit (%x bytes) exceeded\n", 
                    687:                [self name], _driveNum, atapiIoReq->maxTransfer);
                    688:                
                    689:            IOLog("%s: Bytes already transfered: %x, next request: %x\n", 
                    690:                [self name], atapiIoReq->bytesTransferred, bytes);
                    691:            
                    692:            [self dumpStatus: atapiIoReq];
                    693: 
                    694:            /*
                    695:             * This thing is probably hosed but let's do the best we can. 
                    696:             */
                    697:            {
                    698:            int diff = atapiIoReq->maxTransfer-atapiIoReq->bytesTransferred;
                    699:            IOLog("%s: Transferring %x bytes instead of %x\n", 
                    700:                [self name], diff, bytes);
                    701:            [self xferData:buffer+offset read:atapiIoReq->read 
                    702:                    client:client length:diff];
                    703:            atapiIoReq->bytesTransferred += diff;
                    704:            offset += diff;
                    705:            [self atapiSoftReset:_driveNum];    // reset hardware as well
                    706:            }
                    707:            
                    708:            atapiIoReq->scsiStatus = STAT_GOOD;
                    709:            return SR_IOST_GOOD;            
                    710:        }
                    711:        
                    712:        /*
                    713:         * Now transfer data from device to memory. 
                    714:         */
                    715:        [self xferData:buffer+offset read:atapiIoReq->read client:client 
                    716:                length:bytes];
                    717:        
                    718:        atapiIoReq->bytesTransferred += bytes;
                    719:        offset += bytes;
                    720:     }
                    721: 
                    722:     /*
                    723:      * Will never get here. 
                    724:      */
                    725:     atapiIoReq->scsiStatus = STAT_GOOD;
                    726:     return SR_IOST_GOOD;
                    727: }
                    728: 
                    729: 
                    730: - (sc_status_t) atapiXferDMA:(atapiIoReq_t *)atapiIoReq 
                    731:                    buffer : (void *)buffer 
                    732:                    client : (struct vm_map *)client
                    733: {
                    734:     int                i;
                    735:     atapi_return_t     rtn;
                    736:     unsigned char      status;
                    737:     unsigned char      cmd = atapiIoReq->atapiCmd[0];
                    738:     unsigned long      cfgReg;
                    739: 
                    740:     [self setupDMA:(vm_offset_t) buffer client:(vm_task_t) client length:(int)atapiIoReq->maxTransfer fRead:(BOOL)atapiIoReq->read]; 
                    741:     if ( _controllerType != kControllerTypeCmd646X )
                    742:     {
                    743:         IODBDMAContinue( _ideDMARegs );        
                    744:     }
                    745:     else
                    746:     {
                    747:         [[self deviceDescription] configReadLong:0x70 value: &cfgReg];
                    748:         cfgReg &= ~0x08;
                    749:         cfgReg |= 0x01 | ((atapiIoReq->read) ? 0x08 : 0x00);
                    750:         [[self deviceDescription] configWriteLong:0x70 value: cfgReg];
                    751:     }
                    752: 
                    753:     rtn = [self ideWaitForInterrupt:cmd ideStatus:&status];
                    754: 
                    755:     if (rtn != IDER_SUCCESS) 
                    756:     {
                    757:        IOLog("%s: FATAL: ATAPI Device: %d Command %x failed.\n", [self name], _driveNum, atapiIoReq->atapiCmd[0]);
                    758:        [self getIdeRegisters:NULL Print:"ATAPI Command"];
                    759:        [self atapiSoftReset:_driveNum];
                    760:        atapiIoReq->scsiStatus = STAT_CHECK;
                    761:        return SR_IOST_CHKSNV;
                    762:     }
                    763: 
                    764:     for (i = 0; i < MAX_BUSY_WAIT; i++)        
                    765:     {
                    766:        if (status & BUSY)      
                    767:         {
                    768:             IODelay(10);
                    769:        } 
                    770:         else 
                    771:         {
                    772:            break;
                    773:        }
                    774:         status    = inb(_ideRegsAddrs.status);
                    775:     }
                    776: 
                    777:     if ( _controllerType != kControllerTypeCmd646X )
                    778:     {
                    779:         atapiIoReq->bytesTransferred = [self stopDBDMA];
                    780:     }
                    781:     else
                    782:     {
                    783:         [[self deviceDescription] configReadLong: 0x70 value: &cfgReg];
                    784:         cfgReg &= ~0x01;
                    785:         [[self deviceDescription] configWriteLong:0x70 value: cfgReg];
                    786: 
                    787:         atapiIoReq->bytesTransferred = atapiIoReq->maxTransfer;
                    788:     }
                    789: 
                    790:     /*
                    791:      * The DMA has handled all the data movement. 
                    792:      * Must have final command status at this point. 
                    793:      */
                    794:      if ( status & (ERROR) )   
                    795:      {             
                    796:          atapiIoReq->scsiStatus = STAT_CHECK;
                    797:          return SR_IOST_CHKSNV;
                    798:      } 
                    799:      else 
                    800:      {
                    801:          atapiIoReq->scsiStatus = STAT_GOOD;
                    802:          return SR_IOST_GOOD;
                    803:      }
                    804: }     
                    805:   
                    806: - (BOOL) atapiDmaAllowed: (void *)buffer
                    807: {
                    808:     if ( _dmaSupported[_driveNum] == NO ) 
                    809:     {
                    810:         return NO;
                    811:     }
                    812:     
                    813:     if ( (_controllerType == kControllerTypeCmd646X) && ((u_int)buffer & 1) )
                    814:     {
                    815:         return NO;
                    816:     }
                    817: 
                    818:     return YES;
                    819: }
                    820:         
                    821:       
                    822: @end

unix.superglobalmegacorp.com

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