Annotation of drvEIDE/EIDE.drvproj/EIDE.lksproj/IdePIIX.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:  * IdePIIX.m - PIIX/PCI specific ATA controller initialization module. 
                     29:  *
                     30:  * 23-Jan-1998 Joe Liu at Apple
                     31:  *  Added support for PIIX/PIIX3/PIIX4 PCI IDE controllers.
                     32:  *
                     33:  * 05-Apr-1995 Rakesh Dubey at NeXT
                     34:  *     Fixed some bugs in PCI support.
                     35:  * 03-Oct-1994         Rakesh Dubey at NeXT
                     36:  *      Created. 
                     37:  */
                     38: 
                     39: #import "IdeCnt.h"
                     40: #import "IdePIIX.h"
                     41: #import "IdeCntCmds.h"
                     42: #import <driverkit/i386/IOPCIDeviceDescription.h>
                     43: #import <driverkit/i386/IOPCIDirectDevice.h>
                     44: #import <driverkit/generalFuncs.h>
                     45: #import <driverkit/kernelDriver.h>
                     46: #import <driverkit/interruptMsg.h>
                     47: #import <mach/mach_interface.h>
                     48: #import <machdep/i386/io_inline.h>
                     49: #import <string.h>
                     50: #import <stdio.h>
                     51: #import "IdeDDM.h"
                     52: #import "PIIX.h"
                     53: #import "PIIXTiming.h"
                     54: #import "IdeShared.h"
                     55: 
                     56: // XXX get rid of this
                     57: #if (IO_DRIVERKIT_VERSION != 330)
                     58: #import <machdep/machine/pmap.h>
                     59: #endif
                     60: 
                     61: extern vm_offset_t pmap_resident_extract(pmap_t pmap, vm_offset_t va);
                     62: 
                     63: //#define DEBUG
                     64: 
                     65: #ifndef MIN
                     66: #define MIN(a,b)    ((a) < (b) ? (a) : (b))
                     67: #endif  MIN
                     68: 
                     69: #ifndef MAX
                     70: #define MAX(a,b)    ((a) > (b) ? (a) : (b))
                     71: #endif  MAX
                     72: 
                     73: /*
                     74:  * Function: IOMallocPage
                     75:  *
                     76:  * Purpose:
                     77:  *   Returns a pointer to a page-aligned memory block of size >= PAGE_SIZE.
                     78:  *   Note that on Intel, the hardware page size of 4K. However, MACH's
                     79:  *   notion of a page is 8K, which is comprised of two contiguous
                     80:  *   (physical/virtual) hardware pages.
                     81:  *
                     82:  * Return:
                     83:  *   Actual pointer and size of block returned in actual_ptr and actual_size.
                     84:  *   Use these as arguments to IOFree: IOFree(*actual_ptr, *actual_size);
                     85:  */
                     86: static void *
                     87: IOMallocPage(int request_size, void ** actual_ptr,
                     88:                                 int * actual_size)
                     89: {
                     90:     void * mem_ptr;
                     91:     
                     92:        /*
                     93:         * Minimize memory use by first trying to allocate the requested size
                     94:         * without any padding.
                     95:         */
                     96:        *actual_size = round_page(request_size);
                     97:        mem_ptr = IOMalloc(*actual_size);
                     98:        if (mem_ptr == NULL)
                     99:                return NULL;
                    100:        
                    101:        /*
                    102:         * Check alignment of this page.
                    103:         */
                    104:        if ((vm_offset_t)mem_ptr & (PAGE_SIZE - 1)) {   // NOT page aligned.
                    105:                IOFree(mem_ptr, *actual_size);
                    106:                *actual_size = round_page(request_size) + PAGE_SIZE;
                    107:                mem_ptr = IOMalloc(*actual_size);
                    108:                if (mem_ptr == NULL)
                    109:                        return NULL;            
                    110:        }
                    111: 
                    112:        *actual_ptr = mem_ptr;
                    113:        return ((void *)round_page(mem_ptr));           
                    114: }
                    115: 
                    116: @implementation IdeController(PIIX)
                    117: 
                    118: /*
                    119:  * Method: probePCIController
                    120:  *
                    121:  * Purpose:
                    122:  * Probe the existence of a supported PCI chipset, then proceed to
                    123:  * record the PCI IDE controller found.
                    124:  *
                    125:  * Note:
                    126:  * This is called before [super init...], and so we use the class version
                    127:  * of getPCIdevice method calls.
                    128:  *
                    129:  */
                    130: - (BOOL) probePCIController:(IOPCIDeviceDescription *)devDesc
                    131: {
                    132:     unsigned char      devNum, funcNum, busNum;
                    133:     const char                 *value;
                    134:        const char              *deviceName;
                    135:        IOConfigTable   *configTable;
                    136:     IOReturn           rtn;
                    137:     const id self_class = [self class];
                    138: 
                    139:        /*
                    140:         * Initialize PCI ivars.
                    141:         */
                    142:        _controllerID = PCI_ID_NONE;
                    143:        _ideChannel   = PCI_CHANNEL_OTHER;
                    144:        _busMaster    = NO;
                    145:        bzero((char *)&_prdTable, sizeof(_prdTable));
                    146:        
                    147:        /*
                    148:         * Make sure we are dealing with a PCI config table by reading the
                    149:         * BUS_TYPE key.
                    150:         */
                    151:     configTable = [devDesc configTable];
                    152:     value = [configTable valueForStringKey:BUS_TYPE];
                    153:     if (!value || strcmp(value, "PCI") != 0) {
                    154:                // Not PCI, return YES to continue probing for non PCI controllers.
                    155:                return YES;
                    156:     }
                    157:     
                    158:        /*
                    159:         * Read PCI config space for VendorID and DeviceID.
                    160:         */
                    161:     rtn = [devDesc getPCIdevice:&devNum function:&funcNum bus:&busNum];
                    162:     if (rtn != IO_R_SUCCESS) {
                    163:        IOLog("%s: Unsupported PCI hardware\n", [self name]);
                    164:                return NO;
                    165:     }
                    166:     rtn = [self_class getPCIConfigData:&_controllerID atRegister:0x00
                    167:                withDeviceDescription:devDesc];
                    168:     if (rtn != IO_R_SUCCESS)   {
                    169:        IOLog("%s: PCI config space access error %d\n", [self name], rtn);
                    170:                return NO;
                    171:     }    
                    172: 
                    173:        switch (_controllerID) {
                    174:                case PCI_ID_PIIX:
                    175:                        deviceName = "PIIX";
                    176:                        break;
                    177:                case PCI_ID_PIIX3:
                    178:                        deviceName = "PIIX3";
                    179:                        break;
                    180:                case PCI_ID_PIIX4:
                    181:                        deviceName = "PIIX4";
                    182:                        break;
                    183:                default:
                    184:                        IOLog("%s: Unknown PCI IDE controller (0x%08lx)\n",
                    185:                                [self name], _controllerID);
                    186:                        _controllerID = PCI_ID_NONE;
                    187:                        return NO;
                    188:        }
                    189: 
                    190:        /*
                    191:         * Report the PCI controller found.
                    192:         */
                    193:        IOLog("%s: %s PCI IDE Controller at Dev:%d Func:%d Bus:%d\n",
                    194:                [self name], deviceName, devNum, funcNum, busNum);
                    195: 
                    196:        /*
                    197:         * At this point, we are certain that we are dealing with a
                    198:         * Intel PIIX class controller.
                    199:         */
                    200:        return ([self PIIXInitController:devDesc]);
                    201: }
                    202: 
                    203: /*
                    204:  * Method: initPIIXController
                    205:  *
                    206:  * Initializes the Intel PIIX IDE controller.
                    207:  */
                    208: - (BOOL) PIIXInitController:(IOPCIDeviceDescription *)devDesc
                    209: {
                    210:        piix_idetim_u   idetim;
                    211:        IOReturn                rtn;
                    212:        unsigned long   configReg;
                    213:        const id self_class = [self class];
                    214: 
                    215:        /*
                    216:         * Are we initializing the primary or the secondary channel?
                    217:         * Set the ivar _ideChannel.
                    218:         */
                    219:        switch ([devDesc portRangeList]->start) {
                    220:                case PIIX_P_CMD_ADDR:
                    221:                        _ideChannel = PCI_CHANNEL_PRIMARY;
                    222:                        break;
                    223:                case PIIX_S_CMD_ADDR:
                    224:                        _ideChannel = PCI_CHANNEL_SECONDARY;
                    225:                        break;
                    226:                default:
                    227:                        _ideChannel = PCI_CHANNEL_OTHER;
                    228:        }
                    229:        
                    230:        /*
                    231:         * PIIX configured on a weird location, cannot continue.
                    232:         *
                    233:         * NOTE:
                    234:         * The I/O ranges does NOT show up as a I/O range in the PCI
                    235:         * configuration space. However, the Bus-Mastering I/O range
                    236:         * does show up at configuration space location 0x20.
                    237:         */
                    238:        if ((_ideChannel == PCI_CHANNEL_OTHER) ||
                    239:                ([devDesc portRangeList]->size != PIIX_CMD_SIZE)) {
                    240:                IOLog("%s: Invalid IDE Command Block set to 0x%x size %d\n",
                    241:                        [self name],
                    242:                        [devDesc portRangeList]->start,
                    243:                        [devDesc portRangeList]->size);
                    244:                return NO;
                    245:        }
                    246:        
                    247:        /*
                    248:         * Verify our IRQ assignment.
                    249:         *
                    250:         * PIIX hardcodes the following settings:
                    251:         * IRQ 14 - primary channel
                    252:         * IRQ 15 - secondary channel
                    253:         */
                    254:        {
                    255:        unsigned int irq;
                    256:        
                    257:        irq = (_ideChannel == PCI_CHANNEL_PRIMARY) ? PIIX_P_IRQ : PIIX_S_IRQ;
                    258:        if ([devDesc interrupt] != irq) {
                    259:                IOLog("%s: Invalid IRQ: %d\n", [self name], [devDesc interrupt]);
                    260:                return NO;
                    261:        }
                    262:        }
                    263:        
                    264:        /*
                    265:         * Check the I/O Space Enable bit in the PCI command register.
                    266:         *
                    267:         * This is the master enable bit for the PIIX controller.
                    268:         */
                    269:     rtn = [self_class getPCIConfigData:&configReg atRegister:PIIX_PCICMD
                    270:                withDeviceDescription:devDesc];
                    271:     if (rtn != IO_R_SUCCESS)   {
                    272:        IOLog("%s: PCI config space access error %d\n", [self name], rtn);
                    273:                return NO;
                    274:     }  
                    275:        if (!(configReg & 0x0001)) {
                    276:                IOLog("%s: PCI IDE controller is not enabled\n", [self name]);
                    277:                return NO;
                    278:        }
                    279:        if (configReg & 0x0004)
                    280:                _busMaster = YES;
                    281:        else
                    282:                _busMaster = NO;
                    283:        
                    284:        /*
                    285:         * Fetch the corresponding primary/secondary IDETIM register and
                    286:         * verify that the individual channels are enabled.
                    287:         */
                    288:     rtn = [self_class getPCIConfigData:&configReg atRegister:PIIX_IDETIM
                    289:                withDeviceDescription:devDesc];
                    290:     if (rtn != IO_R_SUCCESS)   {
                    291:        IOLog("%s: PCI config space access error %d\n", [self name], rtn);
                    292:                return NO;
                    293:     }
                    294:        if (_ideChannel == PCI_CHANNEL_SECONDARY)
                    295:                configReg >>= 16;       // PIIX_IDETIM + 2 for secondary channel
                    296:        idetim.word = (u_short)configReg;
                    297:        
                    298:        if (!idetim.bits.ide) {
                    299:                IOLog("%s: %s PCI IDE channel is not enabled\n",
                    300:                        [self name],
                    301:                        (_ideChannel == PCI_CHANNEL_PRIMARY) ? "Primary" : "Secondary");
                    302:                return NO;
                    303:        }
                    304: 
                    305:        /*
                    306:         * Register and record the location of our Bus Master 
                    307:         * interface registers.
                    308:         */
                    309:        if (_busMaster && ([self PIIXRegisterBMRange:devDesc] == NO)) {
                    310:                IOLog("%s: Bus master I/O range registration failed\n",
                    311:                        [self name]);
                    312:                _busMaster = NO;
                    313:        }
                    314:        
                    315:        /*
                    316:         * Allocate a 4K-page (perhaps 8K) aligned page of memory for
                    317:         * the PRD table.
                    318:         */
                    319:        if (_busMaster && ([self PIIXInitPRDTable] == NO)) {
                    320:                IOLog("%s: cannot allocate memory for descriptor table\n",
                    321:                        [self name]);
                    322:                _busMaster = NO;
                    323:        }
                    324: 
                    325: #if 0
                    326:        IOLog("%s: PCI bus master DMA: %s\n",
                    327:                [self name], busMaster ? "Enabled" : "Disabled");
                    328: #endif
                    329: 
                    330:        /*
                    331:         * Revert to default timing.
                    332:         */
                    333:        [self PIIXResetTimings:devDesc];
                    334:        
                    335:     return YES;
                    336: }
                    337: 
                    338: /*
                    339:  * Method: getPCIControllerCapabilities
                    340:  *
                    341:  * Return the capability of the PCI IDE controller in 'm'.
                    342:  *
                    343:  */
                    344: - (void) getPCIControllerCapabilities:(txferModes_t *)m
                    345: {
                    346:        m->mode.swdma = m->mode.mwdma = m->mode.udma = ATA_MODE_NONE;
                    347:        switch (_controllerID) {
                    348:                case PCI_ID_PIIX:
                    349:                case PCI_ID_PIIX3:
                    350:                case PCI_ID_PIIX4:
                    351:                        m->mode.pio   = ata_mode_to_mask(ATA_MODE_4);
                    352:                        if (_busMaster) {
                    353:                                m->mode.mwdma = ata_mode_to_mask(ATA_MODE_2);
                    354:                                if (_controllerID == PCI_ID_PIIX4)
                    355:                                        m->mode.udma = ata_mode_to_mask(ATA_MODE_2);
                    356:                        }
                    357:                        break;
                    358:        }
                    359: }
                    360: 
                    361: /*
                    362:  * Get the PIO port transfer width. This refers to the width of the
                    363:  * I/O transfer on the PIO port, the IDE bus width is always 16-bits.
                    364:  *
                    365:  * All PIIX controllers are capable of 32-bit transfers on the data
                    366:  * port.
                    367:  */
                    368: - (ideTransferWidth_t) getPIOTransferWidth
                    369: {
                    370:        return (IDE_TRANSFER_32_BIT);
                    371: }
                    372: 
                    373: /*
                    374:  * Method: resetPCIController
                    375:  *
                    376:  * Not a true RESET, simply return the PCI controller to a quiescent state
                    377:  * and return all IDE ports to the default timing.
                    378:  */
                    379: - (void) resetPCIController
                    380: {
                    381:        switch (_controllerID) {
                    382:                case PCI_ID_PIIX:
                    383:                case PCI_ID_PIIX3:
                    384:                case PCI_ID_PIIX4:
                    385:                        [self PIIXInit];
                    386:                        [self PIIXResetTimings:[self deviceDescription]];
                    387:                        break;
                    388:        }
                    389: }
                    390: 
                    391: /*
                    392:  * Method: PIIXResetTimings
                    393:  *
                    394:  * Purpose:
                    395:  * Revert the timing register to the default value. The transfer timing
                    396:  * is set to the compatible mode. We need to be careful to initialize the
                    397:  * register only for our current IDE channel.
                    398:  */
                    399: - (void) PIIXResetTimings:(IOPCIDeviceDescription *)devDesc
                    400: {
                    401:        union {
                    402:                u_long dword;
                    403:                struct {
                    404:                        piix_idetim_u pri;
                    405:                        piix_idetim_u sec;
                    406:                } tim;
                    407:        } timings;
                    408: 
                    409:     IOReturn rtn;
                    410:        u_long udma;
                    411: 
                    412:        /*
                    413:         * Read the PIIX_IDETIM register.
                    414:         */     
                    415:        rtn = [[self class] getPCIConfigData:&timings.dword
                    416:                atRegister:PIIX_IDETIM
                    417:                withDeviceDescription:devDesc];
                    418:     if (rtn != IO_R_SUCCESS)
                    419:                return;
                    420: 
                    421:        /*
                    422:         * Read both PIIX_UDMACTL and PIIX_UDMATIM register.
                    423:         */
                    424:        rtn = [[self class] getPCIConfigData:&udma atRegister:PIIX_UDMACTL
                    425:                withDeviceDescription:devDesc];
                    426: 
                    427:        /*
                    428:         * Set compatible timing.
                    429:         * Disable UDDMA and set its timing registers to the slowest mode.
                    430:         */     
                    431:        switch (_ideChannel) {
                    432:                case PCI_CHANNEL_PRIMARY:
                    433:                        timings.tim.pri.word &= 0x8000;
                    434:                        udma &= 0xffccfffc;
                    435:                        break;
                    436:                case PCI_CHANNEL_SECONDARY:
                    437:                        timings.tim.sec.word &= 0x8000;
                    438:                        udma &= 0xccfffff3;
                    439:                        break;
                    440:                default:
                    441:                        return;
                    442:        }
                    443:        
                    444:        /*
                    445:         * Write the modified PCI config space registers back.
                    446:         */
                    447:        [[self class] setPCIConfigData:timings.dword atRegister:PIIX_IDETIM
                    448:                withDeviceDescription:devDesc];
                    449:        [[self class] setPCIConfigData:udma atRegister:PIIX_UDMACTL
                    450:                withDeviceDescription:devDesc];
                    451: }
                    452: 
                    453: /*
                    454:  * Method: PIIXRegisterBMRange:
                    455:  *
                    456:  * Purpose:
                    457:  * Add the 8-byte Bus-Master control registers to the portRangeList in
                    458:  * the deviceDescription. The base address for the registers resides in
                    459:  * PCI config space location 0x20. The first 8 bytes are for the primary
                    460:  * IDE channel, the next eight bytes are for the secondary IDE channel.
                    461:  *
                    462:  * Note:
                    463:  * This must be called before [super init...] because that's when the
                    464:  * resources are registered.
                    465:  */
                    466: - (BOOL) PIIXRegisterBMRange:(IOPCIDeviceDescription *)devDesc
                    467: {
                    468:     IOReturn           rtn;
                    469:        unsigned long   bmiba;
                    470:        IORange                 io_range[2];
                    471:        
                    472:     rtn = [[self class] getPCIConfigData:&bmiba atRegister:PIIX_BMIBA
                    473:                withDeviceDescription:devDesc];
                    474:     if (rtn != IO_R_SUCCESS) {
                    475:        IOLog("%s: PCI config space access error %d\n", [self name], rtn);
                    476:                return NO;
                    477:     }
                    478:        
                    479:        /*
                    480:         * Sanity check. Make sure this is an I/O range.
                    481:         */
                    482:        if ((bmiba & 0x01) == 0) {
                    483:                IOLog("%s: PCI memory range 0x%02x (0x%08lx) is not an I/O range\n",
                    484:                        [self name], PIIX_BMIBA, bmiba);
                    485:                return NO;
                    486:        }
                    487:        
                    488:        _bmRegs = bmiba & PIIX_BM_MASK;
                    489: 
                    490:        if (_bmRegs == 0)       // uninitialized range
                    491:                return NO;
                    492: 
                    493:        if (_ideChannel == PCI_CHANNEL_SECONDARY)
                    494:                _bmRegs += PIIX_BM_OFFSET;
                    495:        
                    496:        /*
                    497:         * Add this range to our device description's port range list.
                    498:         */
                    499:        io_range[0] = [devDesc portRangeList][0];
                    500:        io_range[1].start = _bmRegs;
                    501:        io_range[1].size  = PIIX_BM_SIZE;
                    502:        if ([devDesc setPortRangeList:io_range num:2] != IO_R_SUCCESS) {
                    503:                IOLog("%s: setPortRangeList failed\n", [self name]);
                    504:                return NO;
                    505:        }
                    506:        
                    507:        return YES;
                    508: }
                    509: 
                    510: /*
                    511:  * Method: PIIXInitPRDTable
                    512:  *
                    513:  * Purpose:
                    514:  * Initialize a "page-aligned" page of memory for the PRD descriptors
                    515:  * used by the bus master IDE controller.
                    516:  *
                    517:  * FIXME: Need to free the _prdTable memory.
                    518:  */
                    519: - (BOOL) PIIXInitPRDTable
                    520: {
                    521:        _prdTable.size = PAGE_SIZE;
                    522:        _prdTable.ptr = (void *)IOMallocPage(
                    523:                                                _prdTable.size,
                    524:                                                &_prdTable.ptrReal,
                    525:                                                &_prdTable.sizeReal
                    526:                                                );
                    527: 
                    528:        /*
                    529:         * _prdTable->ptr should now points to a physically contiguous block
                    530:         * of PAGE_SIZE bytes.
                    531:         */
                    532:     if (_prdTable.ptr == NULL)
                    533:                return NO;
                    534:        
                    535:        /*
                    536:         * cache the physical address of the descriptor table to _tablePhyAddr.
                    537:         */
                    538:        if (IOPhysicalFromVirtual(IOVmTaskSelf(), (vm_address_t)_prdTable.ptr,
                    539:                &_tablePhyAddr) != IO_R_SUCCESS) {
                    540:                IOFree(_prdTable.ptrReal, _prdTable.sizeReal);
                    541:                return NO;
                    542:        }
                    543: 
                    544:        bzero(_prdTable.ptr, _prdTable.size);
                    545:        return YES;
                    546: }
                    547: 
                    548: /*
                    549:  * Method: PIIXReportTimings:slaveTiming:isPrimary:
                    550:  *
                    551:  * Purpose:
                    552:  * Log the drive timings set in the two PIIX timing registers.
                    553:  * The units for the values are in PCI clocks.
                    554:  */
                    555: - (void) PIIXReportTimings:(piix_idetim_u)tim
                    556:               slaveTiming:(piix_sidetim_u)stim
                    557:                 isPrimary:(BOOL)primary
                    558: {
                    559:        if (!_ide_debug)
                    560:                return;
                    561: 
                    562:        IOLog("%s: Drive 0: ISP:%d Clks RCT:%d Clks\n",
                    563:                [self name],
                    564:                PIIX_ISP_TO_CLK(tim.bits.isp),
                    565:                PIIX_RCT_TO_CLK(tim.bits.rct));
                    566: #if 0
                    567:        IOLog("%s: Drive 0 Fast timing DMA only: %s\n", [self name],
                    568:                tim.bits.dte0 ? "on" : "off");
                    569:        IOLog("%s: Drive 0 Prefetch and Posting: %s\n", [self name],
                    570:                tim.bits.ppe0 ? "on" : "off");
                    571:        IOLog("%s: Drive 0 IORDY sample enable : %s\n", [self name],
                    572:                tim.bits.ie0 ? "on" : "off");
                    573:        IOLog("%s: Drive 0 Fast timing enable  : %s\n", [self name],
                    574:                tim.bits.time0 ? "on" : "off");
                    575: #endif 0
                    576:        IOLog("%s: Drive 1: ISP:%d Clks RCT:%d Clks\n", [self name],
                    577:                tim.bits.sitre ?
                    578:                        (primary ?
                    579:                                PIIX_ISP_TO_CLK(stim.bits.pisp1) : 
                    580:                                PIIX_ISP_TO_CLK(stim.bits.sisp1)) : 
                    581:                        PIIX_ISP_TO_CLK(tim.bits.isp),
                    582:                tim.bits.sitre ?
                    583:                        (primary ?
                    584:                                PIIX_RCT_TO_CLK(stim.bits.prct1) :
                    585:                                PIIX_RCT_TO_CLK(stim.bits.srct1)) :
                    586:                        PIIX_RCT_TO_CLK(tim.bits.rct));
                    587: #if 0
                    588:        IOLog("%s: Drive 1 Fast timing DMA only: %s\n", [self name],
                    589:                tim.bits.dte1 ? "on" : "off");
                    590:        IOLog("%s: Drive 1 Prefetch and Posting: %s\n", [self name],
                    591:                tim.bits.ppe1 ? "on" : "off");
                    592:        IOLog("%s: Drive 1 IORDY sample enable : %s\n", [self name],
                    593:                tim.bits.ie1 ? "on" : "off");
                    594:        IOLog("%s: Drive 1 Fast timing enable  : %s\n", [self name],
                    595:                tim.bits.time1 ? "on" : "off");
                    596: #endif 0
                    597: }
                    598: 
                    599: /*
                    600:  * Method: setPCIControllerCapabilities
                    601:  *
                    602:  * Purpose:
                    603:  * Based on the transfer modes and types for both IDE drives, setup the
                    604:  * controller to support those modes.
                    605:  *
                    606:  */
                    607: - (BOOL) setPCIControllerCapabilitiesForDrives:(driveInfo_t *)drives
                    608: {
                    609:        IOPCIConfigSpace configSpace;
                    610:        
                    611:        if (_controllerID == PCI_ID_NONE)
                    612:                return NO;
                    613:        
                    614:        [self getPCIConfigSpace:&configSpace];
                    615:        
                    616:        switch (_controllerID) {
                    617:                case PCI_ID_PIIX:
                    618:                case PCI_ID_PIIX3:
                    619:                case PCI_ID_PIIX4:
                    620:                        [self PIIXComputePCIConfigSpace:&configSpace forDrives:drives];
                    621:                        break;
                    622:                default:
                    623:                        return NO;
                    624:        }
                    625: 
                    626:        [self setPCIConfigSpace:&configSpace];
                    627:     return YES;
                    628: }
                    629: 
                    630: /*
                    631:  * Method: computePCIConfigSpaceForPIIX:modes:
                    632:  *
                    633:  * Purpose:
                    634:  * Set the IDETIM and the SIDETIM IDE timing registers based on the
                    635:  * PIO modes supported by the two drives on the IDE channel.
                    636:  */
                    637: - (void) PIIXComputePCIConfigSpace:(IOPCIConfigSpace *)configSpace
                    638:                forDrives:(driveInfo_t *)drv
                    639: {
                    640:        u_char *pci_space = (u_char *)configSpace;
                    641:     piix_idetim_u      *idetim;
                    642:        piix_sidetim_u  *sidetim;
                    643:        piix_udmactl_u  *udmactl;
                    644:        piix_udmatim_u  *udmatim;
                    645:        unsigned char   modeDrive0;
                    646:        unsigned char   modeDrive1;
                    647:        u_char                  isp, rct;
                    648: 
                    649:        if (MAX_IDE_DRIVES != 2)
                    650:                return;
                    651:        
                    652:        switch (_ideChannel) {
                    653:                case PCI_CHANNEL_PRIMARY:
                    654:                        idetim = (piix_idetim_u *)&pci_space[PIIX_IDETIM];
                    655:                        break;
                    656:                case PCI_CHANNEL_SECONDARY:
                    657:                        idetim = (piix_idetim_u *)&pci_space[PIIX_IDETIM_S];
                    658:                        break;
                    659:                default:
                    660:                        IOLog("%s: PIIX: Unknown IDE channel\n", [self name]);
                    661:                        return;
                    662:        }
                    663:        sidetim = (piix_sidetim_u *)&pci_space[PIIX_SIDETIM];
                    664:        udmactl = (piix_udmactl_u *)&pci_space[PIIX_UDMACTL];
                    665:        udmatim = (piix_udmatim_u *)&pci_space[PIIX_UDMATIM];
                    666: 
                    667:        modeDrive0 = ata_mode_to_num(drv[0].transferMode);
                    668:        modeDrive1 = ata_mode_to_num(drv[1].transferMode);
                    669:        
                    670:        /* Enable slave timing if timings are different and
                    671:         * a slave device is present.
                    672:         */
                    673:        idetim->bits.sitre = 0;
                    674:        isp = PIIXGetISPForMode(modeDrive0, drv[0].transferType);
                    675:        rct = PIIXGetRCTForMode(modeDrive0, drv[0].transferType);
                    676:        
                    677:        if ((PIIXGetCycleForMode(modeDrive0, drv[0].transferType) != 
                    678:                PIIXGetCycleForMode(modeDrive1, drv[1].transferType)) &&
                    679:                (drv[1].ideInfo.type != 0)) {
                    680:                if (_controllerID == PCI_ID_PIIX) {
                    681:                        /* Do not have the luxury of separate timing register for
                    682:                         * drive 0 and drive 1. Use the minimum of the two PIO modes.
                    683:                         * Or, the max of the two timings.
                    684:                         */
                    685:                        isp = MAX(PIIXGetISPForMode(modeDrive0, drv[0].transferType),
                    686:                                      PIIXGetISPForMode(modeDrive1, drv[1].transferType));
                    687:                        rct = MAX(PIIXGetRCTForMode(modeDrive0, drv[0].transferType),
                    688:                                      PIIXGetRCTForMode(modeDrive1, drv[1].transferType));                      
                    689:                }
                    690:                else
                    691:                        idetim->bits.sitre = 1;         // enable slave timing
                    692:        }
                    693:        
                    694:        /*
                    695:         * Reset all performance tuning bits and disable UDMA.
                    696:         */
                    697:        idetim->word &= 0xc000;
                    698:        switch (_ideChannel) {
                    699:                case PCI_CHANNEL_PRIMARY:
                    700:                        udmactl->bits.psde0 = 0;
                    701:                        udmactl->bits.psde1 = 0;
                    702:                        break;
                    703:                default:
                    704:                        udmactl->bits.ssde0 = 0;
                    705:                        udmactl->bits.ssde1 = 0;
                    706:        }
                    707: 
                    708:        /*
                    709:         * Set the timings for drive 0 (master).
                    710:         */
                    711:        if (drv[0].ideInfo.type == 0) {
                    712:                IOLog("%s: Drive 0 is not present\n", [self name]);
                    713:                return;
                    714:        }
                    715: 
                    716:        /*
                    717:         * Set timings for Drive 0 (Master drive).
                    718:         */
                    719:        if (drv[0].transferType == IDE_TRANSFER_ULTRA_DMA) {
                    720:                if (modeDrive0 > 2) modeDrive0 = 2;
                    721:                switch (_ideChannel) {
                    722:                        case PCI_CHANNEL_PRIMARY:
                    723:                                udmactl->bits.psde0 = 1;
                    724:                                udmatim->bits.pct0 = modeDrive0;
                    725:                                break;
                    726:                        case PCI_CHANNEL_SECONDARY:
                    727:                                udmactl->bits.ssde0 = 1;
                    728:                                udmatim->bits.sct0 = modeDrive0;
                    729:                                break;
                    730:                        default:
                    731:                                break;
                    732:                }
                    733:        }
                    734:        idetim->bits.isp = isp;
                    735:        idetim->bits.rct = rct;
                    736:        
                    737:        /* Set timings for drive 1 (Slave drive).
                    738:         */
                    739:        if (drv[1].transferType == IDE_TRANSFER_ULTRA_DMA) {
                    740:                if (modeDrive1 > 2) modeDrive1 = 2;
                    741:                switch (_ideChannel) {
                    742:                        case PCI_CHANNEL_PRIMARY:
                    743:                                udmactl->bits.psde1 = 1;
                    744:                                udmatim->bits.pct1 = modeDrive1;
                    745:                                break;
                    746:                        case PCI_CHANNEL_SECONDARY:
                    747:                                udmactl->bits.ssde1 = 1;
                    748:                                udmatim->bits.sct1 = modeDrive1;
                    749:                                break;
                    750:                        default:
                    751:                                break;
                    752:                }
                    753:        }
                    754:        if (idetim->bits.sitre) {
                    755:                isp = PIIXGetISPForMode(modeDrive1, drv[1].transferType);
                    756:                rct = PIIXGetRCTForMode(modeDrive1, drv[1].transferType);       
                    757:                if (_ideChannel == PCI_CHANNEL_PRIMARY) {
                    758:                        sidetim->bits.pisp1 = isp;
                    759:                        sidetim->bits.prct1 = rct;
                    760:                }
                    761:                else {
                    762:                        sidetim->bits.sisp1 = isp;
                    763:                        sidetim->bits.srct1 = rct;
                    764:                }
                    765:        }
                    766: 
                    767:        /*
                    768:         * Enable fast timings. Turn on IORDY sampling always?
                    769:         */
                    770:        idetim->bits.time0 = 1;
                    771:        idetim->bits.ppe0  = 1;
                    772:        idetim->bits.ie0   = 1;
                    773:        if (drv[1].ideInfo.type != 0) {
                    774:                idetim->bits.time1 = 1;
                    775:                idetim->bits.ppe1  = 1;
                    776:                idetim->bits.ie1   = 1;
                    777:        }
                    778: 
                    779:        /*
                    780:         * For DMA, disable fast timing for PIO.
                    781:         */
                    782:        if (drv[0].transferType != IDE_TRANSFER_PIO)
                    783:                idetim->bits.dte0 = 1;
                    784:        if (drv[1].transferType != IDE_TRANSFER_PIO)
                    785:                idetim->bits.dte1 = 1;
                    786: 
                    787:        [self PIIXReportTimings:*idetim slaveTiming:*sidetim 
                    788:                isPrimary:(_ideChannel == PCI_CHANNEL_PRIMARY)];
                    789: 
                    790:        return;
                    791: }
                    792: 
                    793: /*************************************************************************
                    794:  *
                    795:  * Intel PIIX/PIIX3/PIIX4 Bus-Mastering IDE DMA support
                    796:  *
                    797:  *************************************************************************/
                    798: 
                    799: /*
                    800:  * Function: PIIXVirtualToPhysical
                    801:  *
                    802:  * Similar to IOPhysicalFromVirtual but with no SPLVM/SPLX and locking.
                    803:  */
                    804: static __inline__ vm_offset_t
                    805: PIIXVirtualToPhysical(struct vm_map *map, vm_offset_t vaddr)
                    806: {
                    807:        return (vm_offset_t)pmap_resident_extract(
                    808:                        (pmap_t)vm_map_pmap_EXTERNAL(map),
                    809:                        vaddr);
                    810: }
                    811: 
                    812: /*
                    813:  * Function: PIIXStartDMA
                    814:  *
                    815:  * Purpose:
                    816:  * Start the bus master by writing a 1 to the SSBM bit in BMICX register.
                    817:  *
                    818:  * Argument:
                    819:  * piix_base - base address of the I/O space mapped bus master registers
                    820:  */
                    821: static __inline__ void
                    822: PIIXStartDMA(u_short piix_base)
                    823: {
                    824:        piix_bmicx_u piix_cmd;
                    825:        
                    826:        /*
                    827:         * Engage the bus master by writing 1 to the start bit in the
                    828:         * Command Register.
                    829:         */
                    830:        piix_cmd.byte = inb(piix_base + PIIX_BMICX);
                    831:        piix_cmd.bits.ssbm = 1;
                    832:        outb(piix_base + PIIX_BMICX, piix_cmd.byte);
                    833: }
                    834: 
                    835: /*
                    836:  * Function: PIIXStopDMA
                    837:  *
                    838:  * Purpose:
                    839:  * Stop the bus master by clearing the SSBM bit in BMICX register.
                    840:  *
                    841:  * Argument:
                    842:  * piix_base - base address of the I/O space mapped bus master registers
                    843:  */
                    844: static __inline__ void
                    845: PIIXStopDMA(u_short piix_base)
                    846: {
                    847:        piix_bmicx_u piix_cmd;
                    848:        
                    849:        /*
                    850:         * Stop the bus master by writing 0 to the start bit in the
                    851:         * Command Register.
                    852:         */
                    853:        piix_cmd.byte = inb(piix_base + PIIX_BMICX);
                    854:        piix_cmd.bits.ssbm = 0;
                    855:        outb(piix_base + PIIX_BMICX, piix_cmd.byte);    
                    856: }
                    857: 
                    858: /*
                    859:  * Function: PIIXGetStatus
                    860:  *
                    861:  * Purpose:
                    862:  * Return the PIIX BMISX (bus master IDE status register).
                    863:  *
                    864:  * Argument:
                    865:  * piix_base - base address of the I/O space mapped bus master registers
                    866:  */
                    867: static __inline__ u_char
                    868: PIIXGetStatus(u_short piix_base)
                    869: {
                    870:        return (inb(piix_base + PIIX_BMISX));
                    871: }
                    872:                        
                    873: /*
                    874:  * Function: PIIXSetupPRDTable
                    875:  *
                    876:  * Purpose:
                    877:  * Setup the PRD (descriptor) table for the current IDE transfer.
                    878:  * This table must be aligned on a DWord (4 byte) boundary.
                    879:  *
                    880:  * Arguments:
                    881:  * table    - points to the start of the PRD table
                    882:  * size     - max number of PRD entries that the table can hold
                    883:  * vaddr       - virtual address of the start of memory buffer
                    884:  * size                - size of memory buffer in bytes
                    885:  * map         - vm_map for the memory buffer
                    886:  *
                    887:  * Return:
                    888:  *     YES: table is setup and ready for use
                    889:  *     NO : table full or alignment error
                    890:  *
                    891:  */
                    892: static __inline__ BOOL
                    893: PIIXSetupPRDTable(piix_prd_t *table, u_int table_size, vm_offset_t vaddr,
                    894:        u_int size, struct vm_map *map)
                    895: {
                    896:        vm_offset_t vaddr_next;
                    897:        vm_offset_t paddr;
                    898:        vm_offset_t paddr_next;
                    899:        vm_offset_t paddr_start;
                    900:        const char *name = "PIIXSetupPRDTable";
                    901:        u_int len_prd;
                    902:        u_int index;
                    903: 
                    904: #ifdef DEBUG   
                    905:        piix_prd_t *table_saved = table;
                    906: #endif DEBUG
                    907: 
                    908:        ddm_ide_dma("  PIIXSetupPRDTable: vaddr:%08x size:%d\n",
                    909:                (u_int)vaddr, (u_int)size, 3, 4, 5);
                    910: 
                    911:        if (vaddr & (PIIX_BUF_ALIGN - 1)) {
                    912:                IOLog("%s: buffer is not %d byte aligned\n", name, PIIX_BUF_ALIGN);
                    913:                return NO;
                    914:        }
                    915:        
                    916:        if (size == 0) {
                    917:                IOLog("%s: zero length DMA buffer\n", name);
                    918:                return NO;
                    919:        }
                    920:        
                    921:        index = len_prd = 0;
                    922:        paddr = PIIXVirtualToPhysical(map, vaddr);
                    923:        paddr_start = paddr;
                    924:        do {
                    925:                u_int len;
                    926: 
                    927:                vaddr_next = trunc_page(vaddr) + PAGE_SIZE;             // next virtual page
                    928:                paddr_next = trunc_page(paddr) + PAGE_SIZE;             // next phys page
                    929:                vaddr      = vaddr_next;
                    930:                
                    931:                len = paddr_next - paddr;               // length to transfer in this page
                    932:                if (len > size) len = size;             // take the minimum
                    933:                size  -= len;                                   // decrement total remaining bytes
                    934:                len_prd += len;                                 // increment current PRD counter
                    935: 
                    936:                /*
                    937:                 * If there are more bytes remaining, try to append the next
                    938:                 * page into the same PRD. We must check that the next page
                    939:                 * is physically contiguous with the current one.
                    940:                 *
                    941:                 * Each PRD cannot cross 64K boundary, and is limited to 64K per PRD.
                    942:                 */
                    943:                if (size && 
                    944:                (paddr_next == (paddr = PIIXVirtualToPhysical(map, vaddr))) &&
                    945:                ((paddr_start & ~(PIIX_BUF_BOUND-1))==(paddr & ~(PIIX_BUF_BOUND-1))) &&
                    946:                (len_prd <= (PIIX_BUF_LIMIT - PAGE_SIZE))) {
                    947:                continue;
                    948:                }
                    949: 
                    950:                /*
                    951:                 * Setup PRD entry
                    952:                 *
                    953:                 * For the length field in PRD, 0 is used to denote the max
                    954:                 * transfer size of 64K.
                    955:                 */
                    956:                table->base = paddr_start;
                    957:                table->count = (len_prd == PIIX_BUF_LIMIT) ? 0 : len_prd;
                    958:                table->eot = 0;
                    959:                table++;
                    960: 
                    961:                len_prd = 0;
                    962:                paddr_start = paddr;
                    963: 
                    964:        } while (size && (++index < table_size));
                    965:        
                    966:        if (size) {
                    967:                IOLog("%s: PRD table exhausted\n", name);
                    968:                return NO;
                    969:        } 
                    970:        
                    971:        /*
                    972:         * Set the 'end-of-table' bit on the last PRD entry.
                    973:         */
                    974:        --table;
                    975:        table->eot = 1;
                    976: 
                    977: #ifdef DEBUG
                    978:        {
                    979:        int i = 0;
                    980:        u_int *ip = (u_int *)&table_saved[0];
                    981:        do {
                    982:                ddm_ide_dma("    table[%d]  %08x:%08x\n", i, *ip, *(ip+1), 4, 5);
                    983:                ip += 2;
                    984:        } while (i++ < index);
                    985:        }
                    986: #endif DEBUG
                    987: 
                    988:        return YES;
                    989: }
                    990: 
                    991: /*
                    992:  * Function: PIIXPrepareDMA
                    993:  *
                    994:  * Purpose:
                    995:  * Prepare the PIIX bus master for a DMA transfer.
                    996:  *
                    997:  * Arguments:
                    998:  *  piix_base - base address of the I/O space mapped bus master registers
                    999:  *  table     - points to the start of the PRD table
                   1000:  *  tableAddr - physical address of the table
                   1001:  *  isRead    - YES for read transfers (from device to host)
                   1002:  */
                   1003: static __inline__ BOOL
                   1004: PIIXPrepareDMA(u_short piix_base, u_int tableAddr, BOOL isRead)
                   1005: {
                   1006:        piix_bmicx_u piix_cmd;
                   1007:        piix_bmisx_u piix_status;
                   1008: 
                   1009:        /*
                   1010:         * Provide the starting address of the PRD table by loading the
                   1011:         * PRD Table Pointer Register.
                   1012:         *
                   1013:         * For some reason, outl(piix_base + PIIX_BMIDTPX, tableAddr)
                   1014:         * will only write the lower 16-bit WORD. That's why we use
                   1015:         * two outw instructions.
                   1016:         */     
                   1017:        outw(piix_base + PIIX_BMIDTPX, tableAddr & 0xffff);
                   1018:        outw(piix_base + PIIX_BMIDTPX + 2, (tableAddr >> 16) & 0xffff);
                   1019: 
                   1020:        /*
                   1021:         * Set the R/W bit depending on the direction of the transfer.
                   1022:         * The controller is also STOP'ed.
                   1023:         *
                   1024:         * Arghh!!! Why does the Intel PIIX3 and PIIX4 doc have this backwards?
                   1025:         */
                   1026:        piix_cmd.byte = 0;
                   1027:        piix_cmd.bits.rwcon = isRead ? 1 : 0;
                   1028:        outb(piix_base + PIIX_BMICX, piix_cmd.byte);
                   1029:        
                   1030:        /*
                   1031:         * Clear interrupt and error bits in the Status Register.
                   1032:         */
                   1033:        piix_status.byte = inb(piix_base + PIIX_BMISX);
                   1034:        piix_status.bits.err = piix_status.bits.ideints = 1;
                   1035: //     piix_status.bits.dma0cap = piix_status.bits.dma1cap = 1;
                   1036:        outb(piix_base + PIIX_BMISX, piix_status.byte);
                   1037:        
                   1038:        return YES;
                   1039: }
                   1040: 
                   1041: /*
                   1042:  * Method: PIIXInit
                   1043:  *
                   1044:  * Purpose:
                   1045:  * Initializes the PIIX controller.
                   1046:  */
                   1047: - (void) PIIXInit
                   1048: {
                   1049:        return (PIIXStopDMA(_bmRegs));
                   1050: }
                   1051: 
                   1052: /*
                   1053:  * Even if an interrupt is missed, consider the transfer operation
                   1054:  * successful if the PIIX status flags says so.
                   1055:  */
                   1056: #define TRUST_PIIX     1
                   1057: 
                   1058: /*
                   1059:  * Method: PIIXPerformDMA
                   1060:  *
                   1061:  * Purpose:
                   1062:  * Program the PIIX controller to perform DMA READ/WRITE transfers
                   1063:  * based on the transfer request ideIoReq. The entire transfer is
                   1064:  * translated into one or more PRD entries in the PRD table. We will
                   1065:  * get a single interrupt when the entire transfer is complete.
                   1066:  *
                   1067:  * Note:
                   1068:  * The PIIX status register should have bit 2 and bit 0 set at the
                   1069:  * conclusion of the transfer. This corresponds to the case when the
                   1070:  * IDE device generated an interrupt and the size of the PRD is equal
                   1071:  * to the IDE device transfer size.
                   1072:  *
                   1073:  * If bit 1 is set, meaning that the controller encountered a target
                   1074:  * or master abort, it is very likely that we told it to DMA to/from
                   1075:  * an invalid piece of memory. Perhaps due to an incorrect virtual
                   1076:  * to physical map conversion.
                   1077:  */
                   1078: - (ide_return_t) performDMA:(ideIoReq_t *)ideIoReq
                   1079: {
                   1080:        ideRegsVal_t    *ideRegs = &(ideIoReq->regValues);
                   1081:        ideRegsAddrs_t  *rp = &_ideRegsAddrs;
                   1082:     unsigned char      status;
                   1083:        piix_bmisx_u    piix_status;
                   1084:        ide_return_t    rtn = IDER_SUCCESS;
                   1085:        unsigned                cmd = ideIoReq->cmd;
                   1086: 
                   1087:        ddm_ide_dma("DMA block:%d count:%d read:%d map:%d rp:%x\n",
                   1088:                ideIoReq->block,
                   1089:                ideIoReq->blkcnt,
                   1090:                (ideIoReq->cmd == IDE_READ_DMA),
                   1091:                ideIoReq->map,
                   1092:                rp->data);
                   1093: 
                   1094:        if ((cmd != IDE_READ_DMA) && (cmd != IDE_WRITE_DMA)) {
                   1095:                IOLog("%s: ideDmaRwCommon: unknown command %d\n", [self name], cmd);
                   1096:                return IDER_REJECT;
                   1097:        }
                   1098: 
                   1099:        /*
                   1100:         * wait for BSY = 0 and DRDY = 1
                   1101:         */
                   1102:     rtn = [self waitForDeviceReady];
                   1103:     if (rtn != IDER_SUCCESS) {
                   1104:                IOLog("%s: drive not ready\n", [self name]);
                   1105:                return (rtn);
                   1106:     }
                   1107: 
                   1108:        /*
                   1109:         * Set up PRD descriptor table
                   1110:         */
                   1111:        if (PIIXSetupPRDTable(_prdTable.ptr,
                   1112:                PIIX_DT_BOUND/sizeof(piix_prd_t),
                   1113:                (vm_offset_t)ideIoReq->addr,
                   1114:                ideIoReq->blkcnt * IDE_SECTOR_SIZE,
                   1115:                (struct vm_map *)ideIoReq->map) == NO) {
                   1116:                return NO;
                   1117:        }
                   1118: 
                   1119:        /*
                   1120:         * Prepare the PIIX controller for the current transfer.
                   1121:         */
                   1122:        if (PIIXPrepareDMA(_bmRegs, _tablePhyAddr,
                   1123:                (ideIoReq->cmd == IDE_READ_DMA)) == NO) {
                   1124:                IOLog("%s: PIIXPrepareDMA error\n", [self name]);
                   1125:                return IDER_CMD_ERROR;
                   1126:        }
                   1127:        
                   1128:        /*
                   1129:         * Program the drive (task file).
                   1130:         * Recall that _driveNum must be set prior to calling logToPhys.
                   1131:         * This is already done in the method ideExecuteCmd which calls
                   1132:         * this method. testDMA also calls this method with _driveNum set.
                   1133:         */
                   1134:        *ideRegs = [self logToPhys:ideIoReq->block numOfBlocks:ideIoReq->blkcnt];
                   1135:     outb(rp->drHead,  ideRegs->drHead);
                   1136:     outb(rp->sectNum, ideRegs->sectNum);
                   1137:     outb(rp->sectCnt, ideRegs->sectCnt);
                   1138:     outb(rp->cylLow,  ideRegs->cylLow);
                   1139:     outb(rp->cylHigh, ideRegs->cylHigh);
                   1140: 
                   1141:        ddm_ide_dma(
                   1142:                "DMA drHead:%02x sectNum:%02x sectCnt:%02x cylLow:%02x cylHigh:%02x\n",
                   1143:                ideRegs->drHead,
                   1144:                ideRegs->sectNum,
                   1145:                ideRegs->sectCnt,
                   1146:                ideRegs->cylLow,
                   1147:                ideRegs->cylHigh);
                   1148: 
                   1149:        /*
                   1150:         * Issue DMA READ/WRITE command to drive.
                   1151:         */
                   1152: //     [self enableInterrupts];
                   1153: //     [self clearInterrupts];
                   1154:     outb(rp->command, cmd);
                   1155: 
                   1156:        /*
                   1157:         * Start the PIIX bus master.
                   1158:         */
                   1159:        PIIXStartDMA(_bmRegs);
                   1160:        
                   1161:        /* Wait for interrupt to signal the completion of the transfer.
                   1162:         */
                   1163:     rtn = [self ideWaitForInterrupt:cmd ideStatus:&status];    
                   1164:        piix_status.byte = PIIXGetStatus(_bmRegs);
                   1165:        PIIXStopDMA(_bmRegs);
                   1166:        
                   1167: #ifdef TRUST_PIIX
                   1168:        if ((piix_status.byte & PIIX_STATUS_MASK) == PIIX_STATUS_OK) {
                   1169: 
                   1170:                        if (rtn != IDER_SUCCESS) {
                   1171:                                /* Interrupt timed-out, but PIIX claims that transaction
                   1172:                                 * was completed without errors.
                   1173:                                 * This may require more testing. Always trust PIIX?
                   1174:                                 * First, read status from the drive.
                   1175:                                 */
                   1176:                                if ((rtn = [self waitForNotBusy]) != IDER_SUCCESS)
                   1177:                                        return IDER_CMD_ERROR;
                   1178:                                status = inb(rp->status);
                   1179:                        }                        
                   1180: #else
                   1181:        if ((rtn == IDER_SUCCESS) && ((piix_status.byte & PIIX_STATUS_MASK) == 
                   1182:                PIIX_STATUS_OK)) {
                   1183: #endif TRUST_PIIX
                   1184: 
                   1185:                    if (status & (ERROR | WRITE_FAULT)) {
                   1186:                                [self getIdeRegisters:ideRegs Print:"DMA error"];
                   1187:                                return IDER_CMD_ERROR;
                   1188:                }
                   1189: 
                   1190:                if (status & ERROR_CORRECTED) {
                   1191:                                IOLog("%s: Error during data transfer (corrected).\n", 
                   1192:                                [self name]);
                   1193:                    }
                   1194:        }
                   1195:        else {
                   1196:                [self getIdeRegisters:ideRegs Print:NULL];
                   1197:                IOLog("%s: PIIX status:0x%02x error code:%d\n",
                   1198:                        [self name], piix_status.byte, rtn);
                   1199:                rtn = IDER_CMD_ERROR;
                   1200:        }
                   1201: 
                   1202:        ddm_ide_dma(
                   1203:                "END drHead:%02x sectNum:%02x sectCnt:%02x cylLow:%02x cylHigh:%02x\n",
                   1204:        inb(rp->drHead),
                   1205:        inb(rp->sectNum),
                   1206:        inb(rp->sectCnt),
                   1207:        inb(rp->cylLow),
                   1208:        inb(rp->cylHigh));
                   1209: 
                   1210:        return (rtn);
                   1211: }
                   1212: 
                   1213: #define MAX_BUSY_WAIT                          (1000*100)
                   1214: 
                   1215: /*
                   1216:  * Perform DMA transfers for ATAPI devices.
                   1217:  */
                   1218: - (sc_status_t) performATAPIDMA:(atapiIoReq_t *)atapiIoReq
                   1219:        buffer:(void *)buffer 
                   1220:        client:(struct vm_map *)client
                   1221: {
                   1222:        piix_bmisx_u piix_status;
                   1223:        unsigned char cmd = atapiIoReq->atapiCmd[0];
                   1224:        ide_return_t    rtn;
                   1225:     unsigned char      status;
                   1226:        ideRegsAddrs_t  *rp = &_ideRegsAddrs;
                   1227:        int     i;
                   1228: 
                   1229:        //IOLog("DMA transfer\n");
                   1230: 
                   1231:        atapiIoReq->bytesTransferred = 0;
                   1232:        
                   1233:        /*
                   1234:         * Set up PRD descriptor table
                   1235:         */
                   1236:        if (PIIXSetupPRDTable(_prdTable.ptr,
                   1237:                PIIX_DT_BOUND/sizeof(piix_prd_t),
                   1238:                (vm_offset_t)buffer,
                   1239:                atapiIoReq->maxTransfer,
                   1240:                client) == NO)
                   1241:                {
                   1242:                atapiIoReq->scsiStatus = STAT_CHECK;
                   1243:                return SR_IOST_CMDREJ;
                   1244:        }
                   1245: 
                   1246:        if (PIIXPrepareDMA(_bmRegs, _tablePhyAddr, atapiIoReq->read) == NO) {
                   1247:                IOLog("%s: PIIXPrepareDMA error\n", [self name]);
                   1248:                atapiIoReq->scsiStatus = STAT_CHECK;
                   1249:                return SR_IOST_CMDREJ;
                   1250:        }
                   1251: 
                   1252:        /*
                   1253:         * Start the PIIX bus master.
                   1254:         */
                   1255:        PIIXStartDMA(_bmRegs);
                   1256: 
                   1257:        if (atapiIoReq->timeout > IDE_INTR_TIMEOUT) {
                   1258:                u_int current_timeout = [self interruptTimeOut];
                   1259:                
                   1260:                //IOLog("using SCSI timeout:%d\n", atapiIoReq->timeout);
                   1261:                [self setInterruptTimeOut:atapiIoReq->timeout];
                   1262:                rtn = [self ideWaitForInterrupt:cmd ideStatus:&status];
                   1263:                [self setInterruptTimeOut:current_timeout];
                   1264:        }
                   1265:        else {
                   1266:                rtn = [self ideWaitForInterrupt:cmd ideStatus:&status];
                   1267:        }
                   1268: 
                   1269:        piix_status.byte = PIIXGetStatus(_bmRegs);
                   1270:        PIIXStopDMA(_bmRegs);
                   1271: 
                   1272:        /*
                   1273:         * This is stupid but the Chinon drive fires off an interrupt first
                   1274:         * and then updates the status register. It appears that any drive
                   1275:         * based on Western Digital chipset will do this. At any rate, this
                   1276:         * code is harmless and should be left here. 
                   1277:         */
                   1278:        for (i = 0; i < MAX_BUSY_WAIT; i++)     {
                   1279:                if (status & BUSY)
                   1280:                        IODelay(10);
                   1281:                else
                   1282:                        break;
                   1283:                status = inb(_ideRegsAddrs.status);     
                   1284:        }
                   1285: 
                   1286: #ifdef TRUST_PIIX
                   1287:        if ((piix_status.byte & PIIX_STATUS_MASK) == PIIX_STATUS_OK) {
                   1288:                if (rtn != IDER_SUCCESS) {
                   1289:                        /* Interrupt timed-out, but PIIX claims that transaction
                   1290:                         * was completed without errors.
                   1291:                         * This may require more testing. Always trust PIIX?
                   1292:                         * First, read status from the drive.
                   1293:                         */
                   1294:                        if ((rtn = [self waitForNotBusy]) != IDER_SUCCESS) {
                   1295:                                IOLog("%s: FATAL: ATAPI Drive: %d Command %x failed.\n", 
                   1296:                                        [self name], _driveNum, atapiIoReq->atapiCmd[0]);
                   1297:                                [self getIdeRegisters:NULL Print:"ATAPI DMA"];
                   1298:                                IOLog("%s: transfer size: %d\n",
                   1299:                                        [self name], atapiIoReq->maxTransfer);
                   1300:                                [self atapiSoftReset:_driveNum];
                   1301:                                atapiIoReq->scsiStatus = STAT_CHECK;
                   1302:                                return SR_IOST_CHKSNV;
                   1303:                        }
                   1304:                        status = inb(rp->status);
                   1305:                }
                   1306: #else
                   1307:        if ((rtn == IDER_SUCCESS) && ((piix_status.byte & PIIX_STATUS_MASK) == 
                   1308:                PIIX_STATUS_OK)) {
                   1309: #endif TRUST_PIIX
                   1310: 
                   1311:                if (status & ERROR) {
                   1312:                        atapiIoReq->scsiStatus = STAT_CHECK;
                   1313:                        return SR_IOST_CHKSNV;  
                   1314:                }
                   1315:        }
                   1316:        else {
                   1317:                [self getIdeRegisters:NULL Print:"ATAPI DMA"];
                   1318:                IOLog("%s: PIIX status:0x%02x error code:%d\n",
                   1319:                        [self name], piix_status.byte, rtn);
                   1320:                IOLog("%s: transfer size: %d\n", [self name], atapiIoReq->maxTransfer);
                   1321:                [self atapiSoftReset:_driveNum];
                   1322:                atapiIoReq->scsiStatus = STAT_CHECK;
                   1323:                return SR_IOST_CHKSNV;
                   1324:        }
                   1325: 
                   1326:        atapiIoReq->bytesTransferred = atapiIoReq->maxTransfer;
                   1327:        atapiIoReq->scsiStatus = STAT_GOOD;
                   1328:        return SR_IOST_GOOD;
                   1329: }
                   1330: 
                   1331: @end

unix.superglobalmegacorp.com

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