Annotation of drvEIDE/EIDE.drvproj/EIDE.lksproj/IdeCntCmds.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:  * IdeCntCmds.m - Implementation of Commands category for IDE Controller 
                     29:  * device. 
                     30:  *
                     31:  * It contains implementation of the ATA command set. 
                     32:  *
                     33:  *
                     34:  * HISTORY 
                     35:  *
                     36:  * 23-Feb-1998         Joe Liu at Apple
                     37:  *  startUpAttachedDevices method is called immediately after acquiring
                     38:  *  the lock.
                     39:  *
                     40:  * 1-Feb-1998          Joe Liu at Apple
                     41:  *     ideSetDriveFeature method changed to support all EIDE transfer modes.
                     42:  *     Added support for Bus Master DMA.
                     43:  *  ideExecuteCmd now sets _driveNum within the retry loop.
                     44:  *
                     45:  * 1-Aug-1995          Rakesh Dubey at NeXT 
                     46:  *     Reduced the timeout in IDE_IDENTIFY_DRIVE method. 
                     47:  *
                     48:  * 17-July-1994        Rakesh Dubey at NeXT 
                     49:  *     Created. 
                     50:  */
                     51: 
                     52: //#define DEBUG
                     53: 
                     54: #import "IdeCnt.h"
                     55: #import "IdeCntInit.h"
                     56: #import "IdePIIX.h"
                     57: #import <kern/assert.h>
                     58: #import <driverkit/kernelDriver.h>
                     59: #import <driverkit/interruptMsg.h>
                     60: #import <mach/mach_interface.h>
                     61: #import <driverkit/IODevice.h>
                     62: #import <driverkit/align.h>
                     63: #import <machkit/NXLock.h>
                     64: #import <machdep/i386/io_inline.h>
                     65: #import "IdeDDM.h"
                     66: 
                     67: /*
                     68:  * All methods in this file implement one or more of the IDE commands. These
                     69:  * commands get invoked by IdeDisk objects. 
                     70:  */
                     71: 
                     72: @implementation IdeController(Commands)
                     73: 
                     74: /*
                     75:  * Returns a struct containing IDE registers values for a given sector
                     76:  * address and size. Depending upon whether the drive supports LBA or CHS we
                     77:  * fill in different values. The calling routine must make sure that these
                     78:  * values are not overwritten. The only thing that they need to fill in is
                     79:  * the drive number. 
                     80:  */
                     81: - (ideRegsVal_t)logToPhys:(unsigned)block numOfBlocks:(unsigned)nblk
                     82: {
                     83:     ideRegsVal_t rv;
                     84:     unsigned int cyl, nheads;
                     85:     unsigned int track, spt;
                     86: 
                     87:     if (_drives[_driveNum].addressMode == ADDRESS_MODE_CHS) {
                     88:                nheads = _drives[_driveNum].ideInfo.heads;
                     89:                spt = _drives[_driveNum].ideInfo.sectors_per_trk;
                     90:        
                     91:                track = (block / spt);
                     92:                cyl = track / nheads;
                     93:                rv.sectNum = block % spt + 1;
                     94:        
                     95:                rv.drHead = track % nheads;
                     96:                rv.cylLow = (cyl & 0xff);
                     97:                rv.cylHigh = ((cyl & 0xff00) >> 8);
                     98:     } else {
                     99:         rv.sectNum = block & 0x0ff;
                    100:                rv.cylLow = (block >> 8) & 0xff;
                    101:                rv.cylHigh = (block >> 16) & 0xff;
                    102:                rv.drHead = (block >> 24) & 0x0f;
                    103:     }
                    104:     
                    105:     rv.sectCnt = (nblk == MAX_BLOCKS_PER_XFER) ? 0 : nblk;
                    106: 
                    107:     rv.drHead |= _drives[_driveNum].addressMode;
                    108:     rv.drHead |= (_driveNum ? SEL_DRIVE1 : SEL_DRIVE0);
                    109:            
                    110:     return rv;
                    111: }
                    112: 
                    113: /*
                    114:  * Commands to the IDE controller. 
                    115:  */
                    116: 
                    117: 
                    118: - (ide_return_t)ideDiagnose:(unsigned *)diagError
                    119: {
                    120:     ide_return_t rtn;
                    121:     unsigned char status;
                    122:     
                    123:     rtn = [self waitForDeviceReady];
                    124:     if (rtn != IDER_SUCCESS)
                    125:        return IDER_CMD_ERROR;
                    126:        
                    127:     [self enableInterrupts];
                    128:     outb(_ideRegsAddrs.command, IDE_DIAGNOSE);
                    129:     
                    130:     rtn = [self ideWaitForInterrupt:IDE_DIAGNOSE ideStatus:&status];
                    131:     if (rtn != IDER_SUCCESS)   {
                    132:        [self getIdeRegisters:NULL Print:"Diagnose"];
                    133:        return IDER_CMD_ERROR;
                    134:     }
                    135: 
                    136:     rtn = [self waitForDeviceReady];
                    137:     if (rtn != IDER_SUCCESS)
                    138:        return IDER_CMD_ERROR;
                    139:     
                    140:     *diagError = inb(_ideRegsAddrs.error);
                    141:     
                    142:     if (*diagError == 0x01)    {
                    143:         /* FIXME: do we need to soft reset ATAPI devices? */
                    144:        return IDER_SUCCESS;
                    145:     }
                    146: 
                    147:     /*
                    148:      * At least one of the drives is bad. 
                    149:      */
                    150:     if (*diagError & 0x080) {
                    151:        IOLog("%s: Drive 1 has failed diagnostics.\n", [self name]);
                    152:        _drives[1].ideInfo.type = 0;
                    153: 
                    154:        if ((*diagError & 0x07f) != 1) {
                    155:            IOLog("%s: Drive 0 has failed diagnostics, error %d\n",
                    156:                    [self name], (*diagError & 0x07f));
                    157:            return IDER_CMD_ERROR;
                    158:        }
                    159:     } else {
                    160:        _drives[0].ideInfo.type = 0;
                    161:        IOLog("%s: Drive 0 has failed diagnostics, error %d\n",
                    162:                [self name], (*diagError & 0x07f));
                    163:     }
                    164:     
                    165:     return IDER_CMD_ERROR;
                    166: }
                    167: 
                    168: - (ide_return_t)ideSetParams:(unsigned)sectCnt numHeads:(unsigned)nHeads
                    169:                        ForDrive:(unsigned)drive
                    170: {
                    171:     unsigned char dh = _drives[drive].addressMode;
                    172:     ide_return_t rtn;
                    173: 
                    174:     rtn = [self waitForDeviceReady];
                    175:     if (rtn != IDER_SUCCESS)
                    176:        return rtn;
                    177:        
                    178:     dh |= ((drive ? SEL_DRIVE1 : SEL_DRIVE0) | ((nHeads - 1) & 0x0f));
                    179:     outb(_ideRegsAddrs.drHead, dh);
                    180:     outb(_ideRegsAddrs.sectCnt, (sectCnt & 0xff));
                    181:     
                    182:     [self enableInterrupts];
                    183:     outb(_ideRegsAddrs.command, IDE_SET_PARAMS);
                    184:     
                    185:     rtn = [self ideWaitForInterrupt:IDE_SET_PARAMS ideStatus:NULL];
                    186:     if (rtn != IDER_SUCCESS) {
                    187:        [self getIdeRegisters:NULL Print:"SetParams"];
                    188:        return rtn;
                    189:     }
                    190:     
                    191:     return rtn;
                    192: }
                    193: 
                    194: - (ide_return_t)ideSetDriveFeature:(unsigned char)feature
                    195:        value:(unsigned char)val
                    196:        transferType:(ideTransferType_t)type
                    197: {
                    198:     unsigned char dh = _drives[_driveNum].addressMode;
                    199:     unsigned char status;
                    200:     ide_return_t rtn;
                    201: //     unsigned char tmp;
                    202: 
                    203: #ifdef DEBUG
                    204:     IOLog("Setting drive feature %x to %x\n", feature, val);
                    205: #endif DEBUG
                    206: 
                    207:     /*
                    208:      * We are not going to do anything if EIDE support is disabled.
                    209:         *
                    210:         * Currently, this is useful only for setting the transfer mode.
                    211:      */
                    212:     if ((_EIDESupport == NO) || (feature != FEATURE_SET_TRANSFER_MODE) ||
                    213:                (val == ATA_MODE_NONE)) 
                    214:        return IDER_SUCCESS;
                    215:        
                    216:        val = ata_mode_to_num(val);
                    217: //     IOLog("Mode num: %d\n", val);
                    218:        
                    219:     rtn = [self waitForDeviceReady];
                    220:     if (rtn != IDER_SUCCESS)
                    221:        return rtn;
                    222:        
                    223:     dh |= (_driveNum ? SEL_DRIVE1 : SEL_DRIVE0);
                    224:     outb(_ideRegsAddrs.drHead, dh);
                    225:        
                    226:        val &= 0x07;
                    227:        switch (type) {
                    228:                case IDE_TRANSFER_PIO:
                    229:                        val |= (1 << 3);
                    230:                        break;
                    231:                case IDE_TRANSFER_SW_DMA:
                    232:                        val |= (1 << 4);
                    233:                        break;
                    234:                case IDE_TRANSFER_MW_DMA:
                    235:                        val |= (1 << 5);
                    236:                        break;
                    237:                case IDE_TRANSFER_ULTRA_DMA:
                    238:                        val |= (1 << 6);
                    239:                        break;
                    240:                default:
                    241:                        val = 0;
                    242:        }
                    243:        outb(_ideRegsAddrs.sectCnt, val);
                    244:     outb(_ideRegsAddrs.features, feature);
                    245:     
                    246:     [self enableInterrupts];
                    247:     outb(_ideRegsAddrs.command, IDE_SET_FEATURES);
                    248:     
                    249:     rtn = [self ideWaitForInterrupt:IDE_SET_FEATURES ideStatus:&status];
                    250:     if (rtn != IDER_SUCCESS) {
                    251:                [self getIdeRegisters:NULL Print:"SetFeatures"];
                    252:                return rtn;
                    253:     }
                    254:     
                    255:     if (status & ERROR)
                    256:        return IDER_ERROR;
                    257:     
                    258:     return rtn;
                    259: }
                    260: 
                    261: - (ide_return_t)ideRestore:(ideRegsVal_t *)ideRegs
                    262: {
                    263:     ide_return_t rtn;
                    264:     unsigned char status;
                    265:     unsigned char dh = _drives[_driveNum].addressMode;
                    266: 
                    267:     rtn = [self waitForDeviceReady];
                    268:     if (rtn != IDER_SUCCESS) {
                    269:        return rtn;
                    270:     }
                    271:     
                    272:     dh |= (_driveNum ? SEL_DRIVE1 : SEL_DRIVE0);
                    273:     outb(_ideRegsAddrs.drHead, dh);
                    274:     
                    275:     [self enableInterrupts];
                    276:     outb(_ideRegsAddrs.command, IDE_RESTORE);
                    277: 
                    278:     rtn = [self ideWaitForInterrupt:IDE_RESTORE ideStatus: &status];
                    279:     if (rtn != IDER_SUCCESS) {
                    280:        [self getIdeRegisters:NULL Print:"Restore"];
                    281:        return rtn;
                    282:     }
                    283:     
                    284:     rtn = [self waitForDeviceReady];
                    285:     if (rtn == IDER_SUCCESS) {
                    286:        if (status & ERROR) {
                    287:            [self getIdeRegisters:ideRegs Print:"Restore"];
                    288:            rtn = IDER_CMD_ERROR;
                    289:        }
                    290:     }
                    291: 
                    292:     return (rtn);
                    293: }
                    294: 
                    295: - (ide_return_t)ideReadGetInfoCommon:(ideRegsVal_t *)ideRegs
                    296:                            client:(struct vm_map *)client
                    297:                            addr:(caddr_t)xferAddr
                    298:                            command:(unsigned int)cmd
                    299: {
                    300:     ide_return_t rtn;
                    301:     unsigned int sec_cnt = ideRegs->sectCnt;
                    302:     int i;
                    303:     unsigned char *taddr;
                    304:     unsigned char status;
                    305:     unsigned char dh = _drives[_driveNum].addressMode;
                    306: 
                    307:     if (sec_cnt == 0)
                    308:        sec_cnt = MAX_BLOCKS_PER_XFER;
                    309:        
                    310:     taddr = xferAddr;
                    311: 
                    312:     /*
                    313:      * We have to define this for the IDE_IDENTIFY_DRIVE command. 
                    314:      */
                    315:     if (cmd == IDE_IDENTIFY_DRIVE)     {
                    316:        ideRegs->sectCnt = 1;
                    317:        sec_cnt = 1;
                    318:     }
                    319: 
                    320:     /*
                    321:      * Select the drive first. This routine is invoked by the initialization
                    322:      * code as well (-resetAndInit) so it is necessary to do this here. 
                    323:      */
                    324:     dh |= (_driveNum ? SEL_DRIVE1 : SEL_DRIVE0);
                    325:     outb(_ideRegsAddrs.drHead, dh);
                    326: 
                    327:     
                    328:     rtn = [self waitForDeviceReady];
                    329:     if (rtn != IDER_SUCCESS) {
                    330:         if (_ide_debug)        {
                    331:            IOLog("ideReadGetInfoCommon: waitForDeviceReady\n");
                    332:            [self getIdeRegisters:ideRegs Print:NULL];
                    333:        }
                    334:        return (rtn);
                    335:     }
                    336:     
                    337:     if (cmd == IDE_READ) {
                    338:        outb(_ideRegsAddrs.drHead, ideRegs->drHead);
                    339:        outb(_ideRegsAddrs.sectNum, ideRegs->sectNum);
                    340:        outb(_ideRegsAddrs.sectCnt, ideRegs->sectCnt);
                    341:        outb(_ideRegsAddrs.cylLow, ideRegs->cylLow);
                    342:        outb(_ideRegsAddrs.cylHigh, ideRegs->cylHigh);
                    343:     } else {
                    344:         /* probably unnecessary */
                    345:        outb(_ideRegsAddrs.drHead, dh);
                    346:        outb(_ideRegsAddrs.sectCnt, ideRegs->sectCnt);
                    347:     }
                    348:         
                    349:     [self enableInterrupts];
                    350:     outb(_ideRegsAddrs.command, cmd);
                    351:         
                    352:     for (i = 0; i < sec_cnt; i++)      {
                    353: 
                    354:        rtn = [self ideWaitForInterrupt:cmd ideStatus:&status];
                    355:        if (rtn != IDER_SUCCESS) {
                    356:            if (_ide_debug)     {
                    357:                IOLog("ideReadGetInfoCommon: ideWaitForInterrupt\n");
                    358:                [self getIdeRegisters:ideRegs Print:NULL];
                    359:            }
                    360:            return rtn;
                    361:        } else {
                    362:            /*
                    363:            if (status & ERROR_CORRECTED) {
                    364:                IOLog("%s: Corrected error during read.\n", [self name]);
                    365:            }
                    366:            */
                    367:        }
                    368:     
                    369:    /*
                    370:        * Same as waitForDataReady but with a quick timeout. 
                    371:        */
                    372:        rtn = [self ataIdeReadGetInfoCommonWaitForDataReady];
                    373:        if (rtn != IDER_SUCCESS) {
                    374:            if (_ide_debug)     {
                    375:                IOLog("ideReadGetInfoCommon: "
                    376:                        "ataIdeReadGetInfoCommonWaitForDataReady\n");
                    377:                [self getIdeRegisters:ideRegs Print:NULL];
                    378:            }
                    379:            return (rtn);
                    380:        }
                    381:        
                    382:        [self xferData:taddr read:YES client:client length:IDE_SECTOR_SIZE];
                    383:        taddr += IDE_SECTOR_SIZE;
                    384:     }
                    385: 
                    386:     return rtn;
                    387: }
                    388: 
                    389: - (ide_return_t)ideWrite:(ideRegsVal_t *)ideRegs
                    390:                    client:(struct vm_map *)client
                    391:                    addr:(caddr_t)xferAddr
                    392: {
                    393:     ide_return_t rtn;
                    394:     unsigned int sec_cnt = ideRegs->sectCnt;
                    395:     int i;
                    396:     unsigned char *taddr;
                    397:     unsigned char status;
                    398: 
                    399:     if (sec_cnt == 0)
                    400:        sec_cnt = MAX_BLOCKS_PER_XFER;
                    401:     
                    402:     taddr = xferAddr;
                    403: 
                    404:     rtn = [self waitForDeviceReady];
                    405:     if (rtn != IDER_SUCCESS) {
                    406:        return (rtn);
                    407:     }
                    408:     
                    409:     outb(_ideRegsAddrs.drHead, ideRegs->drHead);
                    410:     outb(_ideRegsAddrs.sectNum, ideRegs->sectNum);
                    411:     outb(_ideRegsAddrs.sectCnt, ideRegs->sectCnt);
                    412:     outb(_ideRegsAddrs.cylLow, ideRegs->cylLow);
                    413:     outb(_ideRegsAddrs.cylHigh, ideRegs->cylHigh);
                    414:     
                    415:     [self enableInterrupts];
                    416:     outb(_ideRegsAddrs.command, IDE_WRITE);
                    417: 
                    418:     for (i = 0; i < sec_cnt; i++)      {
                    419: 
                    420:        rtn = [self waitForDataReady];
                    421:        if (rtn != IDER_SUCCESS) {
                    422:            return (rtn);
                    423:        }
                    424: 
                    425:        [self xferData:taddr read:NO client:client length:IDE_SECTOR_SIZE];
                    426:        taddr += IDE_SECTOR_SIZE;
                    427: 
                    428:        rtn = [self ideWaitForInterrupt:IDE_WRITE ideStatus:&status];
                    429:     
                    430:        if (rtn != IDER_SUCCESS) {
                    431:            [self getIdeRegisters:ideRegs Print:"Write"];
                    432:            return (rtn);
                    433:        } else {
                    434:            /*
                    435:            if (status & ERROR_CORRECTED) {
                    436:                IOLog("%s: Corrected error during write.\n", [self name]);
                    437:            }
                    438:            */
                    439:        }
                    440:     }
                    441: 
                    442:     return (rtn);
                    443: }
                    444: 
                    445: - (ide_return_t)ideReadVerifySeekCommon:(ideRegsVal_t *)ideRegs
                    446:                            command:(unsigned int)cmd
                    447: {
                    448:     ide_return_t rtn;
                    449:     unsigned char status;
                    450: 
                    451:     rtn = [self waitForDeviceReady];
                    452:     if (rtn != IDER_SUCCESS) {
                    453:        return (rtn);
                    454:     }
                    455:     
                    456:     outb(_ideRegsAddrs.drHead, ideRegs->drHead);
                    457:     outb(_ideRegsAddrs.sectNum, ideRegs->sectNum);
                    458:     if (cmd == IDE_READ_VERIFY)
                    459:        outb(_ideRegsAddrs.sectCnt, ideRegs->sectCnt);
                    460:     outb(_ideRegsAddrs.cylLow, ideRegs->cylLow);
                    461:     outb(_ideRegsAddrs.cylHigh, ideRegs->cylHigh);
                    462: 
                    463:     [self enableInterrupts];
                    464:     outb(_ideRegsAddrs.command, cmd);
                    465:     
                    466:     rtn = [self ideWaitForInterrupt:cmd ideStatus: &status];
                    467:     if (rtn != IDER_SUCCESS) {
                    468:        [self getIdeRegisters:NULL Print:"ReadVerify/Seek"];
                    469:        return (rtn);
                    470:     }
                    471:     
                    472:     if (status & (ERROR | WRITE_FAULT)) {
                    473:        rtn = IDER_CMD_ERROR;
                    474:     } else {
                    475:        if ((cmd == IDE_SEEK) && (!(status & SEEK_COMPLETE)))
                    476:            rtn = IDER_CMD_ERROR;
                    477:     }
                    478: 
                    479:     return (rtn);
                    480: }
                    481: 
                    482: - (ide_return_t)ideSetMultiSectorMode:(ideRegsVal_t *)ideRegs
                    483:                            numSectors:(unsigned char)nSectors
                    484: {
                    485:     ide_return_t rtn;
                    486:     unsigned char status;
                    487:     unsigned char dh = _drives[_driveNum].addressMode;
                    488: 
                    489:     rtn = [self waitForDeviceReady];
                    490:     if (rtn != IDER_SUCCESS) {
                    491:        return (rtn);
                    492:     }
                    493:     
                    494:     dh |= (_driveNum ? SEL_DRIVE1 : SEL_DRIVE0);
                    495:     outb(_ideRegsAddrs.drHead, dh);
                    496:     outb(_ideRegsAddrs.sectCnt, nSectors);
                    497:     
                    498:     [self enableInterrupts];
                    499:     outb(_ideRegsAddrs.command, IDE_SET_MULTIPLE);
                    500: 
                    501:     rtn = [self ideWaitForInterrupt:IDE_SET_MULTIPLE ideStatus:&status];
                    502:     if (rtn != IDER_SUCCESS) {
                    503:        return (rtn);
                    504:     }
                    505:     
                    506:     rtn = [self waitForDeviceReady];
                    507:     if (rtn == IDER_SUCCESS) {
                    508:        if (status & ERROR) {
                    509:            rtn = IDER_CMD_ERROR;
                    510:            [self getIdeRegisters:ideRegs Print:NULL];
                    511:        } else
                    512:            rtn = IDER_SUCCESS;
                    513:     } 
                    514: 
                    515:     return (rtn);
                    516: }
                    517: 
                    518: /*
                    519:  * Note: Never read the status register at the end of data transfer, you may
                    520:  * clobber the next interrupt from the drive. If it is necessary to get
                    521:  * status use the alternate status register. 
                    522:  */
                    523: - (ide_return_t)ideReadMultiple:(ideRegsVal_t *)ideRegs
                    524:        client:(struct vm_map *)client
                    525:        addr:(caddr_t)xferAddr
                    526: {
                    527:     ide_return_t rtn;
                    528:     unsigned char status;
                    529:     unsigned sec_cnt = ideRegs->sectCnt;
                    530:     unsigned int nSectors;
                    531:     unsigned char *taddr;
                    532:     unsigned int length;
                    533: 
                    534:     if (sec_cnt == 0)
                    535:        sec_cnt = MAX_BLOCKS_PER_XFER;
                    536:        
                    537:     taddr = xferAddr;
                    538: 
                    539:     rtn = [self waitForDeviceReady];
                    540:     if (rtn != IDER_SUCCESS) {
                    541:        return (rtn);
                    542:     }
                    543:     
                    544:     outb(_ideRegsAddrs.drHead, ideRegs->drHead);
                    545:     outb(_ideRegsAddrs.sectNum, ideRegs->sectNum);
                    546:     outb(_ideRegsAddrs.sectCnt, ideRegs->sectCnt);
                    547:     outb(_ideRegsAddrs.cylLow, ideRegs->cylLow);
                    548:     outb(_ideRegsAddrs.cylHigh, ideRegs->cylHigh);
                    549: 
                    550:     [self enableInterrupts];
                    551:     outb(_ideRegsAddrs.command, IDE_READ_MULTIPLE);
                    552: 
                    553:     ddm_ide_cmd("ideReadMultiple: sec_cnt %d sectors\n", sec_cnt, 2,3,4,5);
                    554:     
                    555:     while (sec_cnt > 0) {
                    556: 
                    557:        ddm_ide_cmd("ideReadMultiple: waiting for interrupt\n",1,2,3,4,5);
                    558:        rtn = [self ideWaitForInterrupt:IDE_READ_MULTIPLE
                    559:                        ideStatus: &status];
                    560:        ddm_ide_cmd("ideReadMultiple: received interrupt\n",1,2,3,4,5);
                    561: 
                    562:        if (rtn != IDER_SUCCESS) {
                    563:            [self getIdeRegisters:ideRegs Print:"Read Multiple"];
                    564:            return (rtn);
                    565:        }
                    566: 
                    567: #if 1  
                    568:        rtn = [self waitForDataReady];
                    569:        if (rtn != IDER_SUCCESS) {
                    570:            return (rtn);
                    571:        }
                    572: #endif 1
                    573: 
                    574:        if (status & (ERROR | WRITE_FAULT)) {
                    575:            [self getIdeRegisters:ideRegs Print:"Read Multiple"];
                    576:            return IDER_CMD_ERROR;
                    577:        }
                    578: 
                    579:        /*
                    580:         * Any drive formatted with 63 sector/track (which most over 400 MB
                    581:         * are) reporting this status (ERROR_CORRECTED) will cause an
                    582:         * fallacious error (possibly uncorrectable) due to a long-standing
                    583:         * bug in DOS. This status bit should be made vendor specific, like
                    584:         * IDX. It has outlived its usefulness. 
                    585:         * -- [email protected] 
                    586:         */
                    587:         
                    588:        /*
                    589:        if (status & ERROR_CORRECTED) {
                    590:            IOLog("%s: Corrected error during read.\n", [self name]);
                    591:        }
                    592:        */
                    593: 
                    594:        /*
                    595:         * All is well. Read in the data. 
                    596:         */
                    597:        if (sec_cnt > _drives[_driveNum].multiSector)
                    598:            nSectors = _drives[_driveNum].multiSector;
                    599:        else
                    600:            nSectors = sec_cnt;
                    601:            
                    602:        sec_cnt -= nSectors;
                    603: 
                    604:        ddm_ide_cmd("ideReadMultiple: starting data transfer\n",1,2,3,4,5);
                    605: 
                    606:        while (nSectors) {
                    607:            if (nSectors > PAGE_SIZE / IDE_SECTOR_SIZE) {
                    608:                length = PAGE_SIZE;
                    609:                nSectors -= (PAGE_SIZE / IDE_SECTOR_SIZE);
                    610:            } else {
                    611:                length = nSectors * IDE_SECTOR_SIZE;
                    612:                nSectors = 0;
                    613:            }
                    614: 
                    615:            [self xferData:taddr read:YES client:client length:length];
                    616:            taddr += length;
                    617:        }
                    618: 
                    619:        ddm_ide_cmd("ideReadMultiple: data transfer done\n",1,2,3,4,5);
                    620:     }
                    621: 
                    622:     ddm_ide_cmd("ideReadMultiple: completed\n",1,2,3,4,5);
                    623: 
                    624:     return (rtn);
                    625: }
                    626: 
                    627: - (ide_return_t)ideWriteMultiple:(ideRegsVal_t *)ideRegs
                    628:        client:(struct vm_map *)client 
                    629:        addr:(caddr_t)xferAddr
                    630: {
                    631:     ide_return_t rtn;
                    632:     unsigned char status;
                    633:     unsigned sec_cnt = ideRegs->sectCnt;
                    634:     unsigned int nSectors;
                    635:     unsigned char *taddr;
                    636:     unsigned int length;
                    637: 
                    638:     if (sec_cnt == 0)
                    639:        sec_cnt = MAX_BLOCKS_PER_XFER;
                    640:        
                    641:     taddr = xferAddr;
                    642: 
                    643:     rtn = [self waitForDeviceReady];
                    644:     if (rtn != IDER_SUCCESS) {
                    645:        return (rtn);
                    646:     }
                    647:     
                    648:     outb(_ideRegsAddrs.drHead, ideRegs->drHead);
                    649:     outb(_ideRegsAddrs.sectNum, ideRegs->sectNum);
                    650:     outb(_ideRegsAddrs.sectCnt, ideRegs->sectCnt);
                    651:     outb(_ideRegsAddrs.cylLow, ideRegs->cylLow);
                    652:     outb(_ideRegsAddrs.cylHigh, ideRegs->cylHigh);
                    653:     
                    654:     [self enableInterrupts];
                    655:     outb(_ideRegsAddrs.command, IDE_WRITE_MULTIPLE);
                    656: 
                    657:     ddm_ide_cmd("ideWriteMultiple: sec_cnt %d sectors\n", sec_cnt, 2,3,4,5);
                    658: 
                    659:     while (sec_cnt > 0) {
                    660:     
                    661:        rtn = [self waitForDataReady];
                    662:        if (rtn != IDER_SUCCESS) {
                    663:            return (rtn);
                    664:        }
                    665:        
                    666:        if (sec_cnt > _drives[_driveNum].multiSector)
                    667:            nSectors = _drives[_driveNum].multiSector;
                    668:        else
                    669:            nSectors = sec_cnt;
                    670:            
                    671:        sec_cnt -= nSectors;
                    672: 
                    673:        ddm_ide_cmd("ideWriteMultiple: starting data transfer\n",1,2,3,4,5);
                    674: 
                    675:        while (nSectors) {
                    676:            if (nSectors > PAGE_SIZE / IDE_SECTOR_SIZE) {
                    677:                length = PAGE_SIZE;
                    678:                nSectors -= (PAGE_SIZE / IDE_SECTOR_SIZE);
                    679:            } else {
                    680:                length = nSectors * IDE_SECTOR_SIZE;
                    681:                nSectors = 0;
                    682:            }
                    683: 
                    684:            [self xferData:taddr read:NO client:client length:length];
                    685:            taddr += length;
                    686:        }
                    687:        ddm_ide_cmd("ideWriteMultiple: data transfer done\n",1,2,3,4,5);
                    688: 
                    689:        ddm_ide_cmd("ideWriteMultiple: waiting for interrupt\n",1,2,3,4,5);
                    690:        rtn = [self ideWaitForInterrupt:IDE_WRITE_MULTIPLE 
                    691:                                ideStatus:&status];
                    692:        ddm_ide_cmd("ideWriteMultiple: received interrupt\n",1,2,3,4,5);
                    693: 
                    694:        if (rtn != IDER_SUCCESS) {
                    695:            [self getIdeRegisters:ideRegs Print:"Write Multiple"];
                    696:            return (rtn);
                    697:        }
                    698:        
                    699:        if (status & (ERROR | WRITE_FAULT)) {
                    700:            [self getIdeRegisters:ideRegs Print:"Write Multiple"];
                    701:            return IDER_CMD_ERROR;
                    702:        }
                    703:        
                    704:        /*
                    705:        if (status & ERROR_CORRECTED) {
                    706:            IOLog("%s: Corrected error during write.\n", [self name]);
                    707:        }
                    708:        */
                    709:        
                    710:     }
                    711: 
                    712:     ddm_ide_cmd("ideWriteMultiple: completed\n",1,2,3,4,5);
                    713: 
                    714:     return (rtn);
                    715: }
                    716: 
                    717: /*
                    718:  * Method: performDMATestOnDrive:(unsigned char)drive
                    719:  *
                    720:  * Purpose:
                    721:  * Read a few sectors and make sure DMA really "seems" to works.
                    722:  *
                    723:  * NOTE: _driveNum must be set prior to calling this method.
                    724:  */
                    725: - (ide_return_t)performDMATest
                    726: {
                    727:     ideIoReq_t ideIoReq;
                    728:     ide_return_t status;
                    729:     vm_offset_t tempDmaBuf;
                    730:        vm_offset_t alignBuf;
                    731:        unsigned int currentTimeout;
                    732:     unsigned char      dh;
                    733:        
                    734:     /*
                    735:      * The hardware claims to supports DMA. Verify by reading a
                    736:      * few sectors. Allocate memory for dummy buffer.
                    737:      */
                    738:        tempDmaBuf = (vm_offset_t)IOMalloc(PAGE_SIZE);
                    739:     if (tempDmaBuf == NULL)    {
                    740:                IOLog("%s: memory allocation failed\n", [self name]);
                    741:                return IDER_REJECT;
                    742:     }
                    743: 
                    744:        /*
                    745:         * Advance the pointer and make the buffer 4 byte aligned.
                    746:         */
                    747:        alignBuf = (tempDmaBuf + 3) & ~3;
                    748: 
                    749:        bzero((unsigned char *)&ideIoReq, sizeof(ideIoReq_t));
                    750:     ideIoReq.cmd = IDE_READ_DMA;
                    751:     ideIoReq.block = 0;
                    752:     ideIoReq.blkcnt = (PAGE_SIZE - 4)/IDE_SECTOR_SIZE;
                    753:     ideIoReq.addr = (caddr_t)alignBuf;
                    754:     ideIoReq.timeout = 5000;
                    755:     ideIoReq.map = (struct vm_map *)IOVmTaskSelf();
                    756:        
                    757:        /*
                    758:         * Select the drive first.
                    759:         */
                    760:        if ([self waitForDeviceIdle] != IDER_SUCCESS) {
                    761:                IOLog("%s: Drive %d DMA test FAILED\n", [self name], _driveNum);
                    762:                return IDER_TIMEOUT;
                    763:        }
                    764:     dh = _drives[_driveNum].addressMode;
                    765:     dh |= (_driveNum ? SEL_DRIVE1 : SEL_DRIVE0);
                    766:     outb(_ideRegsAddrs.drHead, dh);
                    767:        
                    768:        /*
                    769:         * Wait 400ns before reading the status register and make sure the
                    770:         * currently selected drive is ready to accept a command.
                    771:         */
                    772:        IODelay(1);
                    773:        if ([self waitForDeviceIdle] != IDER_SUCCESS) {
                    774:                IOLog("%s: Drive %d DMA test FAILED\n", [self name], _driveNum);
                    775:                return IDER_TIMEOUT;
                    776:        }       
                    777:        
                    778:        /*
                    779:         * Clear any unwanted interrupts which may have accumulated.
                    780:         */
                    781:        [self enableInterrupts];
                    782:        IOSleep(100);
                    783:        
                    784:        /*
                    785:         * Set a smaller (3 sec) timeout for this test.
                    786:         */
                    787:        currentTimeout = [self interruptTimeOut];
                    788:        [self setInterruptTimeOut:3000];
                    789:        [self clearInterrupts];
                    790:        
                    791:        /*
                    792:         * Perform test.
                    793:         */
                    794:        if (([self performDMA:(ideIoReq_t *)&ideIoReq]) == IDER_SUCCESS) {
                    795:                status = IDER_SUCCESS;
                    796: //             IOLog("%s: Drive %d: DMA test PASSED\n", [self name], _driveNum);
                    797:        }
                    798:        else {
                    799:                status = IDER_REJECT;
                    800:        IOLog("%s: Drive %d: DMA test FAILED\n", [self name], _driveNum);
                    801:        }
                    802:        
                    803:        /*
                    804:         * Revert the original timeout value and free allocated memory.
                    805:         */
                    806:        [self setInterruptTimeOut:currentTimeout];
                    807:     IOFree((void *)tempDmaBuf, PAGE_SIZE);
                    808:        return status;
                    809: }
                    810: 
                    811: /*
                    812:  * All I/O to to controller object is done through this method. We first
                    813:  * acquire a lock before executing any IDE commands since the IDE controller
                    814:  * can do only one thing at a time (both drivers can not be active
                    815:  * simultaneously except for reset and disgnostics). 
                    816:  *
                    817:  * If it necessary to call any of the IDE command methods (which are invoked by
                    818:  * the switch() below, like ideReadGetInfoCommon:client:addr:command) it is
                    819:  * necessary to acquire the lock. The IDE command methods should not be
                    820:  * invoked directly by the Disk object. 
                    821:  *
                    822:  * This method will in turn call one of several methods which deal with
                    823:  * hardware. 
                    824:  */
                    825: 
                    826: static unsigned char unaligned_warnings;
                    827: #define UNALIGNED_WARNINGS_MAX 20
                    828: 
                    829: #define MAX_COMMAND_RETRY      3
                    830: 
                    831: - (IOReturn) ideExecuteCmd:(ideIoReq_t *)ideIoReq ToDrive:(unsigned char)drive
                    832: {
                    833:     int                retry;
                    834:     ideRegsVal_t       irv;
                    835:     unsigned           block, cnt;
                    836:     unsigned           error;
                    837:     unsigned int       maxSectors;
                    838:     unsigned char      dh;
                    839: 
                    840:     ddm_ide_cmd("ideExecuteCmd: executing %x\n", ideIoReq->cmd,2,3,4,5);
                    841: 
                    842:     /*
                    843:      * If the controller wishes to put the drive to sleep, it sets this flag
                    844:      * to YES and tries to acquire the lock. This method should not try to
                    845:      * get the lock (and execute any more commands) if the flag is set. This
                    846:      * is needed in order to enter sleep mode as soon as the current command
                    847:      * is finished. If we do not do this there is contention for lock between
                    848:      * the controller (which wants to put the drive to sleep) and this method
                    849:      * (which wants to service more requests). Note that this does not do
                    850:      * away with the need for a lock, it only gives the controller a little
                    851:      * head-start. 
                    852:      */
                    853:     
                    854:     while (_driveSleepRequest) {
                    855:                IOSleep(100);
                    856:     }
                    857:      
                    858:     ddm_ide_lock("ideExecuteCmd: acquiring lock\n",1,2,3,4,5);
                    859:     [self ideCntrlrLock];
                    860:     ddm_ide_lock("ideExecuteCmd: acquired lock\n",1,2,3,4,5);
                    861: 
                    862:    /*
                    863:     * Check if we need to do a media access to get the drive respinning
                    864:     * after a suspend operation. 
                    865:     */
                    866:     if ([self drivePowerState] != IDE_PM_ACTIVE) {
                    867:                [self startUpAttachedDevices];
                    868:     }
                    869: 
                    870:     _driveNum = drive;         /* used by IDE command methods. */
                    871:        
                    872:     for  (retry = 0; retry < MAX_COMMAND_RETRY; retry++) {
                    873:     
                    874:     /*
                    875:      * Select the drive first. We don't know the head number at this time so
                    876:      * this register will be rewritten by the specific routine later.
                    877:         *
                    878:         * The Device Selection protocol is defined as follows:
                    879:         * HOST: Read Status or AltStatus register
                    880:         * HOST: Continue reading until BSY = 0, and DRQ = 0
                    881:         * HOST: Write Device/Head register with appropriate DEV bit value
                    882:         * HOST: Wait 400ns
                    883:         * HOST: Read Status or AltStatus register
                    884:         * HOST: Continue reading until BSY = 0, and DRQ = 0
                    885:         *
                    886:      */
                    887: //     [self waitForDeviceIdle];       // Devices should be already in an idle state
                    888:     dh = _drives[_driveNum].addressMode;
                    889:     dh |= (_driveNum ? SEL_DRIVE1 : SEL_DRIVE0);
                    890:     outb(_ideRegsAddrs.drHead, dh);
                    891:        IODelay(1);
                    892: //     [self waitForDeviceIdle];       // Each method below will do their own wait
                    893: 
                    894:     ideIoReq->status = IDER_CMD_ERROR;
                    895:     ideIoReq->blocks_xfered = 0;
                    896:        
                    897:        [self clearInterrupts];
                    898: 
                    899:        switch (ideIoReq->cmd) {
                    900: 
                    901:          case IDE_READ_DMA:
                    902:                if (((vm_offset_t)ideIoReq->addr & 0x03) == 0) {
                    903:            block = ideIoReq->block;
                    904:            cnt = ideIoReq->blkcnt;
                    905:                ddm_ide_log("IDE_READ_DMA: %d\n", cnt, 2, 3, 4, 5);
                    906:            if (cnt > MAX_BLOCKS_PER_XFER) {
                    907:                        ideIoReq->status = IDER_REJECT;
                    908:                        break;
                    909:            }
                    910: 
                    911:                ideIoReq->status = [self performDMA:ideIoReq];
                    912:                if (ideIoReq->status == IDER_SUCCESS)
                    913:                ideIoReq->blocks_xfered = ideIoReq->blkcnt;
                    914:            break;
                    915:                }
                    916:                
                    917:                /*
                    918:                 * If we reached here, it means that the buffer is not 4-byte
                    919:                 * aligned. This should not happen.
                    920:                 */
                    921:                if (unaligned_warnings < UNALIGNED_WARNINGS_MAX) {
                    922:                        IOLog("%s: READ DMA: buffer not 4-byte aligned\n", [self name]);
                    923:                        unaligned_warnings++;
                    924:                }
                    925: 
                    926:          case IDE_READ:
                    927:          case IDE_READ_MULTIPLE:
                    928: 
                    929:            block = ideIoReq->block;
                    930:            cnt = ideIoReq->blkcnt;
                    931:                ddm_ide_log("IDE_READ: %d\n", cnt, 2, 3, 4, 5);
                    932:            if (cnt > MAX_BLOCKS_PER_XFER)      {
                    933:                        ideIoReq->status = IDER_REJECT;
                    934:                        break;
                    935:            }
                    936:            ideIoReq->regValues = [self logToPhys:block numOfBlocks:cnt];
                    937:            if (ideIoReq->cmd == IDE_READ)
                    938:                ideIoReq->status = 
                    939:                        [self ideReadGetInfoCommon:&(ideIoReq->regValues) 
                    940:                        client:(ideIoReq->map) 
                    941:                        addr:(ideIoReq->addr) command:IDE_READ];
                    942:            else
                    943:                ideIoReq->status =
                    944:                    [self ideReadMultiple:&(ideIoReq->regValues)
                    945:                     client:(ideIoReq->map) addr:(ideIoReq->addr)];
                    946: 
                    947:            if (ideIoReq->status == IDER_SUCCESS)
                    948:                ideIoReq->blocks_xfered = ideIoReq->blkcnt;
                    949:            break;
                    950: 
                    951:          case IDE_WRITE_DMA:
                    952:                if (((vm_offset_t)ideIoReq->addr & 0x03) == 0) {
                    953:            block = ideIoReq->block;
                    954:            cnt = ideIoReq->blkcnt;
                    955:                ddm_ide_log("IDE_WRITE_DMA: %d\n", cnt, 2, 3, 4, 5);
                    956:            if (cnt > MAX_BLOCKS_PER_XFER) {
                    957:                        ideIoReq->status = IDER_REJECT;
                    958:                        break;
                    959:            }
                    960: 
                    961:                ideIoReq->status = [self performDMA:ideIoReq];
                    962:                if (ideIoReq->status == IDER_SUCCESS)
                    963:                ideIoReq->blocks_xfered = ideIoReq->blkcnt;
                    964:            break;
                    965:                }
                    966: 
                    967:                /*
                    968:                 * If we reached here, it means that the buffer is not 4-byte
                    969:                 * aligned. This should not happen.
                    970:                 */
                    971:                if (unaligned_warnings < UNALIGNED_WARNINGS_MAX) {
                    972:                        IOLog("%s: WRITE DMA: buffer not 4-byte aligned\n", [self name]);
                    973:                        unaligned_warnings++;
                    974:                }
                    975: 
                    976:          case IDE_WRITE:
                    977:          case IDE_WRITE_MULTIPLE:
                    978: 
                    979:            block = ideIoReq->block;
                    980:            cnt = ideIoReq->blkcnt;
                    981:                ddm_ide_log("IDE_WRITE: %d\n", cnt, 2, 3, 4, 5);
                    982:            if (cnt > MAX_BLOCKS_PER_XFER) {
                    983:                        ideIoReq->status = IDER_REJECT;
                    984:                        break;
                    985:            }
                    986:            ideIoReq->regValues = [self logToPhys:block numOfBlocks:cnt];
                    987:            if (ideIoReq->cmd == IDE_WRITE)
                    988:                ideIoReq->status = [self ideWrite:&(ideIoReq->regValues)
                    989:                                        client:(ideIoReq->map)
                    990:                                        addr:(ideIoReq->addr)];
                    991:            else
                    992:                ideIoReq->status = 
                    993:                        [self ideWriteMultiple:&(ideIoReq->regValues)
                    994:                        client:(ideIoReq->map) addr:(ideIoReq->addr)];
                    995: 
                    996:            if (ideIoReq->status == IDER_SUCCESS)
                    997:                ideIoReq->blocks_xfered = ideIoReq->blkcnt;
                    998:            break;
                    999: 
                   1000:          case IDE_SEEK:
                   1001:            block = ideIoReq->block;
                   1002:            cnt = 1;
                   1003:            ideIoReq->regValues = [self logToPhys:block numOfBlocks:cnt];
                   1004:            ideIoReq->status = 
                   1005:                        [self ideReadVerifySeekCommon:&(ideIoReq->regValues) 
                   1006:                                command:IDE_SEEK];
                   1007:            break;
                   1008: 
                   1009:          case IDE_RESTORE:
                   1010:            ideIoReq->status = [self ideRestore:&(ideIoReq->regValues)];
                   1011:            break;
                   1012: 
                   1013:          case IDE_READ_VERIFY:
                   1014:            block = ideIoReq->block;
                   1015:            cnt = ideIoReq->blkcnt;
                   1016:                ddm_ide_log("IDE_READ_VERIFY: %d\n", cnt, 2, 3, 4, 5);
                   1017:            if (cnt > MAX_BLOCKS_PER_XFER) {
                   1018:                ideIoReq->status = IDER_REJECT;
                   1019:                break;
                   1020:            }
                   1021:            ideIoReq->regValues = [self logToPhys:block numOfBlocks:cnt];
                   1022:            ideIoReq->status = 
                   1023:                [self ideReadVerifySeekCommon:&(ideIoReq->regValues)
                   1024:                                command:IDE_READ_VERIFY];
                   1025:            break;
                   1026: 
                   1027:          case IDE_DIAGNOSE:
                   1028:            [self ideDiagnose:&error];
                   1029:            ideIoReq->diagResult = error;
                   1030:            ideIoReq->status = IDER_SUCCESS;
                   1031:            break;
                   1032: 
                   1033:          case IDE_SET_PARAMS:
                   1034:            ideIoReq->status = 
                   1035:                        [self ideSetParams:_drives[_driveNum].ideInfo.sectors_per_trk
                   1036:                        numHeads:_drives[_driveNum].ideInfo.heads ForDrive:_driveNum];
                   1037:            break;
                   1038: 
                   1039:          case IDE_IDENTIFY_DRIVE:
                   1040:            ideIoReq->status = 
                   1041:                        [self ideReadGetInfoCommon:&(ideIoReq->regValues)
                   1042:                        client :(ideIoReq->map) addr :(ideIoReq->addr)
                   1043:                        command:IDE_IDENTIFY_DRIVE];
                   1044: 
                   1045:            if (ideIoReq->status == IDER_SUCCESS)
                   1046:                ideIoReq->blocks_xfered = 1;
                   1047:            break;
                   1048: 
                   1049:          case IDE_SET_MULTIPLE:
                   1050:             maxSectors = (_drives[_driveNum].ideIdentifyInfo->multipleSectors) 
                   1051:                                & IDE_MULTI_SECTOR_MASK;
                   1052:            if (ideIoReq->maxSectorsPerIntr > maxSectors) {
                   1053:                ideIoReq->status = IDER_REJECT;
                   1054:            } else {
                   1055:                ideIoReq->status = [self ideSetMultiSectorMode:
                   1056:                                    &(ideIoReq->regValues)
                   1057:                                    numSectors:ideIoReq->maxSectorsPerIntr];
                   1058:                if (ideIoReq->status == IDER_SUCCESS)
                   1059:                    _drives[_driveNum].multiSector = ideIoReq->maxSectorsPerIntr;
                   1060:                else
                   1061:                    _drives[_driveNum].multiSector = 0;
                   1062:            }
                   1063:            break;
                   1064: 
                   1065:          default:
                   1066:            ideIoReq->status = IDER_REJECT;
                   1067:            ddm_ide_lock("ideExecuteCmd: releasing lock, bad cmd\n",1,2,3,4,5);
                   1068:            [self ideCntrlrUnLock];
                   1069:            return (IDER_REJECT);
                   1070:        }
                   1071: 
                   1072:        /*
                   1073:         * Return if command has been executed successfully or summarily
                   1074:         * rejected. 
                   1075:         */
                   1076:        if (ideIoReq->status == IDER_SUCCESS)   {
                   1077:            [self ideCntrlrUnLock];
                   1078:            ddm_ide_lock("ideExecuteCmd: releasing lock, success\n",1,2,3,4,5);
                   1079:            return IDER_SUCCESS;
                   1080:        }
                   1081:        
                   1082:        if (ideIoReq->status == IDER_REJECT)    {
                   1083:            [self ideCntrlrUnLock];
                   1084:            ddm_ide_lock("ideExecuteCmd: releasing lock, reject\n",1,2,3,4,5);
                   1085:            return IDER_REJECT;
                   1086:        }
                   1087: 
                   1088:        /*
                   1089:         * The command failed to exceute properly but was accepted by the
                   1090:         * drive. Reset the drives and try again. 
                   1091:         */
                   1092:        IOLog("%s: ATA command %x failed. Retrying...\n", [self name], 
                   1093:                ideIoReq->cmd);
                   1094:        [self getIdeRegisters:NULL Print:"ATA Command"];
                   1095:        [self resetAndInit];
                   1096:        
                   1097:        /*
                   1098:         * resetAndInit will change the value of _driveNum.
                   1099:         * Revert _driveNum to the original value before retrying the
                   1100:         * command.
                   1101:         */
                   1102:        _driveNum = drive;
                   1103:        (void) [self ideRestore:&irv];
                   1104:     }
                   1105: 
                   1106:     /*
                   1107:      * If we get here then this is a catastrophic failure. 
                   1108:      */
                   1109:     ddm_ide_lock("ideExecuteCmd: releasing lock, failed\n",1,2,3,4,5);
                   1110:     [self ideCntrlrUnLock];
                   1111:     return ideIoReq->status;
                   1112: }
                   1113: 
                   1114: @end

unix.superglobalmegacorp.com

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