mirror of
https://github.com/elliotnunn/sys7.1-doc-wip.git
synced 2024-12-12 20:29:12 +00:00
1097 lines
39 KiB
C
1097 lines
39 KiB
C
/*
|
|
File: BootItt.c
|
|
|
|
Contains: Code that loads in SCSI Drivers at boot time
|
|
|
|
Entry points: InitSCSIBoot
|
|
IttBoot
|
|
IsItt
|
|
|
|
Written by: Clinton Bauder
|
|
|
|
Copyright: © 1992-1994 by Apple Computer, Inc., all rights reserved.
|
|
|
|
Change History (most recent first):
|
|
|
|
<SM36> 1/28/94 chp Move a local variable declaration inside a conditional
|
|
compilation block so it won't generate a compiler warning when
|
|
it is not used.
|
|
<SM35> 1/25/94 DCB Fixed a minor error in the way we interpret PRAM. The code was
|
|
assuming that SCSI ID 7 had a fixed unit table entry which is
|
|
not true. (only 0-6)
|
|
<SM34> 1/13/94 chp Adjust the usage of dNeedLock and dRAMBased, since the former
|
|
local definitions were different than the constants defined in
|
|
Inside Mac, and now in Devices.h.
|
|
<SM33> 1/13/94 chp Modify SOpenDriver to use new driver types in Devices.h.
|
|
<SM32> 11/22/93 pdw Rolling in from <MCxx>.
|
|
<MC5> 11/9/93 pdw Fixed problem with almost-bootable floppies. IttBoot now
|
|
returns the refNum of the default disk whenever it sees it. We
|
|
also init SCSIDrvrs in here and call InitSCSIBoot from InitItt
|
|
instead of from StartSearch.
|
|
<SM31> 10/29/93 DCB Don't load SIMs from the SlotManager at INIT time.
|
|
<SM30> 10/14/93 pdw <MC> roll-in.
|
|
<MC3> 9/26/93 pdw Fixed a little problem with the forceBoot stuff - should work
|
|
just fine now.
|
|
<MC2> 9/26/93 pdw Added forceBoot ability, fixed CmdShOptDel, fixed multi-bus
|
|
booting bugs, a couple of other little bug fixes/changes.
|
|
<SM29> 9/12/93 pdw Name changes. Added start of check for VirtualID info for
|
|
generating mask when running post-boot.
|
|
<SM28> 9/9/93 pdw Lots of little changes. Name changes, temporary cache_bug
|
|
stuff.
|
|
<SM27> 8/23/93 pdw Added support for LimitPRAMClear, IgnoreCmdOptShDel,
|
|
LoadDefaultOnly - three options required for AIX security,
|
|
enabled by setting bits in PRAM $76.
|
|
<SM26> 7/8/93 pdw Changed some shorts to longs.
|
|
<SM25> 6/29/93 pdw Massive checkins: Change asynchronicity mechanism to CallMachine
|
|
stack switching mechanism. Adding support for Cold Fusion.
|
|
Rearranging HW/SW Init code. Some code optimizations.
|
|
<SM24> 5/31/93 PW Made references to block numbers in the DDM and the Partition
|
|
map relative to the DDM.
|
|
<SM23> 5/29/93 PW Quoting instead of <> StandardGlue.h
|
|
<SM22> 5/29/93 PW Started putting in AIX boot stuff. Added check for PRAM OSType
|
|
instead of constant sbMac check.
|
|
<SM21> 5/25/93 DCB Rollin from Ludwig. (The next two items below)
|
|
<LW14> 5/24/93 PW Fixing "conflict with Figment" bug which is actually our failing
|
|
to clear a parameter block before using it.
|
|
<LW13> 5/21/93 PW Using scsiMaxTarget in BusInquiry for highestSCSIID instead of
|
|
figuring it out based on scsiBusWideXX characteristics.
|
|
<SM20> 5/24/93 PW Fixing "conflict with Figment" bug which is actually our failing
|
|
to clear a parameter block before using it.
|
|
<SM19> 5/5/93 PW Converted names to meanies-friendly names.
|
|
<LW11> 3/26/93 PW Cleared parameter blocks before using them.
|
|
<SM17> 3/20/93 PW Included SysEqu.
|
|
<LW10> 3/23/93 DCB Fixed a bug which prevented bootable CDs from booting. We need
|
|
to ignore Data Run errors at least until we have read block
|
|
zero. For now we will ignore them completely.
|
|
<LW9> 3/10/93 DCB Fixed a shine-through problem (again) which caused the high
|
|
nybble of D5 to get loaded with a weird value when loading
|
|
drivers.
|
|
<LW8> 3/8/93 DCB Fixed bug where startup disk wouldn't boot if CMD_OPT_SHFT_DEL
|
|
was released after nothing else booted.
|
|
<LW7> 3/8/93 PW Included SysEqu.
|
|
<LW6> 3/1/93 DCB Changed startup PRAM to match slot drivers. Also added code to
|
|
scan for srsrcs of type SIM.
|
|
<LW5> 2/17/93 PW Got rid of TIB - no longer supported.
|
|
<LW4> 2/13/93 PW Moved SetLoadFlag macro from BootItt.h to a routine in BootItt.c
|
|
for SCSIDrvrs lo-mem support.
|
|
<SM15> 2/1/93 PW Update from the latest of Ludwig. Also changes required for PDM
|
|
(will update Ludwig with these as needed myself).
|
|
<LW3> 1/27/93 DCB Added code for CmdOptShiftDel startup sequence to fix Radar Bug
|
|
1051033.
|
|
<LW2> 1/27/93 PW Changed kSlow to scsiTransferPolled.
|
|
<SM14> 12/9/92 PW Removed scsiDoVirtualMap flag so I had to remove its use in
|
|
BootItt.
|
|
<SM13> 12/5/92 PW Changed some names mostly.
|
|
<SM12> 12/4/92 CB Added Support for booting drives with a non-512 byte block size.
|
|
(CD-ROMs, some MOs etc.)
|
|
<SM11> 11/24/92 PW Narrowed check for same VID info to only same bus for old driver
|
|
loading qualification.
|
|
<SM10> 11/20/92 DCB Added explicit clear of the scsiCompletion field and setup of the
|
|
length field for SCSIActions
|
|
<SM9> 10/30/92 DCB Added a workaround for the Conner bug so that we can boot with
|
|
those drives.
|
|
<SM8> 10/8/92 DCB Changed offset for new driver loading to 8 bytes. This gives
|
|
driver writers greater flexibility.
|
|
<SM7> 10/8/92 PW (dcb) Added support for variable sized SCSI_IOs. Lots of
|
|
trivial name changes.
|
|
<SM6> 9/17/92 PW Changed SCSI_DriverPB to SCSI_Driver_PB.
|
|
<SM5> 8/31/92 DCB Fixed a problem with reading partition maps that had more than
|
|
one driver entry which caused disks to not mount.
|
|
<SM4> 8/20/92 DCB Changed boot code so it no longer used Select w/Atn to solve a
|
|
problem with Conner drives.
|
|
<SM3> 7/28/92 PW Resolve differences between pdw and (d)cb sources.
|
|
<SM2> 7/28/92 PW Added this comment.
|
|
<0> 6/24/92 DCB New Today
|
|
|
|
*/
|
|
|
|
#include <Types.h>
|
|
#include <Packages.h>
|
|
#include <Memory.h>
|
|
#include <Traps.h>
|
|
#include <OSUtils.h>
|
|
#include <TrapsPrivate.h>
|
|
#include <SysEqu.h>
|
|
#include <SCSIStandard.h>
|
|
#include <SCSI.h>
|
|
#include <OSUtils.h>
|
|
#include <Devices.h>
|
|
#include <Slots.h>
|
|
#include <Start.h>
|
|
|
|
//#include "IPLRecord.h"
|
|
|
|
#include "SCSIDebug.h"
|
|
#include "CUtils.h"
|
|
#include "ACAM.h"
|
|
#include "XPT.h"
|
|
#include "XPTpriv.h"
|
|
|
|
#include "BootItt.h"
|
|
|
|
|
|
short ScanDrive( DevInfo *, BootInfo *, Boolean * forceBootablePtr);
|
|
short AttemptDriverLoad( DevInfo *, BootInfo *, Boolean * forceBootablePtr);
|
|
short ScRead(DevInfo *, ulong, ulong,ushort, Ptr);
|
|
ulong CheckSumDrvr( Ptr driver,ushort length );
|
|
void SetLoadFlag( BootInfo * BInfo, DeviceIdent devIdent);
|
|
short LoadDriver( DevInfo *, ulong, ulong, Boolean, Ptr, Ptr, Partition * );
|
|
Boolean Ck4EjectableVolume( short drvrRefNum);
|
|
void DummyOldCallRead( short scsiID);
|
|
|
|
|
|
#define DONT_WAIT 1
|
|
#define KEEP_WAITING 0
|
|
|
|
|
|
/*————————————————————————————————————————————————————————————————————————
|
|
ISITT -
|
|
————————————————————————————————————————————————————————————————————————*/
|
|
|
|
Boolean ISITT()
|
|
{
|
|
return( NGetTrapAddress(SCSIATOM, OSTrap) !=
|
|
NGetTrapAddress(UNIMPTRAP, ToolTrap) );
|
|
}
|
|
|
|
/*————————————————————————————————————————————————————————————————————————
|
|
INITSCSIBOOT -
|
|
————————————————————————————————————————————————————————————————————————*/
|
|
|
|
void INITSCSIBOOT( void )
|
|
{
|
|
BootInfo *BInfo;
|
|
ushort numBuses, bus;
|
|
XPTglobals *XPTg; // We will store our globals with the XPTs globals
|
|
SCSIBusInquiryPB scPB; // Info about the scsi buses
|
|
SCSIGetVirtualIDInfoPB vidPB; // to determine (at init time) if we need to mask in SCSIDrvrs
|
|
|
|
#if ForROM
|
|
#if !forIttInit
|
|
|
|
char macIDpram;
|
|
|
|
// Since the XPT isn't loaded at PrimaryInit and since SecondaryInit is too late
|
|
// to load a SCSI Interface Module (SIM) we are going to try and help NuBus and
|
|
// PDS developers out by loading SIMs here at the start of StartSearch. We do
|
|
// this by loading sRSRCs of Category CatIntBus and cType TypSIM. Slots are
|
|
// searched for sRSRCs of this type and then loaded as a driver.
|
|
|
|
SpBlock tempSp; // Slot Manager PB used to locate SIMs
|
|
SpBlock loadSp; // Slot Manager PB used to load SIMs
|
|
SEBlock simSe; // exec block that will be passed to each slot SIM
|
|
|
|
/* Start with slot zero and look from there... */
|
|
tempSp.spSlot = 0; tempSp.spID = 0; tempSp.spExtDev = 0;
|
|
tempSp.spDrvrHW = 0; tempSp.spHwDev = 0;
|
|
tempSp.spTBMask = 3; /* don't pay attention to hardware or software vendors */
|
|
tempSp.spCategory = CatIntBus;
|
|
tempSp.spCType = TypSIM;
|
|
tempSp.spDrvrSW = DrvrSwScsi43;
|
|
|
|
while( SNextTypeSRsrc((SpBlockPtr)&tempSp) == noErr ) {
|
|
|
|
loadSp = tempSp; /* Don't touch the original parameter block or SNext Loop will get
|
|
screwed up and will start at the begining again */
|
|
simSe.seSlot = loadSp.spSlot;
|
|
simSe.sesRsrcId = loadSp.spID;
|
|
loadSp.spsExecPBlk = (Ptr)&simSe;
|
|
if (noErr == SGetDriver((SpBlockPtr)&loadSp)) {
|
|
SOpenDriver((SpBlockPtr)&loadSp);
|
|
}
|
|
}
|
|
|
|
// Old SCSI Manager compatibility ————
|
|
// Certain old applications and SCSI utilities use the SCSIDrvrs lo-mem. We'll generate
|
|
// it's default value here by setting the host ID bit (found in byte 2 of PRAM).
|
|
|
|
ReadXPRam( 1, 0x02, &macIDpram); // read 1 byte at location 2
|
|
SCSIDrvrs = 1 << ( macIDpram & 0x07 ); // set bit at host ID
|
|
|
|
#endif
|
|
#endif
|
|
|
|
Clear( (char *)&scPB, sizeof(scPB));
|
|
Clear( (char *)&vidPB, sizeof(vidPB));
|
|
|
|
// Find out how manuy buses there are in the sytem and alloc a BootInfo with that many IDmasks on the end
|
|
|
|
scPB.scsiDevice.bus = -1; // XPT=-1
|
|
scPB.scsiFlags = 0;
|
|
scPB.scsiFunctionCode = SCSIBusInquiry;
|
|
scPB.scsiPBLength = sizeof(SCSIBusInquiryPB); // <SM10>
|
|
scPB.scsiCompletion = nil; // <SM10>
|
|
SCSIAction( (SCSI_PB *) &scPB );
|
|
|
|
if ( scPB.scsiResult != noErr) {
|
|
DebugStr("\pInitSCSIBoot:BusInquiry failed getting numBuses");
|
|
}
|
|
|
|
numBuses = scPB.scsiHiBusID + 1;
|
|
|
|
if( (BInfo = (BootInfo *)NewPtrSysClear(sizeof(BootInfo) + sizeof(ulong) * numBuses)) == nil )
|
|
return;
|
|
|
|
// Get PRAM, Set up the BInfo and store it (in XPT's globals)
|
|
|
|
GetDefaultStartup( &(BInfo->startPRAM));
|
|
BInfo->BusCount = numBuses;
|
|
BInfo->defltDrvrRefNum = KEEP_WAITING;
|
|
|
|
XPTg = GetXPTg();
|
|
XPTg->BootStorage = (Ptr)BInfo;
|
|
|
|
// Start with the mask so far of the drivers that we
|
|
// loaded at original boot time. This is only needed
|
|
// when we're running as an init or a patch (i.e. on Quadras).
|
|
|
|
for (bus = 0; bus <= scPB.scsiHiBusID; bus+=1) {
|
|
BInfo->IDmasks[bus] = SCSIDrvrs; // change to check VirtualID!!!%%%_debugger
|
|
|
|
vidPB.scsiDevice.bus = bus;
|
|
vidPB.scsiDevice.targetID = 0;
|
|
vidPB.scsiFlags = 0;
|
|
vidPB.scsiFunctionCode = SCSIGetVirtualIDInfo;
|
|
vidPB.scsiPBLength = sizeof(SCSIGetVirtualIDInfoPB);
|
|
vidPB.scsiCompletion = nil;
|
|
SCSIAction( (SCSI_PB *) &vidPB );
|
|
|
|
if ( vidPB.scsiResult != noErr) { // !!! _debugger WE NEED TO DO SOMETHING WITH THIS
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*————————————————————————————————————————————————————————————————————————
|
|
IttBoot -
|
|
————————————————————————————————————————————————————————————————————————*/
|
|
|
|
short
|
|
ITTBOOT( ulong onlyStartup, Boolean * forceBootPtr )
|
|
{
|
|
SCSIGetVirtualIDInfoPB getVIDPB; /* for scanning for refNum-driven startup */
|
|
SCSIBusInquiryPB biPB; /* Info about the scsi busses */
|
|
BootInfo * BInfo;
|
|
SCSI_IO * ioPtr; /* Our SCSI Parameter block */
|
|
uchar busID; /* Current scsi bus */
|
|
char hostSCSIID; /* host Mac SCSI ID */
|
|
char highestSCSIID; /* highest SCSI ID on this bus */
|
|
char scsiID; /* Current target */
|
|
DevInfo device; /* Current Device */
|
|
DevInfo fakeScanDevice; /* Device ident used for fake scan of boot ID on higher priority buses */
|
|
DevInfo startdevice; /* Startup Device */
|
|
short defRefNum = 0; /* Default refnum for startup */
|
|
short forceBootRefNum =0; /* Force boot (from specially marked ejectable media) */
|
|
XPTglobals *XPTg; /* We will store our globals with the XPTs globals */
|
|
ulong longPRAM;
|
|
ushort PRAMRefNum;
|
|
char * trashBlockPtr;
|
|
ushort maxSCPBSize; // The largest PB we will need <SM7> pdw
|
|
Boolean foundBus;
|
|
Boolean csodKeysDown;
|
|
Boolean forcedBoot;
|
|
Boolean unknownPRAM; // set when we figure out that we can't figure it out
|
|
|
|
|
|
//——— Initialization ———
|
|
|
|
XPTg = GetXPTg();
|
|
BInfo = (BootInfo *) XPTg->BootStorage;
|
|
|
|
if ( (*(short *)(lm_KeyMap + 6) == (short) CmdShiftOptDel) && !Ck4IgnoreCmdShOptDel()) {
|
|
csodKeysDown = true;
|
|
bset( kbCSOD, &(XPTg->flags));
|
|
}
|
|
else
|
|
csodKeysDown = false;
|
|
|
|
// Initialize our 2 much-used PBs
|
|
|
|
Clear( (char *)&biPB, sizeof(biPB));
|
|
biPB.scsiFunctionCode = SCSIBusInquiry;
|
|
biPB.scsiPBLength = sizeof(SCSIBusInquiryPB);
|
|
|
|
Clear((char *)&getVIDPB, sizeof(getVIDPB));
|
|
getVIDPB.scsiFunctionCode = SCSIGetVirtualIDInfo;
|
|
getVIDPB.scsiPBLength = sizeof(SCSIGetVirtualIDInfo);
|
|
|
|
// Find out just how big our ioPB needs to be
|
|
|
|
biPB.scsiDevice.bus = -1; // XPT (we're getting max size of all bus's PBs)
|
|
SCSIAction( (SCSI_PB *) &biPB );
|
|
if ( biPB.scsiResult != noErr) {
|
|
IfDebugStr("\pIttBoot:BusInquiry failed getting maxSCPBSize");
|
|
return (DONT_WAIT);
|
|
}
|
|
maxSCPBSize = biPB.scsiMaxIOpbSize;
|
|
|
|
// Initialize a 1 block trash buffer for our use
|
|
|
|
if( (trashBlockPtr = NewPtrSysClear(0x200)) == nil )
|
|
return (DONT_WAIT); /* Try and boot with a driver that is already loaded... */
|
|
|
|
// Initialize a SCSI_IO parameter block for our use
|
|
|
|
if( (ioPtr = (SCSI_IO *)NewPtrSysClear(maxSCPBSize)) == nil )
|
|
return (DONT_WAIT); /* Try and boot with a driver that is already loaded... */
|
|
|
|
ioPtr->scsiPBLength = maxSCPBSize;
|
|
|
|
device.ioPB = ioPtr; /* Remember PB for later use */
|
|
startdevice.ioPB = ioPtr; /* Remember PB for later use */
|
|
|
|
|
|
//——— Deal with Default Boot Device first ———
|
|
|
|
// Determine the type of PRAM
|
|
|
|
unknownPRAM =false;
|
|
|
|
// If slot style PRAM... (new style)
|
|
if( (BInfo->startPRAM.slotDev.sdSlotNum & 0xF0) == 0 ) {
|
|
|
|
// Loop through Buses looking for one with this slot number and sRsrc ID
|
|
|
|
foundBus = false;
|
|
|
|
for( busID = 0; busID < BInfo->BusCount; busID+=1 ) {
|
|
biPB.scsiDevice.bus = busID;
|
|
SCSIAction( (SCSI_PB *) &biPB ); /* Get info for the internal (first) bus */
|
|
if ( biPB.scsiResult != noErr)
|
|
DebugStr("\pIttBoot:BusInquiry failed getting scsiHBAslotNumber");
|
|
|
|
if( biPB.scsiHBAslotNumber == BInfo->startPRAM.slotDev.sdSlotNum &&
|
|
biPB.scsiSIMsRsrcID == BInfo->startPRAM.slotDev.sdSRsrcID ) {
|
|
device.DevIdent.diReserved = 0;
|
|
device.DevIdent.bus = busID;
|
|
device.DevIdent.targetID = (BInfo->startPRAM.slotDev.sdExtDevID>>3) & 0x1f; // upper 5 bits
|
|
device.DevIdent.LUN = BInfo->startPRAM.slotDev.sdExtDevID & 0x07; // lower 3 bits
|
|
|
|
if( device.DevIdent.LUN ) // Only do select w/atn + identify message for non-zero luns
|
|
device.IdentMsg = true;
|
|
else
|
|
device.IdentMsg = false;
|
|
|
|
foundBus = true;
|
|
break; // from for loop
|
|
}
|
|
}
|
|
|
|
if (!foundBus)
|
|
defRefNum = DONT_WAIT; // don't wait anymore
|
|
else
|
|
{
|
|
startdevice = device;
|
|
|
|
// Don't load a driver from the startup device if CmdShiftOptDel keys are down
|
|
|
|
if ( csodKeysDown ) {
|
|
defRefNum = DONT_WAIT; // Tell WaitForInternal to stop trying
|
|
bset( kbCSODatBoot, &(XPTg->flags));
|
|
}
|
|
else {
|
|
// hit each device at this ID that might want higher priority VID mapping
|
|
for( busID=0; busID<device.DevIdent.bus; busID+=1 ) {
|
|
biPB.scsiDevice.bus = busID;
|
|
SCSIAction( (SCSI_PB *) &biPB );
|
|
fakeScanDevice = device;
|
|
fakeScanDevice.DevIdent.LUN = 0; // we just want to see if there's a device there
|
|
if( biPB.scsiFeatureFlags & scsiBusOldCallCapable ) {
|
|
/* Read block 0 of each device at this ID on other buses */
|
|
fakeScanDevice.DevIdent.bus = busID;
|
|
ScRead( &device, 0, 1, 512, trashBlockPtr );
|
|
}
|
|
}
|
|
// then try to load the driver for our specified boot device
|
|
if( TestLoadFlag( BInfo, startdevice.DevIdent) ) {
|
|
// we already hit the boot device, so we return that value
|
|
defRefNum = BInfo->defltDrvrRefNum;
|
|
}
|
|
else {
|
|
defRefNum = AttemptDriverLoad( &startdevice, BInfo, forceBootPtr);
|
|
BInfo->defltDrvrRefNum = defRefNum;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if the PRAM is a fixed drefnum for a SCSI device... (old style)
|
|
else
|
|
{
|
|
startdevice.DevIdent.bus = -1; // dummy value for now
|
|
longPRAM = *(ulong *)&BInfo->startPRAM;
|
|
PRAMRefNum = (ushort) (longPRAM & 0xFFFF);
|
|
if( PRAMRefNum >= 0xFFD9 && PRAMRefNum <= 0xFFDF ) {
|
|
device.IdentMsg = false; // !!!
|
|
device.DevIdent.diReserved = 0;
|
|
device.DevIdent.bus = -1; // dummy value for now
|
|
device.DevIdent.targetID = ~PRAMRefNum - 32;
|
|
device.DevIdent.LUN = 0; /* Don't Scan LUNs */
|
|
|
|
// If we have an old ID mapping already, we simply use that bus
|
|
// else, we need to scan all of the oldCallCapable buses until -
|
|
// 1. we find a device (getVID.scsiExists == true) or,
|
|
// 2. we run out of buses
|
|
|
|
getVIDPB.scsiOldCallID = device.DevIdent.targetID;
|
|
SCSIAction((SCSI_PB *) &getVIDPB);
|
|
if ( getVIDPB.scsiResult != noErr) {
|
|
IfDebugStr("\pIttBoot:getVID failed");
|
|
return (DONT_WAIT); // don't wait for it
|
|
}
|
|
|
|
if ( !getVIDPB.scsiExists ) // doesn't already exist? scan
|
|
{
|
|
// Scan OldCallCapable bus(es) until finding VID or running out of buses
|
|
|
|
for ( busID = 0; busID<BInfo->BusCount; busID+=1 ) {
|
|
biPB.scsiDevice.bus = busID;
|
|
SCSIAction( (SCSI_PB *) &biPB );
|
|
if( !(biPB.scsiFeatureFlags & scsiBusOldCallCapable))
|
|
continue;
|
|
|
|
DummyOldCallRead( device.DevIdent.targetID);
|
|
|
|
// if old-ID mapping now exists, then no more scanning
|
|
SCSIAction((SCSI_PB *) &getVIDPB);
|
|
if ( getVIDPB.scsiExists ) {
|
|
break; // get out of loop
|
|
}
|
|
}
|
|
}
|
|
|
|
// after scan, if old-ID mapping now exists, this is the bus
|
|
|
|
if (getVIDPB.scsiExists)
|
|
{
|
|
device.DevIdent.bus = getVIDPB.scsiDevice.bus;
|
|
startdevice = device;
|
|
|
|
if( TestLoadFlag( BInfo, device.DevIdent) ) {
|
|
// we already hit the boot device, so we return that value
|
|
defRefNum = BInfo->defltDrvrRefNum;
|
|
}
|
|
else if (csodKeysDown) {
|
|
defRefNum = DONT_WAIT; // Don't WaitForInternal search keep trying
|
|
bset( kbCSODatBoot, &(XPTg->flags));
|
|
}
|
|
else {
|
|
defRefNum = AttemptDriverLoad( &device, BInfo, forceBootPtr);
|
|
BInfo->defltDrvrRefNum = defRefNum;
|
|
}
|
|
}
|
|
else
|
|
defRefNum = KEEP_WAITING; // no device yet - keep waiting
|
|
}
|
|
else // unknown PRAM format
|
|
{
|
|
unknownPRAM = true;
|
|
defRefNum = DONT_WAIT; // don't wait anymore
|
|
}
|
|
}
|
|
|
|
// If we're not supposed to continue on and look for other disks, let's exit here
|
|
|
|
if( onlyStartup || Ck4OnlyLoadFromDefault() ) {
|
|
DisposPtr( (Ptr)ioPtr );
|
|
DisposPtr( trashBlockPtr );
|
|
return (defRefNum);
|
|
}
|
|
|
|
|
|
//——— Scan all buses for other disks ———
|
|
|
|
*forceBootPtr = false;
|
|
|
|
for( busID = 0; busID < BInfo->BusCount; busID+=1 ) {
|
|
biPB.scsiDevice.bus = busID;
|
|
SCSIAction( (SCSI_PB *) &biPB ); /* Get info for this bus */
|
|
|
|
if ( biPB.scsiResult != noErr)
|
|
DebugStr("\p IttBoot:BusInquiry failed getting scsiMaxTarget");
|
|
|
|
highestSCSIID = biPB.scsiMaxTarget;
|
|
hostSCSIID = biPB.scsiInitiatorID;
|
|
|
|
for( scsiID = highestSCSIID; scsiID >= 0; scsiID-=1 ) {
|
|
if (scsiID == hostSCSIID) {
|
|
continue;
|
|
}
|
|
device.DevIdent.diReserved = 0;
|
|
device.DevIdent.bus = busID;
|
|
device.DevIdent.targetID = scsiID;
|
|
device.DevIdent.LUN = 0; /* Don't Scan LUNs */
|
|
device.IdentMsg = false; // !!!
|
|
if( TestLoadFlag(BInfo,device.DevIdent) ) {
|
|
continue; /* We have already made a decision on this */
|
|
}
|
|
if (unknownPRAM || !csodKeysDown) {
|
|
forceBootRefNum = AttemptDriverLoad( &device, BInfo, &forcedBoot);
|
|
}
|
|
else if( device.DevIdent != startdevice.DevIdent) {
|
|
bset( kbCSODatScan, &(XPTg->flags));
|
|
forceBootRefNum = AttemptDriverLoad( &device, BInfo, &forcedBoot);
|
|
}
|
|
|
|
// If this last one was a force boot, remember that and its refNum
|
|
|
|
if ( forcedBoot && forceBootRefNum<0) {
|
|
*forceBootPtr = true;
|
|
defRefNum = forceBootRefNum;
|
|
}
|
|
}
|
|
}
|
|
DisposPtr( (Ptr)ioPtr );
|
|
DisposPtr( trashBlockPtr );
|
|
|
|
return (defRefNum);
|
|
}
|
|
|
|
/*————————————————————————————————————————————————————————————————————————
|
|
AttemptDriverLoad -
|
|
————————————————————————————————————————————————————————————————————————*/
|
|
|
|
/* Attempt to load a driver for this device
|
|
**
|
|
** First ask the SIM to try. If the SIM doesn't know how to do this or
|
|
** if it fails then we look at the device and try to load a driver from
|
|
** the device. Failing this we again ask the SIM to try. This allows
|
|
** SIMs to either over-ride drivers on the device or only install an emergency
|
|
** "There wasn't any other driver to boot with" driver
|
|
*/
|
|
|
|
short // refNum
|
|
AttemptDriverLoad(
|
|
DevInfo * devInfoPtr,
|
|
BootInfo * BInfo,
|
|
Boolean * forceBootablePtr )
|
|
{
|
|
SCSILoadDriverPB LoadPB; /* PB for Loading SIM Drivers */
|
|
short dRefNum; /* The driver we loaded */
|
|
OSErr err;
|
|
|
|
Clear((char *)&LoadPB,sizeof(LoadPB));
|
|
|
|
dRefNum = 0; // 0 means we haven't found it but we haven't given up
|
|
LoadPB.scsiDevice = devInfoPtr->DevIdent;
|
|
LoadPB.scsiCompletion = 0;
|
|
LoadPB.scsiDiskLoadFailed = 0;
|
|
LoadPB.scsiPBLength = sizeof(LoadPB);
|
|
LoadPB.scsiFunctionCode = SCSILoadDriver;
|
|
err = SCSIAction( (SCSI_PB *) &LoadPB );
|
|
if( err != 0 || LoadPB.scsiLoadedRefNum == 0 ) {
|
|
dRefNum = ScanDrive( devInfoPtr, BInfo, forceBootablePtr);
|
|
if( dRefNum == 0 ) {
|
|
LoadPB.scsiDiskLoadFailed = 1;
|
|
if( SCSIAction( (SCSI_PB *) &LoadPB ) == noErr )
|
|
dRefNum = LoadPB.scsiLoadedRefNum;
|
|
}
|
|
}
|
|
else {
|
|
dRefNum = LoadPB.scsiLoadedRefNum; // <LW16> DCB
|
|
}
|
|
return ( dRefNum );
|
|
}
|
|
|
|
/*————————————————————————————————————————————————————————————————————————
|
|
ScanDrive -
|
|
————————————————————————————————————————————————————————————————————————*/
|
|
|
|
/* Scan The partition map for a driver and try to load it
|
|
**
|
|
** First Examine the driver map in block 0
|
|
** If it was valid Load in Block 1 and find out if it is a new partition map
|
|
** If not we load the driver and assume it is of type "Apple_Driver"
|
|
** If it is a new map we scan for a Driver Partition Map which matches the
|
|
** Entry in the driver map (Block 0) and the first HFS Partition
|
|
** If all of that succeeds we attempt to load the driver. "Apple_Driver43"s get
|
|
** a device Ident in d5 while older "Apple_Drivers" get a SCSI ID.
|
|
*/
|
|
|
|
short
|
|
ScanDrive(
|
|
DevInfo * devInfoPtr,
|
|
BootInfo * BInfo,
|
|
Boolean * forceBootablePtr )
|
|
{
|
|
|
|
Block0 *realBlock0; /* a buffer for block zero (Physical) */
|
|
Partition *curBlock; /* the current block we are working on */
|
|
Partition *HFSBlock; /* first HFS Partition map entry */
|
|
Partition *drvrBlock; /* Driver's Partition map entry */
|
|
ddMap *bootDrvr; /* Scratch */
|
|
ushort d; /* driver index (for scanning DDM) */
|
|
ulong drvrBlockStart; /* The starting block number of the driver */
|
|
ushort drvrSize; /* The size (in blocks) of the driver */
|
|
ulong b; /* partition block number index */
|
|
Boolean drvrIs43; /* false if old, true if new (4pt3) */
|
|
short dRefNum; /* The driver we loaded */
|
|
short partMapCount; /* Length of partition map */
|
|
ulong DDMBlockNum; /* block number of DDM */
|
|
uchar osType; /* OS Type read from PRAM */
|
|
|
|
|
|
// Initialize and alloc needed memory
|
|
|
|
dRefNum = KEEP_WAITING; /* don't have it yet - haven't given up */
|
|
HFSBlock = drvrBlock = curBlock = nil; /* Nobody home yet - needed for cleanup */
|
|
|
|
if( (realBlock0 = (Block0 *) NewPtrSysClear(512)) == nil )
|
|
goto Cleanup; /* Punt */
|
|
|
|
if( (curBlock = (Partition *) NewPtrSysClear(512)) == nil )
|
|
goto Cleanup; /* Punt */
|
|
|
|
// Read block 0 and see if it is a DDM or an IPLRecord or neither
|
|
|
|
if( ScRead( devInfoPtr, 0, 1, 512, (Ptr) realBlock0) ) /* Get block 0 (DDM/IPLRecord?) */
|
|
goto Cleanup;
|
|
|
|
if( realBlock0->sbSig == sbSIGWord ) { // udoublet at 0
|
|
DDMBlockNum = 0;
|
|
}
|
|
else if( ( (ipl_rec_area *)realBlock0 )->IPL_record_id == IPLRECID) { // uquadlet at 0
|
|
DDMBlockNum = ( (ipl_rec_area *)realBlock0 )->boot_prg_start;
|
|
if( ScRead( devInfoPtr, DDMBlockNum, 1, 512, (Ptr) realBlock0) )
|
|
goto Cleanup;
|
|
}
|
|
else {
|
|
SetLoadFlag(BInfo,devInfoPtr->DevIdent); /* Don't try me again! */
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Scan through drivers in DDM to find one that matches our OSType
|
|
|
|
ReadXPRam( 1, 0x77, &osType);
|
|
for( drvrBlockStart = 0, bootDrvr = (ddMap *)&realBlock0->ddBlock, d = 0 ; d < realBlock0->sbDrvrCount ; d+=1 ) {
|
|
if( bootDrvr[d].ddType == osType) {
|
|
drvrBlockStart = bootDrvr[d].ddBlock + DDMBlockNum;
|
|
drvrSize = bootDrvr[d].ddSize;
|
|
break;
|
|
}
|
|
}
|
|
if( drvrBlockStart == 0 ) { /* No Drivers in ddm */
|
|
SetLoadFlag(BInfo,devInfoPtr->DevIdent); /* Don't try me again! */
|
|
dRefNum = DONT_WAIT;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Read first block of part map to determine if it's valid and to find part map length
|
|
|
|
if( ScRead( devInfoPtr, DDMBlockNum+1,1,512,(Ptr)curBlock) ) {
|
|
SetLoadFlag(BInfo,devInfoPtr->DevIdent); /* Don't try me again! */
|
|
goto Cleanup;
|
|
}
|
|
|
|
if( curBlock->pmSig != newPMSigWord ) { /* Old Style PMap or one we don't recognize */
|
|
/* Be friendly and try to boot it anyway */
|
|
if( TestLoadFlag(BInfo,devInfoPtr->DevIdent) == 0 )
|
|
dRefNum = LoadDriver(devInfoPtr,drvrBlockStart,drvrSize,false, (Ptr)realBlock0,(Ptr)curBlock, 0); // <SM12>
|
|
SetLoadFlag(BInfo,devInfoPtr->DevIdent);
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Scan through part map to find HFS and driver partitions
|
|
|
|
for( b=1, drvrIs43 = 0, partMapCount = curBlock->pmMapBlkCnt ; b <= partMapCount ; b+=1 ) {
|
|
|
|
if( ScRead( devInfoPtr, DDMBlockNum+b, 1, 512, (Ptr)curBlock) ) {
|
|
SetLoadFlag( BInfo, devInfoPtr->DevIdent); /* Don't try me again! */
|
|
goto Cleanup;
|
|
}
|
|
if( drvrBlock == 0 &&
|
|
*(long *) &curBlock->pmParType[0] == 'Appl' &&
|
|
*(long *) &curBlock->pmParType[4] == 'e_Dr' &&
|
|
*(long *) &curBlock->pmParType[8] == 'iver' ) {
|
|
|
|
if( curBlock->pmPyPartStart != drvrBlockStart - DDMBlockNum) // <SM5>
|
|
continue; /* Whoops, not the driver from the DDM! */ // <SM5>
|
|
|
|
drvrIs43 = (*(short *)&(curBlock->pmParType[12]) == '43') ? true : false; // <SM7>
|
|
*forceBootablePtr = (*(long *)&(curBlock->pmParType[28]) == 'pdm!') ? true : false;
|
|
|
|
drvrBlock = curBlock;
|
|
|
|
if( (curBlock = (Partition *) NewPtrSysClear(512)) == nil )
|
|
goto Cleanup; /* Punt */
|
|
|
|
}
|
|
else if( HFSBlock == 0 &&
|
|
*(long *) &curBlock->pmParType[0] == 'Appl' &&
|
|
*(long *) &curBlock->pmParType[4] == 'e_HF' &&
|
|
curBlock->pmParType[8] == 'S' ) {
|
|
HFSBlock = curBlock;
|
|
if( (curBlock = (Partition *) NewPtrSysClear(512)) == nil )
|
|
goto Cleanup; /* Punt */
|
|
}
|
|
|
|
if( drvrBlock && HFSBlock )
|
|
break; // <SM5>
|
|
}
|
|
|
|
// Load the driver whether we found an HFS partition or not <SM5>
|
|
|
|
if( HFSBlock) {
|
|
if( TestLoadFlag( BInfo, devInfoPtr->DevIdent) == 0 ) {
|
|
dRefNum = LoadDriver( devInfoPtr, drvrBlockStart, drvrSize, drvrIs43, (Ptr)realBlock0, (Ptr)HFSBlock, drvrBlock ); // <SM12>
|
|
SetLoadFlag( BInfo, devInfoPtr->DevIdent);
|
|
}
|
|
}
|
|
|
|
if (*forceBootablePtr)
|
|
*forceBootablePtr = Ck4EjectableVolume( dRefNum);
|
|
|
|
Cleanup:
|
|
if( realBlock0 )
|
|
DisposPtr((Ptr) realBlock0);
|
|
if( curBlock )
|
|
DisposPtr((Ptr) curBlock);
|
|
if( HFSBlock )
|
|
DisposPtr((Ptr) HFSBlock);
|
|
if( drvrBlock )
|
|
DisposPtr((Ptr) drvrBlock);
|
|
|
|
return (dRefNum);
|
|
}
|
|
|
|
|
|
/*————————————————————————————————————————————————————————————————————————
|
|
LoadDriver -
|
|
————————————————————————————————————————————————————————————————————————*/
|
|
|
|
short
|
|
LoadDriver(
|
|
DevInfo * devInfoPtr,
|
|
ulong DrvrStart,
|
|
ulong DrvrLength,
|
|
Boolean NewDrvr,
|
|
Ptr BZero, // <SM12>
|
|
Ptr HFSBlock,
|
|
Partition * drvrBlock )
|
|
{
|
|
#pragma unused (drvrBlock)
|
|
Ptr theDrvr;
|
|
short dRefNum;
|
|
SCSI_Driver_PB myPB;
|
|
SCSIGetVirtualIDInfoPB myVIDpb;
|
|
|
|
//--- Check to see if it's OK to load and install the driver
|
|
|
|
Clear((char *)&myPB, sizeof(myPB));
|
|
Clear((char *)&myVIDpb, sizeof(myVIDpb));
|
|
|
|
if( NewDrvr) { //--- Driver43 ---
|
|
|
|
myPB.scsiDevice = devInfoPtr->DevIdent;
|
|
myPB.scsiCompletion = nil;
|
|
myPB.scsiPBLength = sizeof(SCSI_Driver_PB);
|
|
myPB.scsiFunctionCode = SCSILookupRefNumXref;
|
|
SCSIAction((SCSI_PB *) &myPB);
|
|
|
|
dRefNum = myPB.scsiDriver;
|
|
|
|
if( dRefNum != 0 )
|
|
return (dRefNum); /* Already installed */
|
|
}
|
|
else { //--- Old style driver --- <SM10>
|
|
|
|
//--- Don't load old driver if SCSI ID is 7 or higher
|
|
if( devInfoPtr->DevIdent.targetID >= 7)
|
|
return (DONT_WAIT);
|
|
|
|
//--- Don't load old driver if device doesn't match VirtualIDInfo
|
|
myVIDpb.scsiOldCallID = devInfoPtr->DevIdent.targetID;
|
|
myVIDpb.scsiFunctionCode = SCSIGetVirtualIDInfo;
|
|
SCSIAction((SCSI_PB *) &myVIDpb); // get the info about this ID
|
|
|
|
if (myVIDpb.scsiExists && myVIDpb.scsiDevice.bus != devInfoPtr->DevIdent.bus) //<SM11> pdw
|
|
return (DONT_WAIT);
|
|
|
|
//--- Don't load it if a driver is already installed at the static drvr slot for this ID
|
|
dRefNum = ~(devInfoPtr->DevIdent.targetID + 32); /* Convert SCSI ID to DRefNum */
|
|
if( GetDCtlEntry(dRefNum) != nil )
|
|
return (DONT_WAIT);
|
|
}
|
|
|
|
//--- Now try to load the driver and do a checksum on it
|
|
|
|
if( (theDrvr = NewPtrSys(DrvrLength * ((Block0 *)BZero)->sbBlkSize)) == nil ) // <SM12>
|
|
return (DONT_WAIT); /* No memory - give up */
|
|
|
|
if( ScRead( devInfoPtr, DrvrStart, DrvrLength, ((Block0 *)BZero)->sbBlkSize, theDrvr) ) {
|
|
DisposPtr(theDrvr);
|
|
return (KEEP_WAITING);
|
|
}
|
|
|
|
FlushInstructionCache();
|
|
FlushDataCache();
|
|
|
|
if( drvrBlock && *(long *)drvrBlock->pmPartName == 'Maci' ) {
|
|
/* !!! Why do a long comparison when the checksum routine returns a short ?
|
|
I don't have any idea - but this is the way the original SCSIBoot.a file
|
|
did it so I will continue to do it the same way until further notice. -DCB
|
|
*/
|
|
if( (ulong) drvrBlock->pmBootCksum != CheckSumDrvr( theDrvr,drvrBlock->pmBootSize ) ) {
|
|
DisposPtr(theDrvr);
|
|
return (DONT_WAIT);
|
|
}
|
|
}
|
|
|
|
//--- Jump to driver
|
|
|
|
if( NewDrvr ) { //--- Driver43 (NOTE! Driver43s start at Driver + 8 bytes!!!
|
|
JmpToDrvr( *(ulong *)&devInfoPtr->DevIdent, theDrvr + 8, BZero, HFSBlock); // <SM8>
|
|
|
|
/* Find out where the driver installed itself */
|
|
myPB.scsiDevice = devInfoPtr->DevIdent;
|
|
myPB.scsiCompletion = nil;
|
|
myPB.scsiPBLength = sizeof(SCSI_Driver_PB);
|
|
myPB.scsiFunctionCode = SCSILookupRefNumXref;
|
|
SCSIAction((SCSI_PB *) &myPB);
|
|
|
|
return (myPB.scsiDriver);
|
|
}
|
|
else { //--- Old style driver
|
|
JmpToDrvr( devInfoPtr->DevIdent.targetID, theDrvr, (Ptr) BZero, HFSBlock); //!!! Add At_App_Time
|
|
dRefNum = ~(devInfoPtr->DevIdent.targetID + 32); /* Convert SCSI ID to DRefNum */
|
|
if( GetDCtlEntry(dRefNum) == nil )
|
|
return (DONT_WAIT); /* Something went wrong - didn't install */
|
|
|
|
/* Ok, it installed - register it with the SCSI Manager */
|
|
myPB.scsiDevice = devInfoPtr->DevIdent;
|
|
myPB.scsiPBLength = sizeof(SCSI_Driver_PB);
|
|
myPB.scsiDriver = dRefNum;
|
|
myPB.scsiFunctionCode = SCSICreateRefNumXref;
|
|
SCSIAction((SCSI_PB *) &myPB);
|
|
return (dRefNum);
|
|
}
|
|
}
|
|
|
|
|
|
/*————————————————————————————————————————————————————————————————————————
|
|
SetLoadFlag -
|
|
————————————————————————————————————————————————————————————————————————*/
|
|
|
|
void
|
|
SetLoadFlag( BootInfo * BInfo, DeviceIdent devIdent)
|
|
{
|
|
SCSIGetVirtualIDInfoPB getVIDPB;
|
|
|
|
Clear((char *)&getVIDPB, sizeof(getVIDPB));
|
|
|
|
BInfo->IDmasks[ devIdent.bus] |= (1 << devIdent.targetID);
|
|
|
|
getVIDPB.scsiOldCallID = devIdent.targetID;
|
|
getVIDPB.scsiFunctionCode = SCSIGetVirtualIDInfo;
|
|
SCSIAction((SCSI_PB *) &getVIDPB); // get the info about this ID
|
|
|
|
if ( getVIDPB.scsiExists && (getVIDPB.scsiDevice.bus == devIdent.bus))
|
|
SCSIDrvrs |= 1<<devIdent.targetID;
|
|
}
|
|
|
|
|
|
/*————————————————————————————————————————————————————————————————————————
|
|
ScRead -
|
|
————————————————————————————————————————————————————————————————————————*/
|
|
|
|
short /* !!! OSErr? */
|
|
ScRead(
|
|
DevInfo *devInfoPtr,
|
|
ulong block,
|
|
ulong length,
|
|
ushort blocklen, // <SM12>
|
|
uchar *buffer )
|
|
{
|
|
uchar *cmd;
|
|
|
|
cmd = (uchar *)&(devInfoPtr->ioPB->scsiCDB);
|
|
|
|
/* 10 byte commands are easier but the @#$%^&*! Connor 40s don't return real data from
|
|
the FIRST 10 byte command after a reset or power on. Therefore we issue 6 byte commands
|
|
unless the data requested exceeds the addressing capacity of a 6 byte command.
|
|
|
|
<SM9>
|
|
*/
|
|
|
|
if( (block & 0xFFE00000) || (length & 0xFFFFFF00) ) { // <SM9>
|
|
|
|
cmd[0] = 0x28; /* Properly pumped up 10 byte scsi command */
|
|
cmd[1] = 0; /* !!! Add support for embedded luns? */
|
|
|
|
cmd[2] = block>>24;
|
|
cmd[3] = block>>16;
|
|
cmd[4] = block>>8;
|
|
cmd[5] = block;
|
|
|
|
cmd[6] = 0; /* reserved */
|
|
|
|
cmd[7] = length>>8;
|
|
cmd[8] = length;
|
|
cmd[9] = 0; /* reserved */
|
|
devInfoPtr->ioPB->scsiCDBLength = 10;
|
|
}
|
|
else {
|
|
cmd[0] = 0x8; /* Wimpy 6 byte command */
|
|
|
|
cmd[1] = block>>16 & 0x1f; /* !!! Add support for embedded luns? */
|
|
cmd[2] = block>>8;
|
|
cmd[3] = block;
|
|
|
|
cmd[4] = length;
|
|
cmd[5] = 0; /* reserved */
|
|
devInfoPtr->ioPB->scsiCDBLength = 6;
|
|
}
|
|
|
|
devInfoPtr->ioPB->scsiDataPtr = buffer;
|
|
devInfoPtr->ioPB->scsiDataLength = length * blocklen; /* <SM12> */
|
|
|
|
devInfoPtr->ioPB->scsiFlags = scsiDirectionIn | scsiSIMQNoFreeze | scsiDisableAutosense;
|
|
devInfoPtr->ioPB->scsiIOFlags = scsiNoParityCheck;
|
|
|
|
if( devInfoPtr->IdentMsg == 0 )
|
|
devInfoPtr->ioPB->scsiIOFlags |= scsiDisableSelectWAtn;
|
|
|
|
devInfoPtr->ioPB->scsiDevice = devInfoPtr->DevIdent;
|
|
devInfoPtr->ioPB->scsiFunctionCode = SCSIExecIO;
|
|
devInfoPtr->ioPB->scsiCompletion = nil;
|
|
|
|
devInfoPtr->ioPB->scsiTransferType = scsiTransferPolled;
|
|
|
|
SCSIAction( (SCSI_PB *) devInfoPtr->ioPB);
|
|
|
|
if( devInfoPtr->ioPB->scsiSCSIstatus ) // status will be cleared upon entry to SIMAction
|
|
SCSIAction( (SCSI_PB *) devInfoPtr->ioPB); /* Retry, to clear out unit attention */
|
|
|
|
if( devInfoPtr->ioPB->scsiResult == scsiDataRunError ) // Not all drives are 512/block <LW10>
|
|
devInfoPtr->ioPB->scsiResult = noErr; // We don't discover this until after we load block zero
|
|
|
|
return( !(devInfoPtr->ioPB->scsiResult == noErr && devInfoPtr->ioPB->scsiSCSIstatus == 0) );
|
|
}
|
|
|
|
|
|
/*————————————————————————————————————————————————————————————————————————
|
|
SOpenDriver -
|
|
————————————————————————————————————————————————————————————————————————*/
|
|
|
|
OSErr SOpenDriver(SpBlockPtr sp)
|
|
{
|
|
OSErr err;
|
|
short refnum;
|
|
unsigned int count;
|
|
AuxDCEHandle myDCE;
|
|
DriverHeaderHandle driver;
|
|
unsigned char name [32];
|
|
ParamBlockRec ioPB;
|
|
|
|
driver = (DriverHeaderHandle) sp->spResult;
|
|
HLock((Handle) driver);
|
|
|
|
/* copy the driver name out of the driver header */
|
|
BlockMove((**driver).drvrName, name, 1 + (**driver).drvrName[0]);
|
|
|
|
for( count = 48; count < *(ulong *)UnitNtryCnt ; count+=1 ) {
|
|
refnum = ~count;
|
|
if( GetDCtlEntry(refnum) == 0 )
|
|
break; /* Use the first empty spot we find */
|
|
}
|
|
|
|
if( (err = DrvrInstallResrvMem(*driver, refnum)) != noErr )
|
|
return(err);
|
|
|
|
myDCE = (AuxDCE**)GetDCtlEntry(refnum);
|
|
|
|
(**myDCE).dCtlDriver = (Ptr)driver;
|
|
(**driver).drvrFlags |= 1 << dNeedLock << 8 | 1 << dRAMBased;
|
|
(**myDCE).dCtlFlags = (**driver).drvrFlags;
|
|
(**myDCE).dCtlDelay = (**driver).drvrDelay;
|
|
(**myDCE).dCtlEMask = (**driver).drvrEMask;
|
|
(**myDCE).dCtlMenu = (**driver).drvrMenu;
|
|
(**myDCE).dCtlSlot = sp->spSlot;
|
|
(**myDCE).dCtlSlotId = sp->spID;
|
|
(**myDCE).dCtlExtDev = sp->spExtDev;
|
|
|
|
ioPB.slotDevParam.ioVRefNum = 0;
|
|
ioPB.slotDevParam.ioFlags = 0;
|
|
ioPB.slotDevParam.ioPermssn = 0;
|
|
ioPB.slotDevParam.ioCompletion = 0;
|
|
ioPB.slotDevParam.ioMix = (Ptr)0;
|
|
ioPB.slotDevParam.ioNamePtr = name;
|
|
ioPB.slotDevParam.ioSlot = sp->spSlot;
|
|
ioPB.slotDevParam.ioID = sp->spID;
|
|
PBOpenSync(&ioPB);
|
|
if( ioPB.slotDevParam.ioResult < 0 ) {
|
|
|
|
DisposeHandle((Handle) driver); /* dispose the driver */
|
|
DisposeHandle((Handle) myDCE); /* dispose the DCE */
|
|
((long *)(*(long *)UTableBase))[count] = nil; /* clear the unit table entry */
|
|
}
|
|
return(ioPB.slotDevParam.ioResult);
|
|
|
|
}
|
|
|
|
|
|
/*————————————————————————————————————————————————————————————————————————
|
|
Ck4EjectableVolume -
|
|
————————————————————————————————————————————————————————————————————————*/
|
|
|
|
Boolean
|
|
Ck4EjectableVolume( short drvrRefNum)
|
|
{
|
|
DrvQEl * qElPtr;
|
|
char diskType;
|
|
|
|
qElPtr = (DrvQEl *)(GetDrvQHdr()->qHead);
|
|
|
|
while (qElPtr)
|
|
{
|
|
if (qElPtr->dQRefNum == drvrRefNum) {
|
|
diskType = *(( (char *)qElPtr )-3);
|
|
if ( diskType ==1 || diskType ==2)
|
|
return (true);
|
|
}
|
|
qElPtr = (DrvQEl *)(qElPtr->qLink);
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
|
|
/*————————————————————————————————————————————————————————————————————————
|
|
DummyOldCallRead -
|
|
————————————————————————————————————————————————————————————————————————*/
|
|
|
|
void
|
|
DummyOldCallRead( short scsiID)
|
|
{
|
|
char cdb[6];
|
|
SCSIInstr tib[2];
|
|
char data[0x200];
|
|
short stat, msg;
|
|
|
|
tib[0].scOpcode = scInc;
|
|
tib[0].scParam1 = &data;
|
|
tib[0].scParam2 = 0x200;
|
|
|
|
tib[1].scOpcode = scStop;
|
|
tib[1].scParam1 = 0;
|
|
tib[1].scParam2 = 0;
|
|
|
|
cdb[0] = 0x08;
|
|
cdb[1] = 0x00;
|
|
cdb[2] = 0x00;
|
|
cdb[3] = 0x00;
|
|
cdb[4] = 0x01;
|
|
cdb[5] = 0x00;
|
|
|
|
|
|
SCSIGet();
|
|
|
|
if (SCSISelect( scsiID))
|
|
return;
|
|
|
|
if (!SCSICmd( cdb, 6))
|
|
SCSIRead( (Ptr)tib);
|
|
|
|
SCSIComplete( &stat, &msg, 60*60);
|
|
}
|
|
|