Annotation of XNU/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxInit.cpp, 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:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: 
                     23: /* Sym8xxInit.m created by russb2 on Sat 30-May-1998 */
                     24: 
                     25: /*-----------------------------------------------------------------------------*
                     26:  * This module contains initialization routines for the driver.
                     27:  *
                     28:  * Driver initialization consists of:
                     29:  * 
                     30:  * - Doing PCI bus initialization for the script engine PCI device.
                     31:  * - Setting up shared communication areas in system memory between the script
                     32:  *   and the driver.
                     33:  * - Copying the script program into the script engine on-board ram, applying 
                     34:  *   script relocation fixups as required.
                     35:  * - Setting the initial register values for the script engine.
                     36:  * - Setting up driver related storage and interfacing with driverKit.
                     37:  *
                     38:  *-----------------------------------------------------------------------------*/
                     39: 
                     40: /*
                     41:  * This define causes Sym8xxScript.h to include the script instructions and
                     42:  * relocation tables. Normally without this define we only will get #define
                     43:  * values for interfacing with the script.
                     44:  */
                     45: #define INCL_SCRIPT_TEXT
                     46: 
                     47: #import "Sym8xxController.h"
                     48: 
                     49: #define super  IOSCSIParallelController
                     50: 
                     51: OSDefineMetaClassAndStructors( Sym8xxSCSIController, IOSCSIParallelController )        ;
                     52: 
                     53: /*-----------------------------------------------------------------------------*
                     54:  * This structure contains most of the inital register settings for
                     55:  * the script engine. See Sym8xxRegs.h for the actual initialization
                     56:  * values.
                     57:  *
                     58:  *-----------------------------------------------------------------------------*/
                     59: typedef struct ChipInitRegs
                     60: {
                     61:     UInt32             regNum;
                     62:     UInt32             regSize;
                     63:     UInt32             regValue;
                     64: 
                     65: } ChipInitRegs;
                     66: 
                     67: static ChipInitRegs    Sym8xxInitRegs[] =
                     68: {
                     69:        { SCNTL0,       SCNTL0_SIZE,    SCNTL0_INIT     },
                     70:        { SCNTL1,       SCNTL1_SIZE,    SCNTL1_INIT     },
                     71:         { SCNTL2,      SCNTL2_SIZE,    SCNTL2_INIT     },
                     72:         { SCNTL3,      SCNTL3_SIZE,    SCNTL3_INIT_875 },
                     73:         { SXFER,       SXFER_SIZE,     SXFER_INIT      },
                     74:         { SDID,                SDID_SIZE,      SDID_INIT       },
                     75:         { GPREG,       GPREG_SIZE,     GPREG_INIT      },
                     76:         { SFBR,                SFBR_SIZE,      SFBR_INIT       },
                     77:         { SOCL,        SOCL_SIZE,      SOCL_INIT       },
                     78:         { DSA,         DSA_SIZE,       DSA_INIT        },
                     79:         { ISTAT,       ISTAT_SIZE,     ISTAT_INIT      },
                     80:         { TEMP,                TEMP_SIZE,      TEMP_INIT       },
                     81:         { CTEST0,      CTEST0_SIZE,    CTEST0_INIT     },
                     82:         { CTEST3,      CTEST3_SIZE,    CTEST3_INIT_A   },
                     83:         { CTEST4,      CTEST4_SIZE,    CTEST4_INIT     },
                     84:         { CTEST5,      CTEST5_SIZE,    CTEST5_INIT_A_revB},
                     85:         { DBC,         DBC_SIZE,       DBC_INIT        },
                     86:         { DCMD,                DCMD_SIZE,      DCMD_INIT       },
                     87:         { DNAD,                DNAD_SIZE,      DNAD_INIT       },
                     88:        { DSPS,         DSPS_SIZE,      DSPS_INIT       },
                     89:        { SCRATCHA,     SCRATCHA_SIZE,  SCRATCHA_INIT   },
                     90:         { DMODE,       DMODE_SIZE,     DMODE_INIT_A    },
                     91:         { DIEN,                DIEN_SIZE,      DIEN_INIT       },
                     92:         { DWT,         DWT_SIZE,       DWT_INIT        },
                     93:         { DCNTL,       DCNTL_SIZE,     DCNTL_INIT_A    },
                     94:         { SIEN,                SIEN_SIZE,      SIEN_INIT       },
                     95:         { SLPAR,       SLPAR_SIZE,     SLPAR_INIT      },
                     96:         { MACNTL,      MACNTL_SIZE,    MACNTL_INIT     },
                     97:         { GPCNTL,      GPCNTL_SIZE,    GPCNTL_INIT     },
                     98:         { STIME0,      STIME0_SIZE,    STIME0_INIT     },
                     99:         { STIME1,      STIME1_SIZE,    STIME1_INIT     },
                    100:         { RESPID0,     RESPID0_SIZE,   RESPID0_INIT    },
                    101:         { RESPID1,     RESPID1_SIZE,   RESPID1_INIT    },
                    102:         { STEST2,      STEST2_SIZE,    STEST2_INIT     },
                    103:         { STEST3,      STEST3_SIZE,    STEST3_INIT     },
                    104:         { SODL,                SODL_SIZE,      SODL_INIT       },
                    105:         { SCRATCHB,    SCRATCHB_SIZE,  SCRATCHB_INIT   }
                    106: };
                    107: 
                    108: /*-----------------------------------------------------------------------------*
                    109:  *  
                    110:  *
                    111:  *-----------------------------------------------------------------------------*/
                    112: bool Sym8xxSCSIController::configure( IOService *forProvider, SCSIControllerInfo *controllerInfo )
                    113: {
                    114:     provider = (IOPCIDevice *)forProvider;
                    115: 
                    116:     if ( Sym8xxInit() == false )
                    117:     {
                    118:         return false;
                    119:     }
                    120: 
                    121:     initialReset = true;
                    122: 
                    123:     Sym8xxSCSIBusReset( 0 );
                    124:     IOSleep(3000);
                    125: 
                    126:     controllerInfo->initiatorId                        = 7;
                    127: 
                    128:     controllerInfo->maxTargetsSupported                = 16;
                    129:     controllerInfo->maxLunsSupported           = 8;
                    130: 
                    131:     controllerInfo->minTransferPeriodpS                = (chipId == kChipIdSym875) ? 50000 : 0;
                    132:     controllerInfo->maxTransferOffset          = (chipId == kChipIdSym875) ? 16    : 0;
                    133:     controllerInfo->maxTransferWidth           = 2;
                    134: 
                    135:     controllerInfo->maxCommandsPerController   = 0;
                    136:     controllerInfo->maxCommandsPerTarget       = 0;
                    137:     controllerInfo->maxCommandsPerLun          = 0;
                    138: 
                    139:     controllerInfo->tagAllocationMethod                = kTagAllocationPerController;
                    140:     controllerInfo->maxTags                    = 128;
                    141: 
                    142:     controllerInfo->commandPrivateDataSize     = sizeof( SRB );
                    143:     controllerInfo->targetPrivateDataSize      = 0;
                    144:     controllerInfo->lunPrivateDataSize         = 0;
                    145: 
                    146:     controllerInfo->disableCancelCommands      = false;
                    147: 
                    148:     return true;
                    149: }
                    150: 
                    151: 
                    152: /*-----------------------------------------------------------------------------*
                    153:  * Script Initialization
                    154:  *
                    155:  *-----------------------------------------------------------------------------*/
                    156: bool Sym8xxSCSIController::Sym8xxInit()
                    157: {
                    158:     /*
                    159:      * Perform PCI related initialization
                    160:      */
                    161:     if ( Sym8xxInitPCI() == false )
                    162:     { 
                    163:         return false;
                    164:     }
                    165: 
                    166:     /*
                    167:      * Allocate/initialize driver resources
                    168:      */
                    169:     if ( Sym8xxInitVars() == false )
                    170:     {
                    171:         return false;
                    172:     }
                    173: 
                    174:     /*
                    175:      * Initialize the script engine registers
                    176:      */
                    177:     if ( Sym8xxInitChip() == false )
                    178:     {
                    179:         return false;
                    180:     }
                    181: 
                    182:     /* 
                    183:      * Apply fixups to script and copy script to script engine's on-board ram
                    184:      */
                    185:     if ( Sym8xxInitScript() == false )
                    186:     {
                    187:         return false;
                    188:     }
                    189: 
                    190:     getWorkLoop()->enableAllInterrupts();
                    191: 
                    192:     /*
                    193:      * Start script execution
                    194:      */
                    195:     Sym8xxWriteRegs( chipBaseAddr, DSP, DSP_SIZE, (UInt32) &chipRamAddrPhys[Ent_select_phase] );
                    196: 
                    197:     return true;
                    198: }
                    199: 
                    200: /*-----------------------------------------------------------------------------*
                    201:  * Script engine PCI initialization
                    202:  *
                    203:  * This routine determines the chip version/revision, enables the chip address
                    204:  * ranges and allocates a virtual mapping to the script engine's registers and
                    205:  * on-board ram.
                    206:  *-----------------------------------------------------------------------------*/
                    207: bool Sym8xxSCSIController::Sym8xxInitPCI()
                    208: {
                    209:     unsigned long      pciReg0, pciReg8;
                    210:     UInt32             chipRev;
                    211:     UInt32             n;
                    212:     UInt32             ramReg;
                    213:     OSString           *matchEntry;
                    214: 
                    215: 
                    216:     /*
                    217:      * Determine the number of memory ranges for the PCI device.
                    218:      * 
                    219:      * The hardware implementation may or may not have a ROM present
                    220:      * accounting for the difference in the number of ranges.
                    221:      */
                    222:     n = provider->getDeviceMemoryCount();
                    223:     if ( !( n == 3  ||  n == 4 )  )
                    224:     {
                    225:         return false;
                    226:     }
                    227: 
                    228:     /*
                    229:      * Determine the hardware version. Check the deviceID and
                    230:      * RevID in the PCI config regs.
                    231:      */
                    232:     pciReg0 = provider->configRead32( 0x00 );
                    233:     pciReg8 = provider->configRead32( 0x08 ); 
                    234: 
                    235:     chipId  = pciReg0 >> 16;
                    236:     chipRev = pciReg8 & 0xff;
                    237: 
                    238: //    IOLog( "SCSI(Symbios8xx): Chip Id = %04x Chip rev = %02x\n\r", chipId, chipRev );
                    239: 
                    240: 
                    241:     ioMapRegs = provider->mapDeviceMemoryWithRegister( 0x14 );
                    242:     if ( ioMapRegs == 0 )
                    243:     {
                    244:         return false;
                    245:     }
                    246: 
                    247:     switch ( chipId )
                    248:     {
                    249:         case kChipIdSym875:
                    250:             ramReg = 0x18;
                    251:             break;
                    252: 
                    253:         case kChipIdSym895:
                    254:         case kChipIdSym896:
                    255:             ramReg = 0x1C;
                    256:             break;
                    257: 
                    258:         default:
                    259:             ramReg = 0x1C;
                    260:     }
                    261: 
                    262:     ioMapRam = provider->mapDeviceMemoryWithRegister( ramReg );
                    263:     if ( ioMapRam == 0 )
                    264:     {
                    265:         return false;
                    266:     }
                    267: 
                    268:     /*
                    269:      * Assume 80Mhz external clock rate for motherboard 875 implementations
                    270:      * and 40Mhz for others.
                    271:      */
                    272:     matchEntry = OSDynamicCast( OSString, getProperty( gIONameMatchedKey ) );
                    273:     if ( matchEntry == 0 )
                    274:     {
                    275:         IOLog("SCSI(Sym8xx): Cannot obtain matching property.\n");
                    276:         return false;
                    277:     }
                    278: 
                    279:     if ( matchEntry->isEqualTo( "apple53C8xx" ) == true )
                    280:     {
                    281:       chipClockRate = CLK_80MHz;
                    282:     }
                    283:     else
                    284:     {
                    285:       chipClockRate = CLK_40MHz;
                    286:     }
                    287: 
                    288:     /*
                    289:      * BUS MASTER, MEM I/O Space, MEM WR & INV
                    290:      */
                    291:     provider->configWrite32( 0x04, 0x16 );
                    292: 
                    293:     /*
                    294:      *  set Latency to Max , cache 32
                    295:      */
                    296:     provider->configWrite32( 0x0C, 0x2008 );
                    297: 
                    298:     /*
                    299:      * get chip register block mapped into pci memory
                    300:      */
                    301:     chipBaseAddr        = (UInt8 *)ioMapRegs->getVirtualAddress();
                    302:     chipBaseAddrPhys   = (UInt8 *)ioMapRegs->getPhysicalAddress();
                    303: 
                    304: //  kprintf( "SCSI(Symbios8xx): Chip Base addr = %08x(p) %08x(v)\n\r", 
                    305: //          (UInt32)chipBaseAddrPhys, (UInt32)chipBaseAddr );
                    306: 
                    307:     chipRamAddr        = (UInt8 *)ioMapRam->getVirtualAddress();
                    308:     chipRamAddrPhys    = (UInt8 *)ioMapRam->getPhysicalAddress();
                    309: 
                    310: //  kprintf( "SCSI(Symbios8xx): Chip Ram  addr = %08x(p) %08x(v)\n\r",  
                    311: //           (UInt32)chipRamAddrPhys,  (UInt32)chipRamAddr );
                    312: 
                    313:     /*
                    314:      * Attach interrupt
                    315:      */
                    316:     interruptEvent = IOInterruptEventSource::interruptEventSource(
                    317:             (OSObject *)             this,
                    318:             (IOInterruptEventAction) &Sym8xxSCSIController::interruptOccurred,
                    319:             (IOService *)            provider,
                    320:             (int)                    0 );
                    321: 
                    322:     if ( interruptEvent == NULL )
                    323:     {
                    324:         return false;
                    325:     }
                    326: 
                    327:     getWorkLoop()->addEventSource( interruptEvent );
                    328:  
                    329:     interruptEvent->enable();
                    330: 
                    331:     /*
                    332:      * 
                    333:      */
                    334:     memoryCursor = IOBigMemoryCursor::withSpecification( 16*1024*1024, 0xffffffff );
                    335:     if ( memoryCursor == NULL )
                    336:     {
                    337:         return false;
                    338:     }
                    339: 
                    340: 
                    341: 
                    342:     return true;
                    343: }
                    344: 
                    345: /*-----------------------------------------------------------------------------*
                    346:  * This routine allocates/initializes shared memory for communication between 
                    347:  * the script and the driver. In addition other driver resources semaphores, 
                    348:  * queues are initialized here.
                    349:  *
                    350:  *-----------------------------------------------------------------------------*/
                    351: bool Sym8xxSCSIController::Sym8xxInitVars()
                    352: {
                    353:     UInt32                     i;
                    354: 
                    355:     adapter = (AdapterInterface *)IOMallocContiguous( page_size, page_size, (IOPhysicalAddress *)&adapterPhys );
                    356:     if ( adapter == 0 )
                    357:     {
                    358:         return false;
                    359:     }
                    360:     bzero( adapter, page_size );
                    361: 
                    362:     /*
                    363:      * We keep two copies of the Nexus pointer array. One contains physical addresses and
                    364:      * is located in the script/driver shared storage. The other copy holds the corresponding
                    365:      * virtual addresses to the active Nexus structures and is located in the drivers instance
                    366:      * data.
                    367:      * Both tables can be accessed through indirect pointers in the script/driver communication
                    368:      * area. This is the preferred method to access these arrays.
                    369:      */ 
                    370:     adapter->nexusPtrsVirt = (Nexus **)nexusArrayVirt;
                    371:     adapter->nexusPtrsPhys = (Nexus **)adapter->nexusArrayPhys;
                    372: 
                    373:     for (i=0; i < MAX_SCSI_TAG; i ++ )
                    374:     {
                    375:         adapter->nexusPtrsVirt[i] = (Nexus *) -1;
                    376:         adapter->nexusPtrsPhys[i] = (Nexus *) -1;
                    377:     }
                    378:  
                    379:     /*
                    380:      * The script/driver communication area also contains a 16-entry table clock
                    381:      * settings for each target.
                    382:      */ 
                    383:     for (i=0; i < MAX_SCSI_TARGETS; i++ )
                    384:     {
                    385:         adapter->targetClocks[i].scntl3Reg = SCNTL3_INIT_875;
                    386:     }
                    387: 
                    388: 
                    389:     return true;
                    390: }
                    391: 
                    392: 
                    393: /*-----------------------------------------------------------------------------*
                    394:  * This routine makes a temporary copy of the script program, applies script fixups,
                    395:  * initializes the script local data table at the top of the script image, and
                    396:  * copies the modified script image to the script engine's on-board ram.
                    397:  *
                    398:  *-----------------------------------------------------------------------------*/
                    399: bool Sym8xxSCSIController::Sym8xxInitScript()
                    400: {
                    401:     UInt32             i;
                    402:     UInt32             scriptPgm[sizeof(BSC_SCRIPT)/sizeof(UInt32)];
                    403: 
                    404:     /*
                    405:      * Make a copy of the script
                    406:      */
                    407:     bcopy( BSC_SCRIPT, scriptPgm, sizeof(scriptPgm) );
                    408:     bzero( scriptPgm, R_ld_size );
                    409: 
                    410:     /*
                    411:      * Apply fixups to the script copy
                    412:      */
                    413:     for ( i=0; i < sizeof(Rel_Patches)/sizeof(UInt32); i++ )
                    414:     {
                    415:         scriptPgm[Rel_Patches[i]] += (UInt32)chipRamAddrPhys;
                    416:     }
                    417:     for ( i=0; i < sizeof(LABELPATCHES)/sizeof(UInt32); i++ )
                    418:     {
                    419:         scriptPgm[LABELPATCHES[i]] += (UInt32)chipRamAddrPhys;
                    420:     }
                    421:  
                    422:     /*
                    423:      * Initialize the script working variables with pointers to the script/driver
                    424:      * communications area.
                    425:      */
                    426:     scriptPgm[R_ld_sched_mlbx_base_adr >> 2]   = (UInt32)&adapterPhys->schedMailBox;
                    427:     scriptPgm[R_ld_nexus_array_base >> 2]      = (UInt32)&adapterPhys->nexusArrayPhys;
                    428:     scriptPgm[R_ld_device_table_base_adr >> 2]         = (UInt32)&adapterPhys->targetClocks;
                    429: 
                    430:     /*
                    431:      * Load the script image into the script engine's on-board ram.
                    432:      */
                    433:     Sym8xxLoadScript( (UInt32 *)scriptPgm, sizeof(scriptPgm)/sizeof(UInt32) );
                    434: 
                    435:     return true;
                    436: }
                    437: 
                    438: 
                    439: /*-----------------------------------------------------------------------------*
                    440:  * This routine transfers the script program image into the script engine's
                    441:  * on-board ram
                    442:  *
                    443:  *-----------------------------------------------------------------------------*/
                    444: void Sym8xxSCSIController::Sym8xxLoadScript( UInt32 *scriptPgm,  UInt32 scriptWords )
                    445: {
                    446:     UInt32                     i;
                    447:     volatile UInt32            *ramPtr = (volatile UInt32 *)chipRamAddr;
                    448: 
                    449:     for ( i = 0; i < scriptWords; i++ )
                    450:     {
                    451:         ramPtr[i] = OSSwapHostToLittleInt32(scriptPgm[i]);
                    452:     }
                    453: }
                    454: 
                    455: /*-----------------------------------------------------------------------------*
                    456:  * This routine initializes the script engine's register block.
                    457:  *
                    458:  *-----------------------------------------------------------------------------*/
                    459: bool Sym8xxSCSIController::Sym8xxInitChip()
                    460: {
                    461:     UInt32                     i;
                    462: 
                    463:     /*
                    464:      * Reset the script engine
                    465:      */
                    466:     Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, RST );
                    467:     IODelay( 25 );
                    468:     Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, ISTAT_INIT );
                    469:   
                    470:     /*
                    471:      * Load our canned register values into the script engine
                    472:      */
                    473:     for ( i = 0; i < sizeof(Sym8xxInitRegs)/sizeof(ChipInitRegs); i++ )
                    474:     {
                    475:         Sym8xxWriteRegs( chipBaseAddr, Sym8xxInitRegs[i].regNum, Sym8xxInitRegs[i].regSize, Sym8xxInitRegs[i].regValue );
                    476:         IODelay( 10 );
                    477:     }
                    478: 
                    479:     /*
                    480:      * For hardware implementations that have a 40Mhz SCLK input, we enable the chip's on-board
                    481:      * clock doubler to bring the clock rate upto 80Mhz which is required for Ultra-SCSI timings.
                    482:      */
                    483:     if ( chipClockRate == CLK_40MHz )
                    484:     {
                    485:         /*
                    486:          *   Clock doubler setup for 875 (rev 3 and above).
                    487:          */
                    488:         /* set clock doubler enabler bit */
                    489:         Sym8xxWriteRegs( chipBaseAddr, STEST1, STEST1_SIZE, STEST1_INIT | DBLEN);
                    490:         IODelay(30);  
                    491:         /* halt scsi clock */
                    492:         Sym8xxWriteRegs( chipBaseAddr, STEST3, STEST3_SIZE, STEST3_INIT | HSC );
                    493:         IODelay(10);
                    494:         Sym8xxWriteRegs( chipBaseAddr, SCNTL3, SCNTL3_SIZE, SCNTL3_INIT_875);
                    495:         IODelay(10);
                    496:         /* set clock doubler select bit */
                    497:         Sym8xxWriteRegs( chipBaseAddr, STEST1, STEST1_SIZE, STEST1_INIT | DBLEN | DBLSEL);
                    498:         IODelay(10);
                    499:         /* clear hold on scsi clock */
                    500:         Sym8xxWriteRegs( chipBaseAddr, STEST3, STEST3_SIZE, STEST3_INIT);
                    501:     }
                    502: 
                    503:     /*  
                    504:      * Set our host-adapter ID in the script engine's registers
                    505:      */
                    506:     initiatorID = kHostAdapterSCSIId;
                    507: 
                    508:     if ( initiatorID > 7 )
                    509:     {
                    510:         Sym8xxWriteRegs( chipBaseAddr, RESPID1, RESPID1_SIZE, 1 << (initiatorID-8));
                    511:     }
                    512:     else
                    513:     {
                    514:         Sym8xxWriteRegs( chipBaseAddr, RESPID0, RESPID0_SIZE, 1 << initiatorID);
                    515:     }
                    516: 
                    517:     Sym8xxWriteRegs( chipBaseAddr, SCID, SCID_SIZE, SCID_INIT | initiatorID );
                    518: 
                    519:     return true;
                    520: }
                    521: 
                    522: 

unix.superglobalmegacorp.com

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