From 14353aa8f494621e510528b7be0e0f4ff82fdefb Mon Sep 17 00:00:00 2001 From: Apple Date: Sun, 10 Aug 2003 07:56:48 +0000 Subject: [PATCH] xnu-201.19.3.tar.gz --- bsd/conf/files | 1 + bsd/conf/version.minor | 2 +- bsd/hfs/hfs_search.c | 176 ++- bsd/hfs/hfscommon/BTree/BTreeScanner.c | 386 +++++ bsd/hfs/hfscommon/headers/BTreeScanner.h | 111 ++ bsd/kern/uipc_socket.c | 11 +- bsd/netat/adsp_stream.c | 2 +- bsd/netat/atp_write.c | 2 +- bsd/netinet/tcp_input.c | 26 +- .../scsi/drvSymbios8xx/Sym8xxClient.cpp | 450 ------ .../scsi/drvSymbios8xx/Sym8xxController.h | 143 -- .../scsi/drvSymbios8xx/Sym8xxExecute.cpp | 1372 ----------------- .../Drivers/scsi/drvSymbios8xx/Sym8xxInit.cpp | 523 ------- .../scsi/drvSymbios8xx/Sym8xxInterface.h | 174 --- .../Drivers/scsi/drvSymbios8xx/Sym8xxMisc.cpp | 73 - iokit/Drivers/scsi/drvSymbios8xx/Sym8xxRegs.h | 556 ------- iokit/Drivers/scsi/drvSymbios8xx/Sym8xxSRB.h | 67 - .../Drivers/scsi/drvSymbios8xx/Sym8xxScript.h | 474 ------ .../scsi/drvSymbios8xx/Sym8xxScript.lis | 993 ------------ .../scsi/drvSymbios8xx/Sym8xxScript.ss | 882 ----------- iokit/Drivers/scsi/drvSymbios8xx/nasmpb | Bin 344008 -> 0 bytes .../IOSCSIParallel/IOSCSIParallelDevice.cpp | 2 +- iokit/Kernel/IOInterruptController.cpp | 29 +- iokit/KernelConfigTables.cpp | 10 +- iokit/conf/files.ppc | 5 - iokit/conf/version.minor | 2 +- libkern/conf/version.minor | 2 +- libsa/conf/version.minor | 2 +- osfmk/conf/kernelversion.minor | 2 +- osfmk/conf/version.minor | 2 +- pexpert/conf/version.minor | 2 +- 31 files changed, 655 insertions(+), 5827 deletions(-) create mode 100644 bsd/hfs/hfscommon/BTree/BTreeScanner.c create mode 100644 bsd/hfs/hfscommon/headers/BTreeScanner.h delete mode 100644 iokit/Drivers/scsi/drvSymbios8xx/Sym8xxClient.cpp delete mode 100644 iokit/Drivers/scsi/drvSymbios8xx/Sym8xxController.h delete mode 100644 iokit/Drivers/scsi/drvSymbios8xx/Sym8xxExecute.cpp delete mode 100644 iokit/Drivers/scsi/drvSymbios8xx/Sym8xxInit.cpp delete mode 100644 iokit/Drivers/scsi/drvSymbios8xx/Sym8xxInterface.h delete mode 100644 iokit/Drivers/scsi/drvSymbios8xx/Sym8xxMisc.cpp delete mode 100644 iokit/Drivers/scsi/drvSymbios8xx/Sym8xxRegs.h delete mode 100644 iokit/Drivers/scsi/drvSymbios8xx/Sym8xxSRB.h delete mode 100644 iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.h delete mode 100644 iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.lis delete mode 100644 iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.ss delete mode 100755 iokit/Drivers/scsi/drvSymbios8xx/nasmpb diff --git a/bsd/conf/files b/bsd/conf/files index 6cb9a0e77..bc6001350 100644 --- a/bsd/conf/files +++ b/bsd/conf/files @@ -484,6 +484,7 @@ bsd/hfs/hfscommon/BTree/BTree.c optional hfs bsd/hfs/hfscommon/BTree/BTreeAllocate.c optional hfs bsd/hfs/hfscommon/BTree/BTreeMiscOps.c optional hfs bsd/hfs/hfscommon/BTree/BTreeNodeOps.c optional hfs +bsd/hfs/hfscommon/BTree/BTreeScanner.c optional hfs bsd/hfs/hfscommon/BTree/BTreeTreeOps.c optional hfs bsd/hfs/hfscommon/Catalog/Catalog.c optional hfs bsd/hfs/hfscommon/Catalog/CatalogIterators.c optional hfs diff --git a/bsd/conf/version.minor b/bsd/conf/version.minor index 00750edc0..b8626c4cf 100644 --- a/bsd/conf/version.minor +++ b/bsd/conf/version.minor @@ -1 +1 @@ -3 +4 diff --git a/bsd/hfs/hfs_search.c b/bsd/hfs/hfs_search.c index e606a3877..df7c233c0 100644 --- a/bsd/hfs/hfs_search.c +++ b/bsd/hfs/hfs_search.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -47,25 +47,13 @@ #include "hfscommon/headers/FileMgrInternal.h" #include "hfscommon/headers/CatalogPrivate.h" #include "hfscommon/headers/HFSUnicodeWrappers.h" - - -/* Private description used in hfs_search */ -/* - * ============ W A R N I N G ! ============ - * DO NOT INCREASE THE SIZE OF THIS STRUCT! - * It must match the size of the opaque - * searchstate struct (in sys/attr.h). - */ -struct SearchState { - long searchBits; - BTreeIterator btreeIterator; -}; -typedef struct SearchState SearchState; +#include "hfscommon/headers/BTreesPrivate.h" +#include "hfscommon/headers/BTreeScanner.h" static int UnpackSearchAttributeBlock(struct vnode *vp, struct attrlist *alist, searchinfospec_t *searchInfo, void *attributeBuffer); -Boolean CheckCriteria(ExtendedVCB *vcb, const SearchState *searchState, +Boolean CheckCriteria(ExtendedVCB *vcb, u_long searchBits, struct attrlist *attrList, CatalogNodeData *cnp, CatalogKey *key, searchinfospec_t *searchInfo1, searchinfospec_t *searchInfo2); @@ -129,11 +117,7 @@ struct vop_searchfs_args *ap; /* struct searchstate *a_searchstate; */ { - CatalogNodeData cnode; - BTreeKey *key; - FSBufferDescriptor btRecord; FCB* catalogFCB; - SearchState *searchState; searchinfospec_t searchInfo1; searchinfospec_t searchInfo2; void *attributesBuffer; @@ -143,7 +127,13 @@ struct vop_searchfs_args *ap; /* u_long fixedBlockSize; u_long eachReturnBufferSize; struct proc *p = current_proc(); - u_long nodesToCheck = 30; /* After we search 30 nodes we must give up time */ + CatalogNodeData myCNodeData; + CatalogNodeData * myCNodeDataPtr; + CatalogKey * myCurrentKeyPtr; + CatalogRecord * myCurrentDataPtr; + CatPosition * myCatPositionPtr; + BTScanState myBTScanState; + Boolean timerExpired = false; u_long lastNodeNum = 0XFFFFFFFF; ExtendedVCB *vcb = VTOVCB(ap->a_vp); int err = E_NONE; @@ -160,19 +150,6 @@ struct vop_searchfs_args *ap; /* return (EINVAL); isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord); - searchState = (SearchState *)ap->a_searchstate; - - /* - * Check if this is the first time we are being called. - * If it is, allocate SearchState and we'll move it to the users space on exit - */ - if ( ap->a_options & SRCHFS_START ) { - bzero( (caddr_t)searchState, sizeof(SearchState) ); - operation = kBTreeFirstRecord; - ap->a_options &= ~SRCHFS_START; - } else { - operation = kBTreeCurrentRecord; - } /* UnPack the search boundries, searchInfo1, searchInfo2 */ err = UnpackSearchAttributeBlock( ap->a_vp, ap->a_searchattrs, &searchInfo1, ap->a_searchparams1 ); @@ -180,16 +157,6 @@ struct vop_searchfs_args *ap; /* err = UnpackSearchAttributeBlock( ap->a_vp, ap->a_searchattrs, &searchInfo2, ap->a_searchparams2 ); if (err) return err; - btRecord.itemCount = 1; - if (isHFSPlus) { - btRecord.itemSize = sizeof(cnode); - btRecord.bufferAddress = &cnode; - } else { - btRecord.itemSize = sizeof(HFSCatalogFile); - btRecord.bufferAddress = &cnode.cnd_extra; - } - catalogFCB = VTOFCB( vcb->catalogRefNum ); - key = (BTreeKey*) &(searchState->btreeIterator.key); fixedBlockSize = sizeof(u_long) + AttributeBlockSize( ap->a_returnattrs ); /* u_long for length longword */ eachReturnBufferSize = fixedBlockSize; @@ -205,41 +172,102 @@ struct vop_searchfs_args *ap; /* goto ExitThisRoutine; }; + catalogFCB = VTOFCB( vcb->catalogRefNum ); + myCurrentKeyPtr = NULL; + myCurrentDataPtr = NULL; + myCatPositionPtr = (CatPosition *)ap->a_searchstate; + + if (ap->a_options & SRCHFS_START) { + /* Starting a new search. */ + ap->a_options &= ~SRCHFS_START; + bzero( (caddr_t)myCatPositionPtr, sizeof( *myCatPositionPtr ) ); + err = BTScanInitialize(catalogFCB, 0, 0, 0, kCatSearchBufferSize, &myBTScanState); + } else { + /* Resuming a search. */ + err = BTScanInitialize(catalogFCB, myCatPositionPtr->nextNode, + myCatPositionPtr->nextRecord, + myCatPositionPtr->recordsFound, + kCatSearchBufferSize, + &myBTScanState); +#if 0 + /* Make sure Catalog hasn't changed. */ + if (err == 0 + && myCatPositionPtr->writeCount != myBTScanState.btcb->writeCount) { + myCatPositionPtr->writeCount = myBTScanState.btcb->writeCount; + err = EBUSY; /* catChangedErr */ + } +#endif + } + + /* Unlock catalog b-tree */ + (void) hfs_metafilelocking(VTOHFS(ap->a_vp), kHFSCatalogFileID, LK_RELEASE, p); + if (err) + goto ExitThisRoutine; + /* - * Iterate over all the catalog btree records + * Check all the catalog btree records... + * return the attributes for matching items */ - - err = BTIterateRecord( catalogFCB, operation, &(searchState->btreeIterator), &btRecord, &recordSize ); + for (;;) { + struct timeval myCurrentTime; + struct timeval myElapsedTime; + + err = BTScanNextRecord(&myBTScanState, timerExpired, + (void **)&myCurrentKeyPtr, (void **)&myCurrentDataPtr, + NULL); + if (err) + break; - while( err == E_NONE ) { - if (!isHFSPlus) - CopyCatalogNodeData(vcb, (CatalogRecord*)&cnode.cnd_extra, &cnode); - - if ( CheckCriteria( vcb, searchState, ap->a_options, ap->a_searchattrs, &cnode, - (CatalogKey *)key, &searchInfo1, &searchInfo2 ) && - CheckAccess(&cnode, (CatalogKey *)key, ap->a_uio->uio_procp)) { - err = InsertMatch(ap->a_vp, ap->a_uio, &cnode, (CatalogKey *)key, - ap->a_returnattrs, attributesBuffer, variableBuffer, - eachReturnBufferSize, ap->a_nummatches); - if ( err != E_NONE ) - break; + if ( isHFSPlus ) { + // HFSPlus vols have CatalogRecords that map exactly to CatalogNodeData so there is no need + // to copy. + myCNodeDataPtr = (CatalogNodeData *) myCurrentDataPtr; + } else { + CopyCatalogNodeData( vcb, myCurrentDataPtr, &myCNodeData ); + myCNodeDataPtr = &myCNodeData; } - - err = BTIterateRecord( catalogFCB, kBTreeNextRecord, &(searchState->btreeIterator), &btRecord, &recordSize ); - - if ( *(ap->a_nummatches) >= ap->a_maxmatches ) + + if (CheckCriteria(vcb, ap->a_options, ap->a_searchattrs, myCNodeDataPtr, + myCurrentKeyPtr, &searchInfo1, &searchInfo2) && + CheckAccess(myCNodeDataPtr, myCurrentKeyPtr, ap->a_uio->uio_procp)) { + + err = InsertMatch(ap->a_vp, ap->a_uio, myCNodeDataPtr, + myCurrentKeyPtr, ap->a_returnattrs, + attributesBuffer, variableBuffer, + eachReturnBufferSize, ap->a_nummatches); + if (err) { + /* + * The last match didn't fit so come back + * to this record on the next trip. + */ + --myBTScanState.recordsFound; + --myBTScanState.recordNum; break; + } + if (*(ap->a_nummatches) >= ap->a_maxmatches) + break; + } - if ( searchState->btreeIterator.hint.nodeNum != lastNodeNum ) { - lastNodeNum = searchState->btreeIterator.hint.nodeNum; - if ( --nodesToCheck == 0 ) - break; /* We must leave the kernel to give up time */ + /* + * Check our elapsed time and bail if we've hit the max. + * The idea here is to throttle the amount of time we + * spend in the kernel. + */ + myCurrentTime = time; + timersub(&myCurrentTime, &myBTScanState.startTime, &myElapsedTime); + /* Note: assumes kMaxMicroSecsInKernel is less than 1,000,000 */ + if (myElapsedTime.tv_sec > 0 + || myElapsedTime.tv_usec >= kMaxMicroSecsInKernel) { + timerExpired = true; } } - /* Unlock catalog b-tree */ - (void) hfs_metafilelocking( VTOHFS(ap->a_vp), kHFSCatalogFileID, LK_RELEASE, p ); + /* Update catalog position */ + myCatPositionPtr->writeCount = myBTScanState.btcb->writeCount; + BTScanTerminate(&myBTScanState, &myCatPositionPtr->nextNode, + &myCatPositionPtr->nextRecord, + &myCatPositionPtr->recordsFound); if ( err == E_NONE ) { err = EAGAIN; /* signal to the user to call searchfs again */ @@ -250,12 +278,14 @@ struct vop_searchfs_args *ap; /* err = ENOBUFS; } else if ( err == btNotFound ) { err = E_NONE; /* the entire disk has been searched */ + } else if ( err == fsBTTimeOutErr ) { + err = EAGAIN; } ExitThisRoutine: FREE( attributesBuffer, M_TEMP ); - return( err ); + return (MacToVFSError(err)); } @@ -330,7 +360,7 @@ CheckAccess(CatalogNodeData *cnp, CatalogKey *key, struct proc *p) } Boolean -CheckCriteria( ExtendedVCB *vcb, const SearchState *searchState, u_long searchBits, +CheckCriteria( ExtendedVCB *vcb, u_long searchBits, struct attrlist *attrList, CatalogNodeData *cnp, CatalogKey *key, searchinfospec_t *searchInfo1, searchinfospec_t *searchInfo2 ) { @@ -395,11 +425,11 @@ CheckCriteria( ExtendedVCB *vcb, const SearchState *searchState, u_long searchBi /* Now that we have a record worth searching, see if it matches the search attributes */ if (cnp->cnd_type == kCatalogFileNode) { - if ((attrList->dirattr & ~ATTR_FILE_VALIDMASK) != 0) { /* attr we do know about */ + if ((attrList->fileattr & ~ATTR_FILE_VALIDMASK) != 0) { /* attr we do know about */ matched = false; goto TestDone; } - else if ((attrList->dirattr & ATTR_FILE_VALIDMASK) != 0) { + else if ((attrList->fileattr & ATTR_FILE_VALIDMASK) != 0) { searchAttributes = attrList->fileattr; /* File logical length (data fork) */ diff --git a/bsd/hfs/hfscommon/BTree/BTreeScanner.c b/bsd/hfs/hfscommon/BTree/BTreeScanner.c new file mode 100644 index 000000000..014069807 --- /dev/null +++ b/bsd/hfs/hfscommon/BTree/BTreeScanner.c @@ -0,0 +1,386 @@ +/* + * Copyright (c) 1996-2002 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * @(#)BTreeScanner.c + */ +#include + +#include "../headers/BTreeScanner.h" + +static int FindNextLeafNode( BTScanState *scanState, Boolean avoidIO ); +static int ReadMultipleNodes( BTScanState *scanState ); + + +//_________________________________________________________________________________ +// +// Routine: BTScanNextRecord +// +// Purpose: Return the next leaf record in a scan. +// +// Inputs: +// scanState Scanner's current state +// avoidIO If true, don't do any I/O to refill the buffer +// +// Outputs: +// key Key of found record (points into buffer) +// data Data of found record (points into buffer) +// dataSize Size of data in found record +// +// Result: +// noErr Found a valid record +// btNotFound No more records +// ??? Needed to do I/O to get next node, but avoidIO set +// +// Notes: +// This routine returns pointers to the found record's key and data. It +// does not copy the key or data to a caller-supplied buffer (like +// GetBTreeRecord would). The caller must not modify the key or data. +//_________________________________________________________________________________ + +int BTScanNextRecord( BTScanState * scanState, + Boolean avoidIO, + void * * key, + void * * data, + u_int32_t * dataSize ) +{ + int err; + u_int16_t dataSizeShort; + + err = noErr; + + // + // If this is the first call, there won't be any nodes in the buffer, so go + // find the first first leaf node (if any). + // + if ( scanState->nodesLeftInBuffer == 0 ) + { + err = FindNextLeafNode( scanState, avoidIO ); + } + + while ( err == noErr ) + { + // See if we have a record in the current node + err = GetRecordByIndex( scanState->btcb, scanState->currentNodePtr, + scanState->recordNum, (KeyPtr *) key, + (UInt8 **) data, &dataSizeShort ); + + if ( err == noErr ) + { + ++scanState->recordsFound; + ++scanState->recordNum; + if (dataSize != NULL) + *dataSize = dataSizeShort; + return noErr; + } + else if (err > 0) + { + // We didn't get the node through the cache, so we can't invalidate it. + //XXX Should we do something else to avoid seeing the same record again? + return err; + } + + // We're done with the current node. See if we've returned all the records + if ( scanState->recordsFound >= scanState->btcb->leafRecords ) + { + return btNotFound; + } + + // Move to the first record of the next leaf node + scanState->recordNum = 0; + err = FindNextLeafNode( scanState, avoidIO ); + } + + // + // If we got an EOF error from FindNextLeafNode, then there are no more leaf + // records to be found. + // + if ( err == fsEndOfIterationErr ) + err = btNotFound; + + return err; + +} /* BTScanNextRecord */ + + +//_________________________________________________________________________________ +// +// Routine: FindNextLeafNode +// +// Purpose: Point to the next leaf node in the buffer. Read more nodes +// into the buffer if needed (and allowed). +// +// Inputs: +// scanState Scanner's current state +// avoidIO If true, don't do any I/O to refill the buffer +// +// Result: +// noErr Found a valid record +// fsEndOfIterationErr No more nodes in file +// ??? Needed to do I/O to get next node, but avoidIO set +//_________________________________________________________________________________ + +static int FindNextLeafNode( BTScanState *scanState, Boolean avoidIO ) +{ + int err; + + err = noErr; // Assume everything will be OK + + while ( 1 ) + { + if ( scanState->nodesLeftInBuffer == 0 ) + { + // Time to read some more nodes into the buffer + if ( avoidIO ) + { + return fsBTTimeOutErr; + } + else + { + // read some more nodes into buffer + err = ReadMultipleNodes( scanState ); + if ( err != noErr ) + break; + } + } + else + { + // Adjust the node counters and point to the next node in the buffer + ++scanState->nodeNum; + --scanState->nodesLeftInBuffer; + + // If we've looked at all nodes in the tree, then we're done + if ( scanState->nodeNum >= scanState->btcb->totalNodes ) + return fsEndOfIterationErr; + + if ( scanState->nodesLeftInBuffer == 0 ) + { + scanState->recordNum = 0; + continue; + } + + (u_int8_t *) scanState->currentNodePtr += scanState->btcb->nodeSize; + } + + // Make sure this is a valid node + if ( CheckNode( scanState->btcb, scanState->currentNodePtr ) != noErr ) + { + continue; + } + + if ( scanState->currentNodePtr->kind == kBTLeafNode ) + break; + } + + return err; + +} /* FindNextLeafNode */ + + +//_________________________________________________________________________________ +// +// Routine: ReadMultipleNodes +// +// Purpose: Read one or more nodes into the buffer. +// +// Inputs: +// theScanStatePtr Scanner's current state +// +// Result: +// noErr One or nodes were read +// fsEndOfIterationErr No nodes left in file, none in buffer +//_________________________________________________________________________________ + +static int ReadMultipleNodes( BTScanState *theScanStatePtr ) +{ + int myErr = E_NONE; + BTreeControlBlockPtr myBTreeCBPtr; + daddr_t myPhyBlockNum; + u_int32_t myBufferSize; + struct vnode * myDevPtr; + int myBlockRun; + u_int32_t myBlocksInBufferCount; + + // release old buffer if we have one + if ( theScanStatePtr->bufferPtr != NULL ) + { + theScanStatePtr->bufferPtr->b_flags |= (B_INVAL | B_AGE); + brelse( theScanStatePtr->bufferPtr ); + theScanStatePtr->bufferPtr = NULL; + theScanStatePtr->currentNodePtr = NULL; + } + + myBTreeCBPtr = theScanStatePtr->btcb; + + // map logical block in catalog btree file to physical block on volume + myErr = VOP_BMAP( myBTreeCBPtr->fileRefNum, theScanStatePtr->nodeNum, + &myDevPtr, &myPhyBlockNum, &myBlockRun ); + if ( myErr != E_NONE ) + { + goto ExitThisRoutine; + } + + // bmap block run gives us the remaining number of valid blocks (number of blocks + // minus the first). so if there are 10 valid blocks our run number will be 9. + // blocks, in our case is the same as nodes (both are 4K) + myBlocksInBufferCount = (theScanStatePtr->bufferSize / myBTreeCBPtr->nodeSize ); + myBufferSize = theScanStatePtr->bufferSize; + if ( (myBlockRun + 1) < myBlocksInBufferCount ) + { + myBufferSize = (myBlockRun + 1) * myBTreeCBPtr->nodeSize; + } + + // now read blocks from the device + myErr = bread( myDevPtr, + myPhyBlockNum, + myBufferSize, + NOCRED, + &theScanStatePtr->bufferPtr ); + if ( myErr != E_NONE ) + { + goto ExitThisRoutine; + } + + theScanStatePtr->nodesLeftInBuffer = theScanStatePtr->bufferPtr->b_bcount / theScanStatePtr->btcb->nodeSize; + theScanStatePtr->currentNodePtr = (BTNodeDescriptor *) theScanStatePtr->bufferPtr->b_data; + +ExitThisRoutine: + return myErr; + +} /* ReadMultipleNodes */ + + + +//_________________________________________________________________________________ +// +// Routine: BTScanInitialize +// +// Purpose: Prepare to start a new BTree scan, or resume a previous one. +// +// Inputs: +// btreeFile The B-Tree's file control block +// startingNode Initial node number +// startingRecord Initial record number within node +// recordsFound Number of valid records found so far +// bufferSize Size (in bytes) of buffer +// +// Outputs: +// scanState Scanner's current state; pass to other scanner calls +// +// Notes: +// To begin a new scan and see all records in the B-Tree, pass zeroes for +// startingNode, startingRecord, and recordsFound. +// +// To resume a scan from the point of a previous BTScanTerminate, use the +// values returned by BTScanTerminate as input for startingNode, startingRecord, +// and recordsFound. +// +// When resuming a scan, the caller should check the B-tree's write count. If +// it is different from the write count when the scan was terminated, then the +// tree may have changed and the current state may be incorrect. In particular, +// you may see some records more than once, or never see some records. Also, +// the scanner may not be able to detect when all leaf records have been seen, +// and will have to scan through many empty nodes. +// +// XXXÊPerhaps the write count should be managed by BTScanInitialize and +// XXX BTScanTerminate? This would avoid the caller having to peek at +// XXX internal B-Tree structures. +//_________________________________________________________________________________ + +int BTScanInitialize( const FCB * btreeFile, + u_int32_t startingNode, + u_int32_t startingRecord, + u_int32_t recordsFound, + u_int32_t bufferSize, + BTScanState * scanState ) +{ + BTreeControlBlock *btcb; + + // + // Make sure this is a valid B-Tree file + // + btcb = (BTreeControlBlock *) btreeFile->fcbBTCBPtr; + if (btcb == NULL) + return fsBTInvalidFileErr; + + // + // Make sure buffer size is big enough, and a multiple of the + // B-Tree node size + // + if ( bufferSize < btcb->nodeSize ) + return paramErr; + bufferSize = (bufferSize / btcb->nodeSize) * btcb->nodeSize; + + // + // Set up the scanner's state + // + scanState->bufferSize = bufferSize; + scanState->bufferPtr = NULL; + scanState->btcb = btcb; + scanState->nodeNum = startingNode; + scanState->recordNum = startingRecord; + scanState->currentNodePtr = NULL; + scanState->nodesLeftInBuffer = 0; // no nodes currently in buffer + scanState->recordsFound = recordsFound; + scanState->startTime = time; // initialize our throttle + + return noErr; + +} /* BTScanInitialize */ + + +//_________________________________________________________________________________ +// +// Routine: BTScanTerminate +// +// Purpose: Return state information about a scan so that it can be resumed +// later via BTScanInitialize. +// +// Inputs: +// scanState Scanner's current state +// +// Outputs: +// nextNode Node number to resume a scan (pass to BTScanInitialize) +// nextRecord Record number to resume a scan (pass to BTScanInitialize) +// recordsFound Valid records seen so far (pass to BTScanInitialize) +//_________________________________________________________________________________ + +int BTScanTerminate( BTScanState * scanState, + u_int32_t * startingNode, + u_int32_t * startingRecord, + u_int32_t * recordsFound ) +{ + *startingNode = scanState->nodeNum; + *startingRecord = scanState->recordNum; + *recordsFound = scanState->recordsFound; + + if ( scanState->bufferPtr != NULL ) + { + scanState->bufferPtr->b_flags |= (B_INVAL | B_AGE); + brelse( scanState->bufferPtr ); + scanState->bufferPtr = NULL; + scanState->currentNodePtr = NULL; + } + + return noErr; + +} /* BTScanTerminate */ + + diff --git a/bsd/hfs/hfscommon/headers/BTreeScanner.h b/bsd/hfs/hfscommon/headers/BTreeScanner.h new file mode 100644 index 000000000..b537bccfd --- /dev/null +++ b/bsd/hfs/hfscommon/headers/BTreeScanner.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1996-2002 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * @(#)BTreeScanner.h + */ + +#ifndef _BTREESCANNER_H_ +#define _BTREESCANNER_H_ + +#include + +#include "FileMgrInternal.h" +#include "BTreesPrivate.h" + +// amount of time we are allowed to process a catalog search (in µ secs) +// NOTE - code assumes kMaxMicroSecsInKernel is less than 1,000,000 +// jertodo - what should we set this to? +enum { kMaxMicroSecsInKernel = (1000 * 100) }; // 1 tenth of a second + +// btree node scanner buffer size. at 32K we get 8 nodes. this is the size used +// in Mac OS 9 +enum { kCatSearchBufferSize = (32 * 1024) }; + + +/* + * ============ W A R N I N G ! ============ + * DO NOT INCREASE THE SIZE OF THIS STRUCT! + * It must be less than or equal to the size of + * the opaque searchstate struct (in sys/attr.h). + */ +/* Private description used in hfs_search */ +struct CatPosition +{ + u_int32_t writeCount; /* The BTree's write count (to see if the catalog writeCount */ + /* changed since the last search). If 0, the rest */ + /* of the record is invalid, start from beginning. */ + u_int32_t nextNode; /* node number to resume search */ + u_int32_t nextRecord; /* record number to resume search */ + u_int32_t recordsFound; /* number of leaf records seen so far */ +}; +typedef struct CatPosition CatPosition; + + +/* + BTScanState - This structure is used to keep track of the current state + of a BTree scan. It contains both the dynamic state information (like + the current node number and record number) and information that is static + for the duration of a scan (such as buffer pointers). + + NOTE: recordNum may equal or exceed the number of records in the node + number nodeNum. If so, then the next attempt to get a record will move + to a new node number. +*/ +struct BTScanState +{ + // The following fields are set up once at initialization time. + // They are not changed during a scan. + u_int32_t bufferSize; + struct buf * bufferPtr; + BTreeControlBlock * btcb; + + // The following fields are the dynamic state of the current scan. + u_int32_t nodeNum; // zero is first node + u_int32_t recordNum; // zero is first record + BTNodeDescriptor * currentNodePtr; // points to current node within buffer + u_int32_t nodesLeftInBuffer; // number of valid nodes still in the buffer + u_int32_t recordsFound; // number of leaf records seen so far + struct timeval startTime; // time we started catalog search +}; +typedef struct BTScanState BTScanState; + + +/* *********************** PROTOTYPES *********************** */ + +int BTScanInitialize( const FCB * btreeFile, + u_int32_t startingNode, + u_int32_t startingRecord, + u_int32_t recordsFound, + u_int32_t bufferSize, + BTScanState * scanState ); + +int BTScanNextRecord( BTScanState * scanState, + Boolean avoidIO, + void * * key, + void * * data, + u_int32_t * dataSize ); + +int BTScanTerminate( BTScanState * scanState, + u_int32_t * startingNode, + u_int32_t * startingRecord, + u_int32_t * recordsFound ); + +#endif /* !_BTREESCANNER_H_ */ diff --git a/bsd/kern/uipc_socket.c b/bsd/kern/uipc_socket.c index c5e6b4891..3d19b403c 100644 --- a/bsd/kern/uipc_socket.c +++ b/bsd/kern/uipc_socket.c @@ -1401,8 +1401,11 @@ dontblock: *mp = (struct mbuf *)0; } else { m->m_nextpkt = 0; - ml = m; - m = m->m_next; + if (ml != 0) + ml->m_next = m; + ml = m; + so->so_rcv.sb_mb = m = m->m_next; + ml->m_next = 0; } if (m) m->m_nextpkt = nextrecord; @@ -1447,8 +1450,6 @@ dontblock: break; if (ml) { - so->so_rcv.sb_mb = ml->m_next; - ml->m_next = (struct mbuf *)0; m_freem_list(free_list); } error = sbwait(&so->so_rcv); @@ -1467,8 +1468,6 @@ dontblock: } } if (ml) { - so->so_rcv.sb_mb = ml->m_next; - ml->m_next = (struct mbuf *)0; m_freem_list(free_list); } diff --git a/bsd/netat/adsp_stream.c b/bsd/netat/adsp_stream.c index c3ea0ae2f..5aa9d3071 100644 --- a/bsd/netat/adsp_stream.c +++ b/bsd/netat/adsp_stream.c @@ -540,7 +540,7 @@ adspAssignSocket(gref, flag) int s; sMax = flag ? DDP_SOCKET_LAST-46 : DDP_SOCKET_LAST-6; - sMin = DDP_SOCKET_1st_DYNAMIC-64; + sMin = DDP_SOCKET_1st_DYNAMIC; ATDISABLE(s, adspall_lock); for (inputC=255, sVal=sMax; sVal >= sMin; sVal--) { diff --git a/bsd/netat/atp_write.c b/bsd/netat/atp_write.c index 38d3954a7..4fea05d13 100644 --- a/bsd/netat/atp_write.c +++ b/bsd/netat/atp_write.c @@ -901,7 +901,7 @@ l_send: } /* atp_unpack_bdsp */ #define ATP_SOCKET_LAST (DDP_SOCKET_LAST-6) -#define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC-64) +#define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC) static unsigned int sNext = 0; int atp_bind(gref, sVal, flag) diff --git a/bsd/netinet/tcp_input.c b/bsd/netinet/tcp_input.c index 92f3697c2..008e01fe4 100644 --- a/bsd/netinet/tcp_input.c +++ b/bsd/netinet/tcp_input.c @@ -1176,13 +1176,20 @@ findpcb: } else { #endif /* INET6 */ - /* - * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN - * in_broadcast() should never return true on a received - * packet with M_BCAST not set. - */ - if (m->m_flags & (M_BCAST|M_MCAST) || - IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) + /* + * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN + * in_broadcast() should never return true on a received + * packet with M_BCAST not set. + * + * Packets with a multicast source address should also + * be discarded. + */ + if (m->m_flags & (M_BCAST|M_MCAST)) + goto drop; + if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || + IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || + ip->ip_src.s_addr == htonl(INADDR_BROADCAST) || + in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) goto drop; MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME, M_NOWAIT); @@ -2398,7 +2405,10 @@ dropwithreset: goto drop; /* anycast check is done at the top */ } else #endif /* INET6 */ - if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) + if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || + IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || + ip->ip_src.s_addr == htonl(INADDR_BROADCAST) || + in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) goto drop; #if TCPDEBUG if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) { diff --git a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxClient.cpp b/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxClient.cpp deleted file mode 100644 index 72a6ebe1f..000000000 --- a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxClient.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* Sym8xxClient.m created by russb2 on Sat 30-May-1998 */ - -#include "Sym8xxController.h" - -extern pmap_t kernel_pmap; - - -/*-----------------------------------------------------------------------------* - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::executeCommand( IOSCSIParallelCommand *scsiCommand ) -{ - SRB *srb = NULL; - SCSICDBInfo scsiCDB; - SCSITargetLun targetLun; - Nexus *nexus; - Nexus *nexusPhys; - UInt32 len; - bool isWrite; - - srb = (SRB *) scsiCommand->getCommandData(); - bzero( srb, sizeof(SRB) ); - - srb->srbPhys = (SRB *) pmap_extract( kernel_pmap, (vm_offset_t) srb ); - srb->scsiCommand = scsiCommand; - - scsiCommand->getCDB( &scsiCDB ); - scsiCommand->getTargetLun( &targetLun ); - - nexus = &srb->nexus; - nexusPhys = &srb->srbPhys->nexus; - - srb->target = targetLun.target; - srb->lun = targetLun.lun; - srb->srbCDBFlags = scsiCDB.cdbFlags; - - /* - * Setup the Nexus struct. This part of the SRB is read/written both by the - * script and the driver. - */ - nexus->targetParms.target = srb->target; - -// printf( "SCSI(Symbios8xx): executeCommand: T/L = %d:%d Cmd = %08x CmdType = %d\n\r", -// targetLun.target, targetLun.lun, (int)scsiCommand, scsiCommand->getCmdType() ); - - switch ( scsiCommand->getCmdType() ) - { - case kSCSICommandAbort: - case kSCSICommandAbortAll: - case kSCSICommandDeviceReset: - Sym8xxAbortCommand( scsiCommand ); - return; - - default: - ; - } - - /* - * Set client data buffer pointers in the SRB - */ - scsiCommand->getPointers( &srb->xferDesc, &srb->xferCount, &isWrite ); - - srb->directionMask = (isWrite) ? 0x00000000 :0x01000000; - - nexus->cdb.ppData = OSSwapHostToLittleInt32((UInt32)&nexusPhys->cdbData); - - len = scsiCDB.cdbLength; - - nexus->cdb.length = OSSwapHostToLittleInt32( len ); - nexus->cdbData = scsiCDB.cdb; - - Sym8xxCalcMsgs( scsiCommand ); - - /* - * Setup initial data transfer list (SGList) - */ - nexus->ppSGList = (SGEntry *)OSSwapHostToLittleInt32((UInt32)&nexusPhys->sgListData[2]); - Sym8xxUpdateSGList( srb ); - - Sym8xxStartSRB( srb ); -} - - -/*-----------------------------------------------------------------------------* - * This routine queues an SRB to reset the SCSI Bus - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::resetCommand( IOSCSIParallelCommand *scsiCommand ) -{ - SRB *srb; - -// printf( "SCSI(Symbios8xx): resetCommand\n\r" ); - - srb = (SRB *) scsiCommand->getCommandData(); - bzero( srb, sizeof(SRB) ); - - srb->srbPhys = (SRB *) pmap_extract( kernel_pmap, (vm_offset_t) srb ); - srb->scsiCommand = scsiCommand; - - Sym8xxSCSIBusReset( srb ); -} - -/*-----------------------------------------------------------------------------* - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::cancelCommand( IOSCSIParallelCommand *scsiCommand ) -{ - IOSCSIParallelCommand *origCommand; - SRB *srb; - SCSITargetLun targetLun; - SCSIResults scsiResults; - - origCommand = scsiCommand->getOriginalCmd(); - srb = (SRB *)origCommand->getCommandData(); - - switch ( origCommand->getCmdType() ) - { - case kSCSICommandAbort: - case kSCSICommandAbortAll: - case kSCSICommandDeviceReset: - if ( abortSRB == srb ) - { - SCRIPT_VAR(R_ld_AbortBdr_mailbox) = 0; - abortSRB = 0; - - origCommand->complete(); - } - break; - - default: - - if ( adapter->nexusPtrsVirt[srb->nexus.tag] == &srb->nexus ) - { - adapter->nexusPtrsVirt[srb->nexus.tag] = (Nexus *) -1; - adapter->nexusPtrsPhys[srb->nexus.tag] = (Nexus *) -1; - - origCommand->complete(); - } - else - { - origCommand->getTargetLun( &targetLun ); - origCommand->complete(); - - IOLog( "SCSI(Symbios8xx): Aborted SRB not found - T/L = %d:%d\n\r", targetLun.target, targetLun.lun ); - } - } - - bzero( &scsiResults, sizeof(scsiResults) ); - scsiCommand->setResults( &scsiResults ); - scsiCommand->complete(); -} - -/*-----------------------------------------------------------------------------* - * - * - * - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxAbortCommand( IOSCSIParallelCommand *scsiCommand ) -{ - SRB *srb; - SCSICDBInfo scsiCDB; - SCSITargetLun targetLun; - - - scsiCommand->getTargetLun( &targetLun ); - - switch ( scsiCommand->getCmdType() ) - { - case kSCSICommandAbort: - srb = (SRB *)scsiCommand->getOriginalCmd()->getCommandData(); - Sym8xxCancelMailBox( &srb->srbPhys->nexus ); - break; - - case kSCSICommandAbortAll: - Sym8xxCancelMailBox( targetLun.target, targetLun.lun, false ); - break; - - case kSCSICommandDeviceReset: - Sym8xxCancelMailBox( targetLun.target, (UInt32) -1, false ); - break; - - default: - ; - } - - if ( abortSRB ) - { - abortReqPending = true; - - rescheduleCommand( scsiCommand ); - disableCommands(); - return; - } - - scsiCommand->getCDB( &scsiCDB ); - - srb = (SRB *) scsiCommand->getCommandData(); - - srb->nexus.msgData[0] = srb->lun | ((srb->srbCDBFlags & kCDBFlagsNoDisconnect ) ? 0x80 : 0xC0); - - if ( scsiCDB.cdbTagMsg != 0 ) - { - srb->nexus.tag = scsiCDB.cdbTag + 128; - srb->nexus.msgData[1] = srb->nexus.tag; - } - else - { - srb->nexus.tag = ((UInt32)srb->target << 3) | srb->lun; - srb->nexus.msgData[1] = 0; - } - srb->tag = srb->nexus.tag; - - srb->nexus.msgData[2] = scsiCDB.cdbAbortMsg; - - Sym8xxAbortBdr( srb ); -} - - -/*-----------------------------------------------------------------------------* - * This routine creates SCSI messages to send during the initial connection - * to the target. It is called during client request processing and also by - * the I/O thread when a request sense operation is required. - * - * Outbound messages are setup in the MsgOut buffer in the Nexus structure of - * the SRB. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxCalcMsgs( IOSCSIParallelCommand *scsiCommand ) -{ - SRB *srb; - Nexus *nexus; - Nexus *nexusPhys; - UInt32 msgIndex; - SCSICDBInfo scsiCDB; - SCSITargetParms targetParms; - UInt32 i; - UInt32 tw; - - - srb = (SRB *)scsiCommand->getCommandData(); - nexus = &srb->nexus; - nexusPhys = &srb->srbPhys->nexus; - - scsiCommand->getCDB( &scsiCDB ); - - /* - * Setup Identify message - */ - msgIndex = 0; - nexus->msg.ppData = OSSwapHostToLittleInt32((UInt32)&nexusPhys->msgData); - nexus->msgData[msgIndex++] = srb->lun | (( scsiCDB.cdbFlags & kCDBFlagsNoDisconnect ) ? 0x80 : 0xC0); - - /* - * Allocate tag for request. - * - * For non-tagged requests a pseudo-tag is created consisting of target*16+lun. For tagged - * requests a tag in the range 128-255 is allocated. - * - * If a pseudo-tag is inuse for a non-tagged command or there are no tags available for - * a tagged request, then the command is blocked until a tag becomes available. - * - * Note: If we are being called during request sense processing (srbState != ksrbStateCDBDone) - * then a tag has already been allocated to the request. - */ - if ( scsiCDB.cdbTagMsg != 0 ) - { - nexus->msgData[msgIndex++] = scsiCDB.cdbTagMsg; - nexus->msgData[msgIndex++] = srb->tag = srb->nexus.tag = scsiCDB.cdbTag + 128; - } - else - { - srb->tag = srb->nexus.tag = ((UInt32)srb->target << 3) | srb->lun; - } - /* - * Setup to negotiate for Wide (16-bit) data transfers - * - * Note: There is no provision to negotiate back to narrow transfers although - * SCSI does support this. - */ - - scsiCommand->getDevice(kIOSCSIParallelDevice)->getTargetParms( &targetParms ); - - if ( scsiCDB.cdbFlags & (kCDBFlagsNegotiateWDTR | kCDBFlagsNegotiateSDTR) ) - { - negotiateWDTRComplete = negotiateSDTRComplete = false; - } - - if ( scsiCDB.cdbFlags & kCDBFlagsNegotiateWDTR ) - { - nexus->msgData[msgIndex++] = kSCSIMsgExtended; - nexus->msgData[msgIndex++] = 2; - nexus->msgData[msgIndex++] = kSCSIMsgWideDataXferReq; - - for ( tw = targetParms.transferWidth, i = (UInt32)-1; - tw; - tw >>= 1, i++ ) - ; - - nexus->msgData[msgIndex++] = i; - } - - /* - * Setup to negotiate for Synchronous data transfers. - * - * Note: We can negotiate back to async based on the flags in the command. - */ - - if ( scsiCDB.cdbFlags & kCDBFlagsNegotiateSDTR ) - { - nexus->msgData[msgIndex++] = kSCSIMsgExtended; - nexus->msgData[msgIndex++] = 3; - nexus->msgData[msgIndex++] = kSCSIMsgSyncXferReq; - if ( targetParms.transferOffset != 0 ) - { - nexus->msgData[msgIndex++] = targetParms.transferPeriodpS / 4000; - nexus->msgData[msgIndex++] = targetParms.transferOffset; - } - else - { - nexus->msgData[msgIndex++] = 0; - nexus->msgData[msgIndex++] = 0; - } - - } - - /* - * If we are negotiating for both Sync and Wide data transfers, we setup both messages - * in the Nexus msgOut buffer. However, after each message the script needs to wait for - * a reply message from the target. In this case, we set the msgOut length to include - * bytes upto the end of the Wide message. When we get the reply from the target, the - * routine handling the WDTR will setup the Nexus pointers/counts to send the remaining - * message bytes. See Sym8xxExecute.m(Sym8xxNegotiateWDTR). - */ - srb->srbMsgLength = msgIndex; - - if ((scsiCDB.cdbFlags & (kCDBFlagsNegotiateWDTR | kCDBFlagsNegotiateSDTR)) - == (kCDBFlagsNegotiateWDTR | kCDBFlagsNegotiateSDTR)) - { - msgIndex -= 5; - } - - nexus->msg.length = OSSwapHostToLittleInt32( msgIndex ); - - srb->srbCDBFlags = scsiCDB.cdbFlags; -} - -/*-----------------------------------------------------------------------------* - * This routine sets up the data transfer SG list for the client's buffer in the - * Nexus structure. - * - * The SGList actually consists of script instructions. The script will branch - * to the SGList when the target enters data transfer phase. When the SGList completes - * it will either execute a script INT instruction if there are more segments of the - * user buffer that need to be transferred or will execute a script RETURN instruction - * to return to the script. - * - * The first two slots in the SGList are reserved for partial data transfers. See - * Sym8xxExecute.m(Sym8xxAdjustDataPtrs). - * - *-----------------------------------------------------------------------------*/ - - -/*-----------------------------------------------------------------------------* - * Build SG list based on an IOMemoryDescriptor object. - * - *-----------------------------------------------------------------------------*/ -bool Sym8xxSCSIController::Sym8xxUpdateSGList( SRB *srb ) -{ - IOPhysicalSegment range; - UInt32 actRanges; - UInt32 offset; - UInt32 bytesLeft; - UInt32 i; - IOReturn rc = true; - - offset = srb->xferOffset; - bytesLeft = srb->xferCount - srb->xferOffset; - - if ( bytesLeft == 0 ) return rc; - - i = 2; - - while ( (bytesLeft > 0) && (i < MAX_SGLIST_ENTRIES-1)) - { - actRanges = memoryCursor->getPhysicalSegments( srb->xferDesc, - offset, - &range, - 1 ); - - if ( actRanges != 1 ) - { - rc = false; - break; - } - - /* - * Note: The script instruction(s) to transfer data to/from the scsi bus - * have the same format as a typical SGList with the transfer length - * as the first word and the physical transfer address as the second. - * The data transfer direction is specified by a bit or'd into the - * high byte of the SG entry's length field. - */ - srb->nexus.sgListData[i].physAddr = OSSwapHostToLittleInt32( (UInt32)range.location ); - srb->nexus.sgListData[i].length = OSSwapHostToLittleInt32( range.length | srb->directionMask ); - - bytesLeft -= range.length; - offset += range.length; - i++; - } - - if ( !bytesLeft ) - { - srb->nexus.sgListData[i].length = OSSwapHostToLittleInt32( 0x90080000 ); - srb->nexus.sgListData[i].physAddr = OSSwapHostToLittleInt32( 0x00000000 ); - } - else - { - srb->nexus.sgListData[i].length = OSSwapHostToLittleInt32( 0x98080000 ); - srb->nexus.sgListData[i].physAddr = OSSwapHostToLittleInt32( A_sglist_complete ); - } - - srb->xferOffsetPrev = srb->xferOffset; - srb->xferOffset = offset; - - return rc; -} - diff --git a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxController.h b/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxController.h deleted file mode 100644 index 1b1d08551..000000000 --- a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxController.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* Sym8xxController.h created by russb2 on Sat 30-May-1998 */ - -#include -#include -#include - -#include - -#include "Sym8xxRegs.h" -#include "Sym8xxInterface.h" -#include "Sym8xxSRB.h" - -#include "Sym8xxScript.h" - -#define offsetof(type, field) ((int)&((type *)0)->field) - -class Sym8xxSCSIController : public IOSCSIParallelController -{ - OSDeclareDefaultStructors( Sym8xxSCSIController ) - -private: - - AdapterInterface *adapter; - AdapterInterface *adapterPhys; - - UInt32 nexusArrayVirt[MAX_SCSI_TAG]; - - IOBigMemoryCursor *memoryCursor; - - IOPCIDevice *provider; - - IOInterruptEventSource *interruptEvent; - - IOMemoryMap *ioMapRegs; - IOMemoryMap *ioMapRam; - - UInt8 mailBoxIndex; - - UInt32 initiatorID; - - UInt8 istatReg; - UInt8 dstatReg; - u_int16_t sistReg; - - UInt32 scriptRestartAddr; - - UInt32 srbSeqNum; - UInt32 resetSeqNum; - - SRB *resetSRB; - SRB *abortSRB; - SRB *abortCurrentSRB; - bool abortReqPending; - bool initialReset; - - bool negotiateWDTRComplete; - bool negotiateSDTRComplete; - - UInt32 transferPeriod; - UInt32 transferOffset; - UInt32 transferWidth; - - UInt32 chipId; - UInt32 chipClockRate; - - volatile UInt8 *chipBaseAddr; - UInt8 *chipBaseAddrPhys; - - volatile UInt8 *chipRamAddr; - UInt8 *chipRamAddrPhys; - -public: - bool configure( IOService *forProvider, SCSIControllerInfo *controllerInfo ); - void executeCommand( IOSCSIParallelCommand *scsiCommand ); - void cancelCommand( IOSCSIParallelCommand *scsiCommand ); - void resetCommand( IOSCSIParallelCommand *scsiCommand ); - -private: - bool Sym8xxInit(); - bool Sym8xxInitPCI(); - bool Sym8xxInitVars(); - bool Sym8xxInitScript(); - void Sym8xxLoadScript( UInt32 *scriptPgm, UInt32 scriptWords ); - bool Sym8xxInitChip(); - - void Sym8xxCalcMsgs( IOSCSIParallelCommand *scsiCommand ); - void Sym8xxAbortCommand( IOSCSIParallelCommand *scsiCommand ); - - bool Sym8xxUpdateSGList( SRB *srb ); - bool Sym8xxUpdateSGListVirt( SRB *srb ); - bool Sym8xxUpdateSGListDesc( SRB *srb ); - - void Sym8xxStartSRB( SRB *srb ); - void Sym8xxSignalScript( SRB *srb ); - void interruptOccurred( IOInterruptEventSource *ies, int intCount ); - void Sym8xxProcessIODone(); - void Sym8xxCompleteSRB( SRB *srb ); - void Sym8xxProcessInterrupt(); - void Sym8xxAdjustDataPtrs( SRB *srb, Nexus *nexus ); - UInt32 Sym8xxCheckFifo( SRB *srb, UInt32 *pfifoCnt ); - void Sym8xxUpdateXferOffset( SRB *srb ); - void Sym8xxProcessNoNexus(); - void Sym8xxAbortCurrent( SRB *srb ); - void Sym8xxClearFifo(); - void Sym8xxNegotiateSDTR( SRB *srb, Nexus *nexus ); - void Sym8xxNegotiateWDTR( SRB *srb, Nexus *nexus ); - void Sym8xxSendMsgReject( SRB *srb ); - void Sym8xxSCSIBusReset(SRB *srb ); - void Sym8xxProcessSCSIBusReset(); - void Sym8xxCheckRequestSense( SRB *srb ); - void Sym8xxAbortBdr( SRB *srb ); - bool Sym8xxCancelMailBox( Nexus *nexusCancel ); - void Sym8xxCancelMailBox( UInt32 target, UInt32 lun, bool fReschedule ); - - void Sym8xxAbortScript(); - - UInt32 Sym8xxReadRegs( volatile UInt8 *chipRegs, UInt32 regOffset, UInt32 regSize ); - void Sym8xxWriteRegs( volatile UInt8 *chipRegs, UInt32 regOffset, UInt32 regSize, UInt32 regValue ); - -}; - diff --git a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxExecute.cpp b/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxExecute.cpp deleted file mode 100644 index a90da6559..000000000 --- a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxExecute.cpp +++ /dev/null @@ -1,1372 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* Sym8xxExecute.m created by russb2 on Sat 30-May-1998 */ - -#include "Sym8xxController.h" - -extern "C" -{ - unsigned int ml_phys_read( vm_offset_t paddr ); -}; - -#if 0 -static UInt32 dropInt = 0; -#endif - -void Sym8xxSCSIController::Sym8xxStartSRB( SRB *srb ) -{ - - srb->nexus.targetParms.scntl3Reg = adapter->targetClocks[srb->target].scntl3Reg; - srb->nexus.targetParms.sxferReg = adapter->targetClocks[srb->target].sxferReg; - - adapter->nexusPtrsVirt[srb->nexus.tag] = &srb->nexus; - adapter->nexusPtrsPhys[srb->nexus.tag] = (Nexus *)OSSwapHostToLittleInt32( (UInt32)&srb->srbPhys->nexus ); - adapter->schedMailBox[mailBoxIndex++] = (Nexus *)OSSwapHostToLittleInt32 ( (UInt32)&srb->srbPhys->nexus ); - - Sym8xxSignalScript( srb ); -} - - -/*-----------------------------------------------------------------------------* - * Interrupts from the Symbios chipset are dispatched here at task time under the - * IOThread's context. - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::interruptOccurred( IOInterruptEventSource *ies, int intCount ) -{ - do - { - /* - * The chipset's ISTAT reg gives us the general interrupting condiditions, - * with DSTAT and SIST providing more detailed information. - */ - istatReg = Sym8xxReadRegs( chipBaseAddr, ISTAT, ISTAT_SIZE ); - - /* The INTF bit in ISTAT indicates that the script is signalling the driver - * that its IODone mailbox is full and that we should process a completed - * request. The script continues to run after posting this interrupt unlike - * other chipset interrupts which require the driver to restart the script - * engine. - */ - if ( istatReg & INTF ) - { - Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, istatReg ); -#if 0 - if ( dropInt++ > 100 ) - { - dropInt = 0; - SCRIPT_VAR(R_ld_IOdone_mailbox) = 0; - continue; - } -#endif - Sym8xxProcessIODone(); - } - - /* - * Handle remaining interrupting conditions - */ - if ( istatReg & (SIP | DIP) ) - { - Sym8xxProcessInterrupt(); - } - } - while ( istatReg & (SIP | DIP | INTF) ); - - getWorkLoop()->enableAllInterrupts(); - -} - -/*-----------------------------------------------------------------------------* - * Process a request posted in the script's IODone mailbox. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxProcessIODone() -{ - SRB *srb; - Nexus *nexus; - IODoneMailBox *pMailBox; - - - /* - * The IODone mailbox contains an index into our Nexus pointer tables. - * - * The Nexus struct is part of the SRB so we can get our SRB address - * by subtracting the offset of the Nexus struct in the SRB. - */ - pMailBox = (IODoneMailBox *)&SCRIPT_VAR(R_ld_IOdone_mailbox); - nexus = adapter->nexusPtrsVirt[pMailBox->nexus]; - srb = (SRB *)((UInt32)nexus - offsetof(SRB, nexus)); - - srb->srbSCSIStatus = pMailBox->status; - - if ( srb->srbSCSIStatus == kSCSIStatusCheckCondition ) - { - Sym8xxCheckRequestSense( srb ); - } - - Sym8xxUpdateXferOffset( srb ); - - /* - * Clear the completed Nexus pointer from our tables and clear the - * IODone mailbox. - */ - adapter->nexusPtrsVirt[pMailBox->nexus] = (Nexus *) -1; - adapter->nexusPtrsPhys[pMailBox->nexus] = (Nexus *) -1; - SCRIPT_VAR(R_ld_IOdone_mailbox) = 0; - - /* - * Wake up the client's thread to do post-processing - */ - Sym8xxCompleteSRB( srb ); - - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_select_phase]; -} -/*-----------------------------------------------------------------------------* - * - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxCompleteSRB( SRB *srb ) -{ - IOSCSIParallelCommand *scsiCommand; - SCSIResults scsiResults; - SCSINegotiationResults negotiationResult, *negResult; - - - scsiCommand = srb->scsiCommand; - - bzero( &scsiResults, sizeof(scsiResults) ); - - scsiResults.adapterStatus = srb->srbAdapterStatus; - scsiResults.returnCode = srb->srbReturnCode; - - - if ( srb == abortSRB ) - { - abortSRB = 0; - if ( abortReqPending == true ) - { - abortReqPending = false; - enableCommands(); - } - } - else - { - scsiResults.bytesTransferred = srb->xferDone; - scsiResults.scsiStatus = srb->srbSCSIStatus; - } - - negResult = 0; - - if ( (srb->srbCDBFlags & kCDBFlagsNegotiateSDTR) || (srb->srbCDBFlags & kCDBFlagsNegotiateWDTR) ) - { - bzero( &negotiationResult, sizeof(struct SCSINegotiationResults) ); - - if ( ((srb->srbCDBFlags & kCDBFlagsNegotiateSDTR) && srb->negotiateSDTRComplete == false) || - ((srb->srbCDBFlags & kCDBFlagsNegotiateWDTR) && srb->negotiateWDTRComplete == false) ) - { - negotiationResult.returnCode = kIOReturnIOError; - } - - negotiationResult.transferPeriodpS = transferPeriod; - negotiationResult.transferOffset = transferOffset; - negotiationResult.transferWidth = transferWidth; - negotiationResult.transferOptions = 0; - - negResult = &negotiationResult; - } - - scsiCommand->setResults( &scsiResults, negResult ); - scsiCommand->complete(); -} - -/*-----------------------------------------------------------------------------* - * General script interrupt processing - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxProcessInterrupt() -{ - SRB *srb = NULL; - Nexus *nexus = NULL; - UInt32 nexusIndex; - UInt32 scriptPhase; - UInt32 fifoCnt = 0; - UInt32 dspsReg = 0; - UInt32 dspReg = 0; - - - /* - * Read DSTAT/SIST regs to determine why the script stopped. - */ - dstatReg = Sym8xxReadRegs( chipBaseAddr, DSTAT, DSTAT_SIZE ); - IODelay(5); - sistReg = Sym8xxReadRegs( chipBaseAddr, SIST, SIST_SIZE ); - -// printf( "SCSI(Symbios8xx): SIST = %04x DSTAT = %02x\n\r", sistReg, dstatReg ); - - /* - * This Script var tells us what the script thinks it was doing when the interrupt occurred. - */ - scriptPhase = OSSwapHostToLittleInt32( SCRIPT_VAR(R_ld_phase_flag) ); - - /* - * SCSI Bus reset detected - * - * Clean up the carnage. - * Note: This may be either an adapter or target initiated reset. - */ - if ( sistReg & RSTI ) - { - Sym8xxProcessSCSIBusReset(); - return; - } - - /* - * Calculate our current SRB/Nexus. - * - * Read a script var to determine the index of the nexus it was processing - * when the interrupt occurred. The script will invalidate the index if there - * is no target currently connected or the script cannot determine which target - * has reconnected. - */ - nexusIndex = OSSwapHostToLittleInt32(SCRIPT_VAR(R_ld_nexus_index)); - if ( nexusIndex >= MAX_SCSI_TAG ) - { - Sym8xxProcessNoNexus(); - return; - } - nexus = adapter->nexusPtrsVirt[nexusIndex]; - if ( nexus == (Nexus *) -1 ) - { - Sym8xxProcessNoNexus(); - return; - } - srb = (SRB *)((UInt32)nexus - offsetof(SRB, nexus)); - - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_phase_handler]; - - /* - * Parity and SCSI Gross Errors. - * - * Abort the current connection. The abort completion will trigger - * clean-up of the current SRB/Nexus. - */ - if ( sistReg & PAR ) - { - srb->srbAdapterStatus = kSCSIAdapterStatusParityError; - Sym8xxAbortCurrent( srb ); - } - - else if ( sistReg & SGE ) - { - srb->srbAdapterStatus = kSCSIAdapterStatusProtocolError; - Sym8xxAbortCurrent( srb ); - } - - /* - * Unexpected disconnect. - * - * If we were currently trying to abort this connection then mark the abort - * as completed. For all cases clean-up and wake-up the client thread. - */ - else if ( sistReg & UDC ) - { - if ( srb->srbAdapterStatus == kSCSIAdapterStatusSuccess ) - { - srb->srbAdapterStatus = kSCSIAdapterStatusProtocolError; - } - adapter->nexusPtrsVirt[nexusIndex] = (Nexus *) -1; - adapter->nexusPtrsPhys[nexusIndex] = (Nexus *) -1; - - if ( scriptPhase == A_kphase_ABORT_CURRENT ) - { - abortCurrentSRB = NULL; - } - - Sym8xxCompleteSRB( srb ); - - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_select_phase]; - } - - /* - * Phase Mis-match - * - * If we are in MsgOut phase then calculate how much of the message we sent. For - * now, however, we dont handle the target rejecting messages, so the request is aborted. - * - * If we are in DataIn/DataOut phase. We update the SRB/Nexus with our current data - * pointers. - */ - else if ( sistReg & MA ) - { - if ( scriptPhase == A_kphase_MSG_OUT ) - { - srb->srbMsgResid = Sym8xxCheckFifo( srb, &fifoCnt ); - nexus->msg.ppData = OSSwapHostToLittleInt32( OSSwapHostToLittleInt32(nexus->msg.ppData) - + OSSwapHostToLittleInt32(nexus->msg.length) - - srb->srbMsgResid ); - nexus->msg.length = OSSwapHostToLittleInt32( srb->srbMsgResid ); - - Sym8xxAbortCurrent( srb ); - } - else if ( (scriptPhase == A_kphase_DATA_OUT) || (scriptPhase == A_kphase_DATA_IN) ) - { - Sym8xxAdjustDataPtrs( srb, nexus ); - } - else - { - IOLog("SCSI(Symbios8xx): Unexpected phase mismatch - scriptPhase = %08x\n\r", (int)scriptPhase); - Sym8xxAbortCurrent( srb ); - } - - Sym8xxClearFifo(); - } - - /* - * Selection Timeout. - * - * Clean-up the current request. - */ - else if ( sistReg & STO ) - { - srb->srbAdapterStatus = kSCSIAdapterStatusSelectionTimeout; - - adapter->nexusPtrsVirt[nexusIndex] = (Nexus *) -1; - adapter->nexusPtrsPhys[nexusIndex] = (Nexus *) -1; - SCRIPT_VAR(R_ld_IOdone_mailbox) = 0; - - Sym8xxCompleteSRB( srb ); - - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_select_phase]; - } - - /* - * Handle script initiated interrupts - */ - else if ( dstatReg & SIR ) - { - dspsReg = Sym8xxReadRegs( chipBaseAddr, DSPS, DSPS_SIZE ); - -// printf( "SCSI(Symbios8xx): DSPS = %08x\n\r", dspsReg ); - - switch ( dspsReg ) - { - /* - * Non-zero SCSI status - * - * Send request sense CDB or complete request depending on SCSI status value - */ - case A_status_error: - Sym8xxProcessIODone(); - break; - - /* - * Received SDTR/WDTR message from target. - * - * Prepare reply message if we requested negotiation. Otherwise reject - * target initiated negotiation. - */ - case A_negotiateSDTR: - Sym8xxNegotiateSDTR( srb, nexus ); - break; - - case A_negotiateWDTR: - Sym8xxNegotiateWDTR( srb, nexus ); - break; - - /* - * Partial SG List completed. - * - * Refresh the list from the remaining addresses to be transfered and set the - * script engine to branch into the list. - */ - case A_sglist_complete: - Sym8xxUpdateSGList( srb ); - scriptRestartAddr = (UInt32)&srb->srbPhys->nexus.sgListData[2]; - break; - - /* - * Completed abort request - * - * Clean-up the aborted request. - */ - case A_abort_current: - adapter->nexusPtrsVirt[nexusIndex] = (Nexus *) -1; - adapter->nexusPtrsPhys[nexusIndex] = (Nexus *) -1; - - abortCurrentSRB = NULL; - - Sym8xxCompleteSRB( srb ); - - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_select_phase]; - break; - - /* - * Script detected protocol errors - * - * Abort the current request. - */ - case A_unknown_phase: - srb->srbAdapterStatus = kSCSIAdapterStatusProtocolError; - Sym8xxAbortCurrent( srb ); - break; - - case A_unknown_msg_reject: - case A_unexpected_msg: - case A_unexpected_ext_msg: - srb->srbAdapterStatus = kSCSIAdapterStatusMsgReject; - Sym8xxAbortCurrent( srb ); - break; - - default: - IOLog( "SCSI(Symbios8xx): Unknown Script Int = %08x\n\r", (int)dspsReg ); - Sym8xxAbortCurrent( srb ); - } - } - - /* - * Illegal script instruction. - * - * We're toast! Abort the current request and hope for the best! - */ - else if ( dstatReg & IID ) - { - dspReg = Sym8xxReadRegs( chipBaseAddr, DSP, DSP_SIZE ); - - IOLog("SCSI(Symbios8xx): Illegal script instruction - dsp = %08x srb=%08x\n\r", (int)dspReg, (int)srb ); - - Sym8xxAbortCurrent( srb ); - } - - if ( scriptRestartAddr ) - { - Sym8xxWriteRegs( chipBaseAddr, DSP, DSP_SIZE, scriptRestartAddr ); - } -} - - -/*-----------------------------------------------------------------------------* - * Current Data Pointer calculations - * - * To do data transfers the driver generates a list of script instructions - * in system storage to deliver data to the requested physical addresses. The - * script branches to the list when the target enters data transfer phase. - * - * When the target changes phase during a data transfer, data is left trapped - * inside the various script engine registers. This routine determines how much - * data was not actually transfered to/from the target and generates a new - * S/G List entry for the partial transfer and a branch back into the original - * S/G list. These script instructions are stored in two reserved slots at the - * top of the original S/G List. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxAdjustDataPtrs( SRB *srb, Nexus *nexus ) -{ - UInt32 i; - UInt32 sgResid; - UInt32 fifoCnt; - UInt32 dspReg; - UInt32 sgDone; - UInt8 scntl2Reg; - Nexus *nexusPhys; - - /* - * Determine SG element residual - * - * This routine returns how much of the current S/G List element the - * script was processing remains to be sent/received. All the information - * required to do this is stored in the script engine's registers. - */ - sgResid = Sym8xxCheckFifo( srb, &fifoCnt ); - - /* - * Determine which script instruction in our SGList we were executing when - * the target changed phase. - * - * The script engine's dspReg tells us where the script thinks it was. Based - * on the physical address of our current SRB/Nexus we can calculate - * an index into our S/G List. - */ - dspReg = Sym8xxReadRegs( chipBaseAddr, DSP, DSP_SIZE ); - - i = ((dspReg - (UInt32)srb->srbPhys->nexus.sgListData) / sizeof(SGEntry)) - 1; - - if ( i > MAX_SGLIST_ENTRIES-1 ) - { - IOLog("SCSI(Symbios8xx): Bad sgListIndex\n\r"); - Sym8xxAbortCurrent( srb ); - return; - } - - /* - * Wide/odd-byte transfers. - * - * When dealing with Wide data transfers, if a S/G List ends with an odd-transfer count, then a - * valid received data byte is left in the script engine's SWIDE register. The least painful way - * to recover this byte is to construct a small script thunk to transfer one additional byte. The - * script will automatically draw this byte from the SWIDE register rather than the SCSI bus. - * The script thunk then branches back to script's PhaseHandler entrypoint. - * - */ - nexusPhys = &srb->srbPhys->nexus; - - scntl2Reg = Sym8xxReadRegs( chipBaseAddr, SCNTL2, SCNTL2_SIZE ); - if ( scntl2Reg & WSR ) - { - adapter->xferSWideInst[0] = OSSwapHostToLittleInt32( srb->directionMask | 1 ); - adapter->xferSWideInst[1] = nexus->sgListData[i].physAddr; - adapter->xferSWideInst[2] = OSSwapHostToLittleInt32( 0x80080000 ); - adapter->xferSWideInst[3] = OSSwapHostToLittleInt32( (UInt32)&chipRamAddrPhys[Ent_phase_handler] ); - - scriptRestartAddr = (UInt32) adapterPhys->xferSWideInst; - - /* - * Note: There is an assumption here that the sgResid count will be > 1. It appears - * that the script engine does not generate a phase-mismatch interrupt until - * we attempt to move > 1 byte from the SCSI bus and the only byte available is - * in SWIDE. - */ - sgResid--; - } - - /* - * Calculate partial S/G List instruction and branch - * - * Fill in slots 0/1 of the SGList based on the SGList index (i) and SGList residual count - * (sgResid) calculated above. - * - */ - sgDone = (OSSwapHostToLittleInt32( nexus->sgListData[i].length ) & 0x00ffffff) - sgResid; - - nexus->sgListData[0].length = OSSwapHostToLittleInt32( sgResid | srb->directionMask ); - nexus->sgListData[0].physAddr = OSSwapHostToLittleInt32( OSSwapHostToLittleInt32(nexus->sgListData[i].physAddr) + sgDone ); - /* - * If a previously calculated SGList 0 entry was interrupted again, we dont need to calculate - * a new branch address since the previous one is still valid. - */ - if ( i != 0 ) - { - nexus->sgListData[1].length = OSSwapHostToLittleInt32( 0x80080000 ); - nexus->sgListData[1].physAddr = OSSwapHostToLittleInt32( (UInt32)&nexusPhys->sgListData[i+1] ); - nexus->sgNextIndex = i + 1; - } - nexus->ppSGList = (SGEntry *)OSSwapHostToLittleInt32( (UInt32) &nexusPhys->sgListData[0] ); - - /* - * The script sets this Nexus variable to non-zero each time it calls the driver generated - * S/G list. This allows the driver's completion routines to differentiate between a successful - * transfer vs no data transfer at all. - */ - nexus->dataXferCalled = 0; - - return; -} - -/*-----------------------------------------------------------------------------* - * Determine SG element residual - * - * This routine returns how much of the current S/G List element the - * script was processing remains to be sent/received. All the information - * required to do this is stored in the script engine's registers. - * - *-----------------------------------------------------------------------------*/ -UInt32 Sym8xxSCSIController::Sym8xxCheckFifo( SRB *srb, UInt32 *pfifoCnt ) -{ - bool fSCSISend; - bool fXferSync; - UInt32 scriptPhase = 0; - UInt32 dbcReg = 0; - UInt32 dfifoReg = 0; - UInt32 ctest5Reg = 0; - UInt8 sstat0Reg = 0; - UInt8 sstat1Reg = 0; - UInt8 sstat2Reg = 0; - UInt32 fifoCnt = 0; - UInt32 sgResid = 0; - - scriptPhase = OSSwapHostToLittleInt32( SCRIPT_VAR(R_ld_phase_flag) ); - - fSCSISend = (scriptPhase == A_kphase_DATA_OUT) || (scriptPhase == A_kphase_MSG_OUT); - - fXferSync = ((scriptPhase == A_kphase_DATA_OUT) || (scriptPhase == A_kphase_DATA_IN)) - && (srb->nexus.targetParms.sxferReg & 0x1F); - - dbcReg = Sym8xxReadRegs( chipBaseAddr, DBC, DBC_SIZE ) & 0x00ffffff; - - if ( !(dstatReg & DFE) ) - { - ctest5Reg = Sym8xxReadRegs( chipBaseAddr, CTEST5, CTEST5_SIZE ); - dfifoReg = Sym8xxReadRegs( chipBaseAddr, DFIFO, DFIFO_SIZE ); - - if ( ctest5Reg & DFS ) - { - fifoCnt = ((((ctest5Reg & 0x03) << 8) | dfifoReg) - dbcReg) & 0x3ff; - } - else - { - fifoCnt = (dfifoReg - dbcReg) & 0x7f; - } - } - - sstat0Reg = Sym8xxReadRegs( chipBaseAddr, SSTAT0, SSTAT0_SIZE ); - sstat2Reg = Sym8xxReadRegs( chipBaseAddr, SSTAT2, SSTAT2_SIZE ); - - if ( fSCSISend ) - { - fifoCnt += (sstat0Reg & OLF ) ? 1 : 0; - fifoCnt += (sstat2Reg & OLF1) ? 1 : 0; - - if ( fXferSync ) - { - fifoCnt += (sstat0Reg & ORF ) ? 1 : 0; - fifoCnt += (sstat2Reg & ORF1) ? 1 : 0; - } - } - else - { - if ( fXferSync ) - { - sstat1Reg = Sym8xxReadRegs( chipBaseAddr, SSTAT0, SSTAT0_SIZE ); - fifoCnt += (sstat1Reg >> 4) | (sstat2Reg & FF4); - } - else - { - fifoCnt += (sstat0Reg & ILF ) ? 1 : 0; - fifoCnt += (sstat2Reg & ILF1) ? 1 : 0; - } - } - - sgResid = dbcReg + fifoCnt; - *pfifoCnt = fifoCnt; - - return sgResid; -} - -/*-----------------------------------------------------------------------------* - * Calculate transfer counts. - * - * This routine updates srb->xferDone with the amount of data transferred - * by the last S/G List executed. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxUpdateXferOffset( SRB *srb ) -{ - UInt32 i; - UInt32 xferOffset; - - /* - * srb->xferOffset contains the client buffer offset INCLUDING the range - * covered by the current SGList. - */ - xferOffset = srb->xferOffset; - - /* - * If script did not complete the current transfer list then we need to determine - * how much of the list was completed. - */ - if ( srb->nexus.dataXferCalled == 0 ) - { - /* - * srb->xferOffsetPrev contains the client buffer offset EXCLUDING the - * range covered by the current SGList. - */ - xferOffset = srb->xferOffsetPrev; - - /* - * Calculate bytes transferred for partially completed list. - * - * To calculate the amount of this list completed, we sum the residual amount - * in SGList Slot 0 and the completed list elements 2 to sgNextIndex-1. - */ - if ( srb->nexus.sgNextIndex != 0 ) - { - xferOffset += OSSwapHostToLittleInt32( srb->nexus.sgListData[srb->nexus.sgNextIndex-1].length ) - - OSSwapHostToLittleInt32( srb->nexus.sgListData[0].length ); - - for ( i=2; i < srb->nexus.sgNextIndex-1; i++ ) - { - xferOffset += OSSwapHostToLittleInt32( srb->nexus.sgListData[i].length ) & 0x00ffffff; - } - } - } - - /* - * The script leaves the result of any Ignore Wide Residual message received from the target - * during the transfer. - */ - xferOffset -= srb->nexus.wideResidCount; - - -#if 0 - { - UInt32 resid = srb->xferOffset - xferOffset; - if ( resid ) - { - IOLog( "SCSI(Symbios8xx): Incomplete transfer - Req Count = %08x Act Count = %08x - srb = %08x\n\r", - srb->xferCount, xferOffset, (UInt32)srb ); - } - } -#endif - - srb->xferDone = xferOffset; -} - -/*-----------------------------------------------------------------------------* - * No SRB/Nexus Processing. - * - * In some cases (mainly Aborts) not having a SRB/Nexus is normal. In other - * cases it indicates a problem such a reconnection from a target that we - * have no record of. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxProcessNoNexus() -{ - UInt32 dspsReg; - UInt32 dspReg = 0; - UInt32 scriptPhase = (UInt32)-1 ; - - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_select_phase]; - - dspsReg = Sym8xxReadRegs( chipBaseAddr, DSPS, DSPS_SIZE ); - - scriptPhase = OSSwapHostToLittleInt32( SCRIPT_VAR(R_ld_phase_flag) ); - - /* - * If we were trying to abort or disconnect a target and the bus - * is now free we consider the abort to have completed. - */ - if ( sistReg & UDC ) - { - if ( (scriptPhase == A_kphase_ABORT_MAILBOX) && abortSRB ) - { - Sym8xxCompleteSRB( abortSRB ); - SCRIPT_VAR(R_ld_AbortBdr_mailbox) = 0; - } - else if ( scriptPhase == A_kphase_ABORT_CURRENT ) - { - abortCurrentSRB = NULL; - } - } - /* - * If we were trying to connect to a target to send it an abort message, and - * we timed out, we consider the abort as completed. - * - * Note: In this case the target may be hung, but at least its not on the bus. - */ - else if ( sistReg & STO ) - { - if ( (scriptPhase == A_kphase_ABORT_MAILBOX) && abortSRB ) - { - Sym8xxCompleteSRB( abortSRB ); - SCRIPT_VAR(R_ld_AbortBdr_mailbox) = 0; - } - } - - /* - * If the script died, without a vaild nexusIndex, we abort anything that is currently - * connected and hope for the best! - */ - else if ( dstatReg & IID ) - { - dspReg = Sym8xxReadRegs( chipBaseAddr, DSP, DSP_SIZE ); - IOLog("SCSI(Symbios8xx): Illegal script instruction - dsp = %08x srb=0\n\r", (int)dspReg ); - Sym8xxAbortCurrent( (SRB *)-1 ); - } - - /* - * Script signaled conditions - */ - else if ( dstatReg & SIR ) - { - switch ( dspsReg ) - { - case A_abort_current: - abortCurrentSRB = NULL; - break; - - case A_abort_mailbox: - Sym8xxCompleteSRB( abortSRB ); - SCRIPT_VAR(R_ld_AbortBdr_mailbox) = 0; - break; - - default: - Sym8xxAbortCurrent( (SRB *)-1 ); - } - } - else - { - Sym8xxAbortCurrent( (SRB *)-1 ); - } - - if ( scriptRestartAddr ) - { - Sym8xxWriteRegs( chipBaseAddr, DSP, DSP_SIZE, scriptRestartAddr ); - } -} - - -/*-----------------------------------------------------------------------------* - * Abort currently connected target. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxAbortCurrent( SRB *srb ) -{ - if ( abortCurrentSRB ) - { - if ( abortCurrentSRB != srb ) - { - IOLog("SCSI(Symbios8xx): Multiple abort immediate SRBs - resetting\n\r"); - Sym8xxSCSIBusReset( (SRB *)0 ); - } - return; - } - - abortCurrentSRB = srb; - - if ( srb != (SRB *)-1 ) - { - if ( srb->srbAdapterStatus == kSCSIAdapterStatusSuccess ) - { - srb->srbAdapterStatus = kSCSIAdapterStatusProtocolError; - } - } - - /* - * Issue abort or abort tag depending on whether the is a tagged request - */ - SCRIPT_VAR(R_ld_AbortCode) = OSSwapHostToLittleInt32( ((srb != (SRB *)-1) && (srb->nexus.tag >= MIN_SCSI_TAG)) ? 0x0d : 0x06 ); - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_issueAbort_BDR]; - - Sym8xxClearFifo(); -} - -/*-----------------------------------------------------------------------------* - * This routine clears the script engine's SCSI and DMA fifos. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxClearFifo() -{ - UInt8 ctest3Reg; - UInt8 stest2Reg; - UInt8 stest3Reg; - - stest2Reg = Sym8xxReadRegs( chipBaseAddr, STEST2, STEST2_SIZE ); - if ( stest2Reg & ROF ) - { - Sym8xxWriteRegs( chipBaseAddr, STEST2, STEST2_SIZE, stest2Reg ); - } - - ctest3Reg = Sym8xxReadRegs( chipBaseAddr, CTEST3, CTEST3_SIZE ); - ctest3Reg |= CLF; - Sym8xxWriteRegs( chipBaseAddr, CTEST3, CTEST3_SIZE, ctest3Reg ); - - stest3Reg = Sym8xxReadRegs( chipBaseAddr, STEST3, STEST3_SIZE ); - stest3Reg |= CSF; - Sym8xxWriteRegs( chipBaseAddr,STEST3, STEST3_SIZE, stest3Reg ); - - do - { - ctest3Reg = Sym8xxReadRegs( chipBaseAddr, CTEST3, CTEST3_SIZE ); - stest2Reg = Sym8xxReadRegs( chipBaseAddr, STEST3, STEST3_SIZE ); - stest3Reg = Sym8xxReadRegs( chipBaseAddr, STEST3, STEST3_SIZE ); - } - while( (ctest3Reg & CLF) || (stest3Reg & CSF) || (stest2Reg & ROF) ); -} - -/*-----------------------------------------------------------------------------* - * This routine processes the target's response to our SDTR message. - * - * We calculate the values for the script engine's timing registers - * for synchronous registers, and update our tables indicating that - * requested data transfer mode is in-effect. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxNegotiateSDTR( SRB *srb, Nexus *nexus ) -{ - UInt32 x; - UInt8 *pMsg; - UInt32 syncPeriod; - - /* - * If we were not negotiating, the send MsgReject to targets negotiation - * attempt. - */ - if ( !(srb->srbCDBFlags & kCDBFlagsNegotiateSDTR) ) - { - Sym8xxSendMsgReject( srb ); - return; - } - - /* - * Get pointer to negotiation message received from target. - */ - pMsg = (UInt8 *) &SCRIPT_VAR(R_ld_message); - - /* - * The target's SDTR response contains the (transfer period / 4). - * - * We set our sync clock divisor to 1, 2, or 4 giving us a clock rates - * of: - * 80Mhz (Period = 12.5ns), - * 40Mhz (Period = 25.0ns) - * 20Mhz (Period = 50.0ns) - * - * This is further divided by the value in the sxfer reg to give us the final sync clock rate. - * - * The requested sync period is scaled up by 1000 and the clock periods are scaled up by 10 - * giving a result scaled up by 100. This is rounded-up and converted to sxfer reg values. - */ - if ( pMsg[4] == 0 ) - { - nexus->targetParms.scntl3Reg &= 0x0f; - nexus->targetParms.sxferReg = 0x00; - } - else - { - syncPeriod = (UInt32)pMsg[3] << 2; - if ( syncPeriod < 100 ) - { - nexus->targetParms.scntl3Reg |= SCNTL3_INIT_875_ULTRA; - x = (syncPeriod * 1000) / 125; - } - else if ( syncPeriod < 200 ) - { - nexus->targetParms.scntl3Reg |= SCNTL3_INIT_875_FAST; - x = (syncPeriod * 1000) / 250; - } - else - { - nexus->targetParms.scntl3Reg |= SCNTL3_INIT_875_SLOW; - x = (syncPeriod * 1000) / 500; - } - - if ( x % 100 ) x += 100; - - /* - * sxferReg Bits: 5-0 - Transfer offset - * 7-6 - Sync Clock Divisor (0 = sync clock / 4) - */ - nexus->targetParms.sxferReg = ((x/100 - 4) << 5) | pMsg[4]; - - transferPeriod = syncPeriod * 1000; - transferOffset = pMsg[4]; - - srb->negotiateSDTRComplete = true; - } - - /* - * Update our per-target tables and set-up the hardware regs for this request. - * - * On reconnection attempts, the script will use our per-target tables to set-up - * the scntl3 and sxfer registers in the script engine. - */ - adapter->targetClocks[srb->target].sxferReg = nexus->targetParms.sxferReg; - adapter->targetClocks[srb->target].scntl3Reg = nexus->targetParms.scntl3Reg; - - Sym8xxWriteRegs( chipBaseAddr, SCNTL3, SCNTL3_SIZE, nexus->targetParms.scntl3Reg ); - Sym8xxWriteRegs( chipBaseAddr, SXFER, SXFER_SIZE, nexus->targetParms.sxferReg ); - - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_clearACK]; -} - -/*-----------------------------------------------------------------------------* - * This routine processes the target's response to our WDTR message. - * - * In addition, if there is a pending SDTR message, this routine sends it - * to the target. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxNegotiateWDTR( SRB *srb, Nexus *nexus ) -{ - UInt8 *pMsg; - UInt32 msgBytesSent; - UInt32 msgBytesLeft; - - /* - * If we were not negotiating, the send MsgReject to targets negotiation - * attempt. - */ - if ( !(srb->srbCDBFlags & kCDBFlagsNegotiateWDTR) ) - { - Sym8xxSendMsgReject( srb ); - return; - } - - /* - * Set Wide (16-bit) vs Narrow (8-bit) data transfer mode based on target's response. - */ - pMsg = (UInt8 *) &SCRIPT_VAR(R_ld_message); - - if ( pMsg[3] == 1 ) - { - nexus->targetParms.scntl3Reg |= EWS; - transferWidth = 2; - } - else - { - nexus->targetParms.scntl3Reg &= ~EWS; - transferWidth = 1; - } - - /* - * Update our per-target tables and set-up the hardware regs for this request. - * - * On reconnection attempts, the script will use our per-target tables to set-up - * the scntl3 and sxfer registers in the script engine. - */ - - adapter->targetClocks[srb->target].scntl3Reg = nexus->targetParms.scntl3Reg; - Sym8xxWriteRegs( chipBaseAddr, SCNTL3, SCNTL3_SIZE, nexus->targetParms.scntl3Reg ); - - srb->negotiateWDTRComplete = true; - - /* - * If there any pending messages left for the target, send them now, - */ - msgBytesSent = OSSwapHostToLittleInt32( nexus->msg.length ); - msgBytesLeft = srb->srbMsgLength - msgBytesSent; - if ( msgBytesLeft ) - { - nexus->msg.length = OSSwapHostToLittleInt32( msgBytesLeft ); - nexus->msg.ppData = OSSwapHostToLittleInt32( OSSwapHostToLittleInt32( nexus->msg.ppData ) + msgBytesSent ); - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_issueMessageOut]; - } - - /* - * Otherwise, tell the script we're done with MsgOut phase. - */ - else - { - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_clearACK]; - } -} - -/*-----------------------------------------------------------------------------* - * Reject message received from target. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxSendMsgReject( SRB *srb ) -{ - srb->nexus.msg.ppData = OSSwapHostToLittleInt32((UInt32)&srb->srbPhys->nexus.msgData); - srb->nexus.msg.length = OSSwapHostToLittleInt32(0x01); - srb->nexus.msgData[0] = 0x07; - - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_issueMessageOut]; -} - - -/*-----------------------------------------------------------------------------* - * This routine initiates a SCSI Bus Reset. - * - * This may be an internally generated request as part of error recovery or - * a client's bus reset request. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxSCSIBusReset( SRB *srb ) -{ - if ( srb ) - { - if ( resetSRB ) - { - srb->srbReturnCode = kIOReturnBusy; - Sym8xxCompleteSRB( srb ); - return; - } - resetSRB = srb; - } - - Sym8xxAbortScript(); - - Sym8xxWriteRegs( chipBaseAddr, SCNTL1, SCNTL1_SIZE, SCNTL1_SCSI_RST ); - IODelay( 100 ); - Sym8xxWriteRegs( chipBaseAddr, SCNTL1, SCNTL1_SIZE, SCNTL1_INIT ); -} - -/*-----------------------------------------------------------------------------* - * This routine handles a SCSI Bus Reset interrupt. - * - * The SCSI Bus reset may be generated by a target on the bus, internally from - * the driver's error recovery or from a client request. - * - * Once the reset is detected we establish a settle period where new client requests - * are blocked in the client thread. In addition we flush all currently executing - * scsi requests back to the client. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxProcessSCSIBusReset() -{ - UInt32 i; - - Sym8xxClearFifo(); - - /* - * We clear the script's request mailboxes. Any work in the script mailboxes is - * already in the NexusPtr tables so we have already have handled the SRB/Nexus - * cleanup. - */ - for ( i=0; i < MAX_SCHED_MAILBOXES; i++ ) - { - adapter->schedMailBox[i] = 0; - } - - SCRIPT_VAR(R_ld_AbortBdr_mailbox) = 0; - SCRIPT_VAR(R_ld_IOdone_mailbox) = 0; - SCRIPT_VAR(R_ld_counter) = 0; - mailBoxIndex = 0; - - - /* - * Reset the data transfer mode/clocks in our per-target tables back to Async/Narrow 8-bit - */ - for ( i=0; i < MAX_SCSI_TARGETS; i++ ) - { - adapter->targetClocks[i].scntl3Reg = SCNTL3_INIT_875; - adapter->targetClocks[i].sxferReg = 0; - } - - scriptRestartAddr = (UInt32) &chipRamAddrPhys[Ent_select_phase]; - Sym8xxWriteRegs( chipBaseAddr, DSP, DSP_SIZE, scriptRestartAddr ); - - if ( resetSRB ) - { - resetSRB->srbReturnCode = kIOReturnBusy; - Sym8xxCompleteSRB( resetSRB ); - resetSRB = 0; - } - else if ( initialReset == true ) - { - initialReset = false; - } - else - { - resetOccurred(); - } -} - -/*-----------------------------------------------------------------------------* - * This routine sets the SIGP bit in the script engine's ISTAT - * register. This signals the script to wake-up for a WAIT for - * reselection instruction. The script will then check the mailboxes - * for work to do. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxSignalScript( SRB *srb ) -{ - Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, SIGP ); -} - -/*-----------------------------------------------------------------------------* - * - * - * - * - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxCheckRequestSense( SRB *srb ) -{ - IOSCSIParallelCommand *scsiCommand; - IOMemoryDescriptor *reqSenseDesc; - - scsiCommand = srb->scsiCommand; - - scsiCommand->getPointers( &reqSenseDesc, 0, 0, true ); - - if ( reqSenseDesc != 0 ) - { - Sym8xxCancelMailBox( srb->target, srb->lun, true ); - } -} - -/*-----------------------------------------------------------------------------* - * This routine does a mailbox abort. - * - * This type of abort is used for targets not currently connected to the SCSI Bus. - * - * The script will select the target and send a tag (if required) followed by the - * appropriate abort message (abort/abort-tag) - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxAbortBdr( SRB *srb ) -{ - IOAbortBdrMailBox abortMailBox; - - abortSRB = srb; - - /* - * Setup a script variable containing the abort information. - */ - abortMailBox.identify = srb->nexus.msgData[0]; - abortMailBox.tag = srb->nexus.msgData[1]; - abortMailBox.message = srb->nexus.msgData[2]; - abortMailBox.scsi_id = srb->target; - - SCRIPT_VAR(R_ld_AbortBdr_mailbox) = *(UInt32 *) &abortMailBox; - - Sym8xxSignalScript( srb ); -} - -/*-----------------------------------------------------------------------------* - * - * - * - * - *-----------------------------------------------------------------------------*/ -bool Sym8xxSCSIController::Sym8xxCancelMailBox( Nexus *nexusCancel ) -{ - Nexus *nexusPhys; - UInt32 i; - - nexusPhys = (Nexus *)OSSwapHostToLittleInt32( (UInt32)nexusCancel ); - for ( i=0; i < MAX_SCHED_MAILBOXES; i++ ) - { - if ( nexusPhys == adapter->schedMailBox[i] ) - { - adapter->schedMailBox[i] = (Nexus *)OSSwapHostToLittleInt32( kMailBoxCancel ); - return true; - } - } - return false; -} - - -/*-----------------------------------------------------------------------------* - * - * - * - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxCancelMailBox( UInt32 target, UInt32 lun, bool fReschedule ) -{ - UInt32 tag; - UInt32 tagPos; - UInt32 tagShift; - - UInt32 i; - - SRB *srb; - Nexus *nexus; - Nexus *nexusPhys; - - tagPos = offsetof(Nexus, tag) & 0x03; - tagShift = 24 - (tagPos << 3); - - for ( i=0; i < MAX_SCHED_MAILBOXES; i++ ) - { - nexusPhys = (Nexus *)OSSwapHostToLittleInt32( (UInt32)adapter->schedMailBox[i] ); - if ( (nexusPhys != (Nexus *)kMailBoxEmpty) && (nexusPhys != (Nexus *)kMailBoxCancel) ) - { - /* - * Read the 'tag' byte given Nexus physical address from the mailBox. - * Look-up the virtual address of the corresponding Nexus struct. - */ - tag = ml_phys_read((UInt32)&nexusPhys->tag - tagPos); - tag = (tag >> tagShift) & 0xff; - - nexus = adapter->nexusPtrsVirt[tag]; - if ( nexus == (Nexus *)-1 ) - { - continue; - } - - /* - * If the SCSI target of the mailbox entry matches the abort SRB target, - * then we may have a winner. - */ - srb = (SRB *)((UInt32)nexus - offsetof(SRB, nexus)); - - if ( srb->target == target ) - { - /* - * For a device reset, we cancel all requests for that target regardless of lun. - * For an abort all, we must match on both target and lun - */ - if ( (lun == (UInt32)-1) || (srb->lun == lun) ) - { - adapter->schedMailBox[i] = (Nexus *)OSSwapHostToLittleInt32( kMailBoxCancel ); - - if ( fReschedule == true ) - { - rescheduleCommand( srb->scsiCommand ); - } - } - } - } - } -} - -/*-----------------------------------------------------------------------------* - * This routine is used to shutdown the script engine in an orderly fashion. - * - * Normally the script engine automatically stops when an interrupt is generated. However, - * in the case of timeouts we need to change the script engine's dsp reg (instruction pointer). - * to issue an abort. - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxAbortScript() -{ - mach_timespec_t currentTime; - mach_timespec_t startTime; - - getWorkLoop()->disableAllInterrupts(); - - /* - * We set the ABRT bit in ISTAT and spin until the script engine acknowledges the - * abort or we timeout. - */ - Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, ABRT ); - - IOGetTime( &startTime ); - - do - { - IOGetTime( ¤tTime ); - SUB_MACH_TIMESPEC( ¤tTime, &startTime ); - - istatReg = Sym8xxReadRegs( chipBaseAddr, ISTAT, ISTAT_SIZE ); - - if ( istatReg & SIP ) - { - Sym8xxReadRegs( chipBaseAddr, SIST, SIST_SIZE ); - continue; - } - - if ( istatReg & DIP ) - { - Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, 0x00 ); - Sym8xxReadRegs( chipBaseAddr, DSTAT, DSTAT_SIZE ); - break; - } - } - while ( currentTime.tv_nsec < (kAbortScriptTimeoutMS * 1000 * 1000) ); - - istatReg = SIGP; - Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, istatReg ); - - getWorkLoop()->enableAllInterrupts(); - - if ( currentTime.tv_nsec >= (kAbortScriptTimeoutMS * 1000 * 1000) ) - { - IOLog( "SCSI(Symbios8xx): Abort script failed - resetting bus\n\r" ); - } - - } - - diff --git a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxInit.cpp b/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxInit.cpp deleted file mode 100644 index 64bb689de..000000000 --- a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxInit.cpp +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* Sym8xxInit.m created by russb2 on Sat 30-May-1998 */ - -/*-----------------------------------------------------------------------------* - * This module contains initialization routines for the driver. - * - * Driver initialization consists of: - * - * - Doing PCI bus initialization for the script engine PCI device. - * - Setting up shared communication areas in system memory between the script - * and the driver. - * - Copying the script program into the script engine on-board ram, applying - * script relocation fixups as required. - * - Setting the initial register values for the script engine. - * - Setting up driver related storage and interfacing with driverKit. - * - *-----------------------------------------------------------------------------*/ - -/* - * This define causes Sym8xxScript.h to include the script instructions and - * relocation tables. Normally without this define we only will get #define - * values for interfacing with the script. - */ -#define INCL_SCRIPT_TEXT - -#include "Sym8xxController.h" - -#define super IOSCSIParallelController - -OSDefineMetaClassAndStructors( Sym8xxSCSIController, IOSCSIParallelController ) ; - -/*-----------------------------------------------------------------------------* - * This structure contains most of the inital register settings for - * the script engine. See Sym8xxRegs.h for the actual initialization - * values. - * - *-----------------------------------------------------------------------------*/ -typedef struct ChipInitRegs -{ - UInt32 regNum; - UInt32 regSize; - UInt32 regValue; - -} ChipInitRegs; - -static ChipInitRegs Sym8xxInitRegs[] = -{ - { SCNTL0, SCNTL0_SIZE, SCNTL0_INIT }, - { SCNTL1, SCNTL1_SIZE, SCNTL1_INIT }, - { SCNTL2, SCNTL2_SIZE, SCNTL2_INIT }, - { SCNTL3, SCNTL3_SIZE, SCNTL3_INIT_875 }, - { SXFER, SXFER_SIZE, SXFER_INIT }, - { SDID, SDID_SIZE, SDID_INIT }, - { GPREG, GPREG_SIZE, GPREG_INIT }, - { SFBR, SFBR_SIZE, SFBR_INIT }, - { SOCL, SOCL_SIZE, SOCL_INIT }, - { DSA, DSA_SIZE, DSA_INIT }, - { ISTAT, ISTAT_SIZE, ISTAT_INIT }, - { TEMP, TEMP_SIZE, TEMP_INIT }, - { CTEST0, CTEST0_SIZE, CTEST0_INIT }, - { CTEST3, CTEST3_SIZE, CTEST3_INIT_A }, - { CTEST4, CTEST4_SIZE, CTEST4_INIT }, - { CTEST5, CTEST5_SIZE, CTEST5_INIT_A_revB}, - { DBC, DBC_SIZE, DBC_INIT }, - { DCMD, DCMD_SIZE, DCMD_INIT }, - { DNAD, DNAD_SIZE, DNAD_INIT }, - { DSPS, DSPS_SIZE, DSPS_INIT }, - { SCRATCHA, SCRATCHA_SIZE, SCRATCHA_INIT }, - { DMODE, DMODE_SIZE, DMODE_INIT_A }, - { DIEN, DIEN_SIZE, DIEN_INIT }, - { DWT, DWT_SIZE, DWT_INIT }, - { DCNTL, DCNTL_SIZE, DCNTL_INIT_A }, - { SIEN, SIEN_SIZE, SIEN_INIT }, - { SLPAR, SLPAR_SIZE, SLPAR_INIT }, - { MACNTL, MACNTL_SIZE, MACNTL_INIT }, - { GPCNTL, GPCNTL_SIZE, GPCNTL_INIT }, - { STIME0, STIME0_SIZE, STIME0_INIT }, - { STIME1, STIME1_SIZE, STIME1_INIT }, - { RESPID0, RESPID0_SIZE, RESPID0_INIT }, - { RESPID1, RESPID1_SIZE, RESPID1_INIT }, - { STEST2, STEST2_SIZE, STEST2_INIT }, - { STEST3, STEST3_SIZE, STEST3_INIT }, - { SODL, SODL_SIZE, SODL_INIT }, - { SCRATCHB, SCRATCHB_SIZE, SCRATCHB_INIT } -}; - -/*-----------------------------------------------------------------------------* - * - * - *-----------------------------------------------------------------------------*/ -bool Sym8xxSCSIController::configure( IOService *forProvider, SCSIControllerInfo *controllerInfo ) -{ - provider = (IOPCIDevice *)forProvider; - - if ( Sym8xxInit() == false ) - { - return false; - } - - initialReset = true; - - Sym8xxSCSIBusReset( 0 ); - IOSleep(3000); - - controllerInfo->initiatorId = 7; - - controllerInfo->maxTargetsSupported = 16; - controllerInfo->maxLunsSupported = 8; - - controllerInfo->minTransferPeriodpS = (chipId == kChipIdSym875) ? 50000 : 0; - controllerInfo->maxTransferOffset = (chipId == kChipIdSym875) ? 16 : 0; - controllerInfo->maxTransferWidth = 2; - - controllerInfo->maxCommandsPerController = 0; - controllerInfo->maxCommandsPerTarget = 0; - controllerInfo->maxCommandsPerLun = 0; - - controllerInfo->tagAllocationMethod = kTagAllocationPerController; - controllerInfo->maxTags = 128; - - controllerInfo->commandPrivateDataSize = sizeof( SRB ); - controllerInfo->targetPrivateDataSize = 0; - controllerInfo->lunPrivateDataSize = 0; - - controllerInfo->disableCancelCommands = false; - - return true; -} - - -/*-----------------------------------------------------------------------------* - * Script Initialization - * - *-----------------------------------------------------------------------------*/ -bool Sym8xxSCSIController::Sym8xxInit() -{ - /* - * Perform PCI related initialization - */ - if ( Sym8xxInitPCI() == false ) - { - return false; - } - - /* - * Allocate/initialize driver resources - */ - if ( Sym8xxInitVars() == false ) - { - return false; - } - - /* - * Initialize the script engine registers - */ - if ( Sym8xxInitChip() == false ) - { - return false; - } - - /* - * Apply fixups to script and copy script to script engine's on-board ram - */ - if ( Sym8xxInitScript() == false ) - { - return false; - } - - getWorkLoop()->enableAllInterrupts(); - - /* - * Start script execution - */ - Sym8xxWriteRegs( chipBaseAddr, DSP, DSP_SIZE, (UInt32) &chipRamAddrPhys[Ent_select_phase] ); - - return true; -} - -/*-----------------------------------------------------------------------------* - * Script engine PCI initialization - * - * This routine determines the chip version/revision, enables the chip address - * ranges and allocates a virtual mapping to the script engine's registers and - * on-board ram. - *-----------------------------------------------------------------------------*/ -bool Sym8xxSCSIController::Sym8xxInitPCI() -{ - unsigned long pciReg0, pciReg8; - UInt32 chipRev; - UInt32 n; - UInt32 ramReg; - OSString *matchEntry; - - - /* - * Determine the number of memory ranges for the PCI device. - * - * The hardware implementation may or may not have a ROM present - * accounting for the difference in the number of ranges. - */ - n = provider->getDeviceMemoryCount(); - if ( !( n == 3 || n == 4 ) ) - { - return false; - } - - /* - * Determine the hardware version. Check the deviceID and - * RevID in the PCI config regs. - */ - pciReg0 = provider->configRead32( 0x00 ); - pciReg8 = provider->configRead32( 0x08 ); - - chipId = pciReg0 >> 16; - chipRev = pciReg8 & 0xff; - -// IOLog( "SCSI(Symbios8xx): Chip Id = %04x Chip rev = %02x\n\r", chipId, chipRev ); - - - ioMapRegs = provider->mapDeviceMemoryWithRegister( 0x14 ); - if ( ioMapRegs == 0 ) - { - return false; - } - - switch ( chipId ) - { - case kChipIdSym875: - ramReg = 0x18; - break; - - case kChipIdSym895: - case kChipIdSym896: - case kChipIdSym1010: - ramReg = 0x1C; - break; - - default: - ramReg = 0x1C; - } - - ioMapRam = provider->mapDeviceMemoryWithRegister( ramReg ); - if ( ioMapRam == 0 ) - { - return false; - } - - /* - * Assume 80Mhz external clock rate for motherboard 875 implementations - * and 40Mhz for others. - */ - matchEntry = OSDynamicCast( OSString, getProperty( gIONameMatchedKey ) ); - if ( matchEntry == 0 ) - { - IOLog("SCSI(Sym8xx): Cannot obtain matching property.\n"); - return false; - } - - if ( matchEntry->isEqualTo( "apple53C8xx" ) == true ) - { - chipClockRate = CLK_80MHz; - } - else - { - chipClockRate = CLK_40MHz; - } - - /* - * BUS MASTER, MEM I/O Space, MEM WR & INV - */ - provider->configWrite32( 0x04, 0x16 ); - - /* - * set Latency to Max , cache 32 - */ - provider->configWrite32( 0x0C, 0x2008 ); - - /* - * get chip register block mapped into pci memory - */ - chipBaseAddr = (UInt8 *)ioMapRegs->getVirtualAddress(); - chipBaseAddrPhys = (UInt8 *)ioMapRegs->getPhysicalAddress(); - -// kprintf( "SCSI(Symbios8xx): Chip Base addr = %08x(p) %08x(v)\n\r", -// (UInt32)chipBaseAddrPhys, (UInt32)chipBaseAddr ); - - chipRamAddr = (UInt8 *)ioMapRam->getVirtualAddress(); - chipRamAddrPhys = (UInt8 *)ioMapRam->getPhysicalAddress(); - -// kprintf( "SCSI(Symbios8xx): Chip Ram addr = %08x(p) %08x(v)\n\r", -// (UInt32)chipRamAddrPhys, (UInt32)chipRamAddr ); - - /* - * Attach interrupt - */ - interruptEvent = IOInterruptEventSource::interruptEventSource( - (OSObject *) this, - (IOInterruptEventAction) &Sym8xxSCSIController::interruptOccurred, - (IOService *) provider, - (int) 0 ); - - if ( interruptEvent == NULL ) - { - return false; - } - - getWorkLoop()->addEventSource( interruptEvent ); - - interruptEvent->enable(); - - /* - * - */ - memoryCursor = IOBigMemoryCursor::withSpecification( 16*1024*1024, 0xffffffff ); - if ( memoryCursor == NULL ) - { - return false; - } - - - - return true; -} - -/*-----------------------------------------------------------------------------* - * This routine allocates/initializes shared memory for communication between - * the script and the driver. In addition other driver resources semaphores, - * queues are initialized here. - * - *-----------------------------------------------------------------------------*/ -bool Sym8xxSCSIController::Sym8xxInitVars() -{ - UInt32 i; - - adapter = (AdapterInterface *)IOMallocContiguous( page_size, page_size, (IOPhysicalAddress *)&adapterPhys ); - if ( adapter == 0 ) - { - return false; - } - bzero( adapter, page_size ); - - /* - * We keep two copies of the Nexus pointer array. One contains physical addresses and - * is located in the script/driver shared storage. The other copy holds the corresponding - * virtual addresses to the active Nexus structures and is located in the drivers instance - * data. - * Both tables can be accessed through indirect pointers in the script/driver communication - * area. This is the preferred method to access these arrays. - */ - adapter->nexusPtrsVirt = (Nexus **)nexusArrayVirt; - adapter->nexusPtrsPhys = (Nexus **)adapter->nexusArrayPhys; - - for (i=0; i < MAX_SCSI_TAG; i ++ ) - { - adapter->nexusPtrsVirt[i] = (Nexus *) -1; - adapter->nexusPtrsPhys[i] = (Nexus *) -1; - } - - /* - * The script/driver communication area also contains a 16-entry table clock - * settings for each target. - */ - for (i=0; i < MAX_SCSI_TARGETS; i++ ) - { - adapter->targetClocks[i].scntl3Reg = SCNTL3_INIT_875; - } - - - return true; -} - - -/*-----------------------------------------------------------------------------* - * This routine makes a temporary copy of the script program, applies script fixups, - * initializes the script local data table at the top of the script image, and - * copies the modified script image to the script engine's on-board ram. - * - *-----------------------------------------------------------------------------*/ -bool Sym8xxSCSIController::Sym8xxInitScript() -{ - UInt32 i; - UInt32 scriptPgm[sizeof(BSC_SCRIPT)/sizeof(UInt32)]; - - /* - * Make a copy of the script - */ - bcopy( BSC_SCRIPT, scriptPgm, sizeof(scriptPgm) ); - bzero( scriptPgm, R_ld_size ); - - /* - * Apply fixups to the script copy - */ - for ( i=0; i < sizeof(Rel_Patches)/sizeof(UInt32); i++ ) - { - scriptPgm[Rel_Patches[i]] += (UInt32)chipRamAddrPhys; - } - for ( i=0; i < sizeof(LABELPATCHES)/sizeof(UInt32); i++ ) - { - scriptPgm[LABELPATCHES[i]] += (UInt32)chipRamAddrPhys; - } - - /* - * Initialize the script working variables with pointers to the script/driver - * communications area. - */ - scriptPgm[R_ld_sched_mlbx_base_adr >> 2] = (UInt32)&adapterPhys->schedMailBox; - scriptPgm[R_ld_nexus_array_base >> 2] = (UInt32)&adapterPhys->nexusArrayPhys; - scriptPgm[R_ld_device_table_base_adr >> 2] = (UInt32)&adapterPhys->targetClocks; - - /* - * Load the script image into the script engine's on-board ram. - */ - Sym8xxLoadScript( (UInt32 *)scriptPgm, sizeof(scriptPgm)/sizeof(UInt32) ); - - return true; -} - - -/*-----------------------------------------------------------------------------* - * This routine transfers the script program image into the script engine's - * on-board ram - * - *-----------------------------------------------------------------------------*/ -void Sym8xxSCSIController::Sym8xxLoadScript( UInt32 *scriptPgm, UInt32 scriptWords ) -{ - UInt32 i; - volatile UInt32 *ramPtr = (volatile UInt32 *)chipRamAddr; - - for ( i = 0; i < scriptWords; i++ ) - { - ramPtr[i] = OSSwapHostToLittleInt32(scriptPgm[i]); - } -} - -/*-----------------------------------------------------------------------------* - * This routine initializes the script engine's register block. - * - *-----------------------------------------------------------------------------*/ -bool Sym8xxSCSIController::Sym8xxInitChip() -{ - UInt32 i; - - /* - * Reset the script engine - */ - Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, RST ); - IODelay( 25 ); - Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, ISTAT_INIT ); - - /* - * Load our canned register values into the script engine - */ - for ( i = 0; i < sizeof(Sym8xxInitRegs)/sizeof(ChipInitRegs); i++ ) - { - Sym8xxWriteRegs( chipBaseAddr, Sym8xxInitRegs[i].regNum, Sym8xxInitRegs[i].regSize, Sym8xxInitRegs[i].regValue ); - IODelay( 10 ); - } - - /* - * For hardware implementations that have a 40Mhz SCLK input, we enable the chip's on-board - * clock doubler to bring the clock rate upto 80Mhz which is required for Ultra-SCSI timings. - */ - if ( chipClockRate == CLK_40MHz ) - { - /* - * Clock doubler setup for 875 (rev 3 and above). - */ - /* set clock doubler enabler bit */ - Sym8xxWriteRegs( chipBaseAddr, STEST1, STEST1_SIZE, STEST1_INIT | DBLEN); - IODelay(30); - /* halt scsi clock */ - Sym8xxWriteRegs( chipBaseAddr, STEST3, STEST3_SIZE, STEST3_INIT | HSC ); - IODelay(10); - Sym8xxWriteRegs( chipBaseAddr, SCNTL3, SCNTL3_SIZE, SCNTL3_INIT_875); - IODelay(10); - /* set clock doubler select bit */ - Sym8xxWriteRegs( chipBaseAddr, STEST1, STEST1_SIZE, STEST1_INIT | DBLEN | DBLSEL); - IODelay(10); - /* clear hold on scsi clock */ - Sym8xxWriteRegs( chipBaseAddr, STEST3, STEST3_SIZE, STEST3_INIT); - } - - /* - * Set our host-adapter ID in the script engine's registers - */ - initiatorID = kHostAdapterSCSIId; - - if ( initiatorID > 7 ) - { - Sym8xxWriteRegs( chipBaseAddr, RESPID1, RESPID1_SIZE, 1 << (initiatorID-8)); - } - else - { - Sym8xxWriteRegs( chipBaseAddr, RESPID0, RESPID0_SIZE, 1 << initiatorID); - } - - Sym8xxWriteRegs( chipBaseAddr, SCID, SCID_SIZE, SCID_INIT | initiatorID ); - - return true; -} - - diff --git a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxInterface.h b/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxInterface.h deleted file mode 100644 index cc031da5f..000000000 --- a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxInterface.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* Sym8xxInterface.h created by russb2 on Sat 30-May-1998 */ - -/* - * This file contains shared data structures between the script and the driver - * - */ - -#define MAX_SCSI_TARGETS 16 -#define MAX_SCSI_LUNS 8 -#define MAX_SCSI_TAG 256 -#define MIN_SCSI_TAG 128 - -#define kHostAdapterSCSIId 7 - -#define MAX_SCHED_MAILBOXES 256 -#define kMailBoxEmpty 0 -#define kMailBoxCancel 1 - -#define kSCSITimerIntervalMS 250 -#define kReqSenseTimeoutMS 3000 -#define kAbortTimeoutMS 3000 -#define kResetQuiesceDelayMS 3000 -#define kAbortScriptTimeoutMS 50 - -/* - * NEXUS DATA Structure - * - * The Nexus structure contains per-request information for the script/driver - * to execute a SCSI request. - */ - -typedef struct SGEntry -{ - UInt32 length; - UInt32 physAddr; -} SGEntry; - -/* - * Note: There are (3) SG List entries reserved for use by the driver, - * i.e SG Entries 0-1 and the last entry in the list. - */ -#define MAX_SGLIST_ENTRIES (64+3) - -/* - * This part of the Nexus structure contains the script engine clock registers to - * be used for this request. This information is also contained in the per-target - * table (AdapterInterface->targetClocks). - */ -typedef struct NexusParms -{ - UInt8 reserved_1; - UInt8 sxferReg; - UInt8 target; - UInt8 scntl3Reg; -} NexusParms; - -/* - * Pointers in the Nexus to our CDB/MsgOut data are in this format. - */ -typedef struct NexusData -{ - UInt32 length; - UInt32 ppData; -} NexusData; - -typedef struct Nexus Nexus; -struct Nexus -{ - NexusParms targetParms; - - SGEntry *ppSGList; - - NexusData msg; - NexusData cdb; - - UInt32 currentDataPtr; - UInt32 savedDataPtr; - - UInt8 tag; - UInt8 dataXferCalled; - UInt8 wideResidCount; - UInt8 reserved_1[1]; - - /* - * Data buffers for nexus - */ - UInt8 cdbData[16]; - UInt8 msgData[16]; - UInt32 sgNextIndex; - SGEntry sgListData[MAX_SGLIST_ENTRIES]; - -}; - -/* - * Abort Bdr Mailbox - * - * The mailbox is used to send an Abort or Bus Device Reset to a device - * This mailbox is 4 bytes long, and all the necessary information are - * contained in this mailbox (No nexus Data associated) - */ -typedef struct IOAbortBdrMailBox -{ - UInt8 identify; /* Identify msg (0xC0) if Abort A0 */ - UInt8 tag; /* Tag Message or Zero A1 */ - UInt8 scsi_id; /* SCSI id of the target of the request A2 */ - UInt8 message; /* Abort(0x06) or Bdr(0x0C) or AbortTag (0x0D) A3 */ -} IOAbortBdrMailBox; - -/* - * IODone mailbox - * - * This mailbox is used to signal the completion of an I/O to the driver. - */ - -typedef struct IODoneMailBox -{ - UInt8 nexus; /* Nexus of the completed I/O */ - UInt8 status; /* Status of the completed I/O */ - UInt8 zero; - UInt8 semaphore; /* If set, these contents are valid */ -} IODoneMailBox; - -/* - * Adapter Interface - * - * This structure contains the shared data between the script and - * the driver. The script's local variable table is updated to point to the - * physical addresses of the data in this control block. - */ - -typedef struct TargetClocks -{ - UInt8 reserved_1; - UInt8 sxferReg; - UInt8 reserved_2; - UInt8 scntl3Reg; -} TargetClocks; - -typedef struct AdapterInterface -{ - Nexus **nexusPtrsVirt; - Nexus **nexusPtrsPhys; - - Nexus *nexusArrayPhys[MAX_SCSI_TAG]; /* Active SRBs or -1 */ - Nexus *schedMailBox[MAX_SCHED_MAILBOXES]; /* New SRBs */ - TargetClocks targetClocks[MAX_SCSI_TARGETS]; - - UInt32 xferSWideInst[4]; - -} AdapterInterface; - -#define SCRIPT_VAR(x) ( *(UInt32 *)(chipRamAddr+(x)) ) diff --git a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxMisc.cpp b/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxMisc.cpp deleted file mode 100644 index 17d179caf..000000000 --- a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxMisc.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* Sym8xxMisc.m created by russb2 on Sat 30-May-1998 */ - -#include "Sym8xxController.h" - -/* - * Miscellaneous IO worker routines - */ - -UInt32 Sym8xxSCSIController::Sym8xxReadRegs( volatile UInt8 *chipRegs, UInt32 regOffset, UInt32 regSize ) -{ - if ( regSize == 1 ) - { - return chipRegs[regOffset]; - } - if ( regSize == 2 ) - { - return OSSwapHostToLittleInt16( *(volatile u_int16_t *)&chipRegs[regOffset] ); - } - else if (regSize == 4 ) - { - return OSSwapHostToLittleInt32( *(volatile UInt32 *)&chipRegs[regOffset] ); - } - else - { - kprintf("SCSI(SymBios875): Sym8xxReadRegs incorrect regSize\n\r" ); - return 0; - } -} - -void Sym8xxSCSIController::Sym8xxWriteRegs( volatile UInt8 *chipRegs, UInt32 regOffset, UInt32 regSize, UInt32 regValue ) -{ - if ( regSize == 1 ) - { - chipRegs[regOffset] = regValue; - } - else if ( regSize == 2 ) - { - volatile u_int16_t *p = (volatile u_int16_t *)&chipRegs[regOffset]; - *p = OSSwapHostToLittleInt16( regValue ); - } - else if ( regSize == 4 ) - { - volatile UInt32 *p = (volatile UInt32 *)&chipRegs[regOffset]; - *p = OSSwapHostToLittleInt32( regValue ); - } - else - { - kprintf("SCSI(SymBios875): Sym8xxWriteRegs incorrect regSize\n\r" ); - } - eieio(); -} diff --git a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxRegs.h b/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxRegs.h deleted file mode 100644 index fd8102606..000000000 --- a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxRegs.h +++ /dev/null @@ -1,556 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * Copyright (c) 1998 Apple Computer Inc. - * - * Symbios8xx Controller. - * - */ - -/* SymBios 8xx register addressing definitions */ - -#define SCNTL0_SIZE 0x01 -#define SCNTL0 0x00000000 -#define SCNTL0_INIT 0xCA /* Scsi control 0 */ - /* ARB1 1 */ - /* ARB0 1 : Full arbitration */ - /* START 0 : Start sequence */ - /* WATN 0 : Select with ATN */ - /* EPC 1 : enable SCSI bus parity checking */ - /* RES */ - /* AAP 1 : Assert ATN on SCSI parity error */ - /* TRG 0 : Target mode. 720 is Initiator */ - -#define SCNTL1_SIZE 0x01 -#define SCNTL1 0x00000001 -#define SCNTL1_INIT 0x00 /* Scsi control 1 */ - /* EXC 0 : Extra clock cycle data setup (Sdtr) */ - /* ADB 0 : Assert SCSI data bus */ - /* DHP 0 : Target only Disable halt parity error */ - /* CON 0 : 820 connected to SCSI bus */ - /* RST 0 : Assert SCSI RST signal */ - /* AESP 0 : Force bad parity */ - /* IARB 0 : Immediate arbitration */ - /* SST 0 : Start SCSI transfer */ - -#define SCNTL1_SCSI_RST 0x08 /* force scsi reset in scntl1 reg */ - -#define SCNTL2_SIZE 0x01 -#define SCNTL2 0x00000002 -#define SCNTL2_INIT 0x00 /* Scsi control 2 */ - #define SDU 0x80 /* SDU 0 : SCSI Disconnect Unexpected */ - #define CHM 0x40 /* CHM 0 : Chained mode */ - #define SLPMD 0x40 /* SLPMD 0 : SLPAR Mode Bit */ - #define SLPHBEN 0x40 /* SLPHBEN : SLPAR High Byte Enable */ - #define WSS 0x08 /* WSS 0 : Wide Scsi Send */ - #define VUE0 0x40 /* VUE0 : Vendor Uniq Enhancements Bit 0 */ - #define VUE1 0x40 /* VUE1 : Vendor Uniq Enhancements Bit 1 */ - #define WSR 0x01 /* WSR 0 : Wide Scsi Receive */ - -#define SCNTL3_SIZE 0x01 -#define SCNTL3 0x00000003 -#define SCNTL3_INIT 0x03 /* Scsi control 3 for 40Mhz sys clock */ -#define SCNTL3_INIT_875 0x05 /* Scsi control 3 for 80Mhz sys clock */ -#define SCNTL3_INIT_875_ULTRA 0x95 /* Scsi control 3 for 80Mhz sys clock */ -#define SCNTL3_INIT_875_FAST 0x35 /* Scsi control 3 for 80Mhz sys clock */ -#define SCNTL3_INIT_875_SLOW 0x55 /* Scsi control 3 for 80Mhz sys clock */ - /* RES */ - #define SCF 0x70 /* SCF 0 : Sync clock conversion factor 0-2 */ - #define EWS 0x08 /* EWS 0 : Enable Wide SCSI (wdtr) */ - #define CCF 0x07 /* CCF 0 : Async clock conversion factor 0-2 */ - -#define SCID_SIZE 0x01 -#define SCID 0x00000004 -#define SCID_INIT 0x40 /* Scsi chip Id */ - /* RES */ - /* RRE 1 : Enable response to reselection */ - /* SRE 0 : Disable response to selection */ - /* RES */ - /* ID3 0 */ - /* ID2 0 */ - /* ID1 0 */ - /* ID0 0 : Encoded 53825 chip SCSI Id */ - -#define SXFER_SIZE 0x01 -#define SXFER 0x00000005 -#define SXFER_INIT 0x00 /* Scsi Transfer */ - /* TP2 0 */ - /* TP1 0 */ - /* TP0 0 : Scsi sync Transfer Period (4)(Sdtr) */ - /* RES */ - /* MO3 0 */ - /* MO2 0 */ - /* MO1 0 */ - /* MO0 0 : Max Scsi Sync ReqAck offset (async) (Sdtr) */ - -#define SDID_SIZE 0x01 -#define SDID 0x00000006 -#define SDID_INIT 0x00 /* Scsi destination Id */ - /* RES */ - /* RES */ - /* RES */ - /* RES */ - /* ID3 0 */ - /* ID2 0 */ - /* ID1 0 */ - /* ID0 0 : Encoded destination Scsi Id */ - -#define GPREG_SIZE 0x01 -#define GPREG 0x00000007 -#define GPREG_INIT 0x00 /* Read/write general purpose */ -#define GPIO3 0x08 /* GPIO bit 3 */ - /* RES */ - /* RES */ - /* RES */ - /* GPO 0 : General purpose output */ - /* GPI3 0 */ - /* GPI2 0 */ - /* GPI1 0 */ - /* GPI0 0 : General purpose inputs */ - -#define SFBR_SIZE 0x01 -#define SFBR 0x00000008 -#define SFBR_INIT 0x00 - /* SCSI First Byte Received */ - -#define SOCL_SIZE 0x01 -#define SOCL 0x00000009 -#define SOCL_INIT 0x00 - #define SREQ 0x80 /* REQ 0 : Assert SCSI REQ signal */ - #define SACK 0x40 /* ACK 0 : ACK */ - #define SBSY 0x20 /* BSY 0 : BSY */ - #define SSEL 0x10 /* SEL 0 : SEL */ - #define SATN 0x08 /* ATN 0 : ATN */ - #define SMSG 0x04 /* MSG 0 : MSG */ - #define SC_D 0x02 /* C/D 0 : C/D */ - #define SI_O 0x01 /* I/O 0 : I/O */ - -#define SSID_SIZE 0x01 -#define SSID 0x0000000A /* Read Only */ - /* VAL Scsi Valid Bit */ - /* RES */ - /* RES */ - /* RES */ - /* ID3 */ - /* ID2 */ - /* ID1 */ - /* ID0 Encoded Destination Scsi Id */ - -#define SBCL_SIZE 0x01 -#define SBCL 0x0000000B /* Scsi Bus Control Lines Read only */ - /* REQ */ - /* ACK */ - /* BSY */ - /* SEL */ - /* ATN */ - /* MSG */ - /* C/D */ - /* I/O */ - -#define DSTAT_SIZE 0x01 -#define DSTAT 0x0000000C /* DMA status Read only */ - #define DFE 0x80 /* DSTAT DMA FIFO Empty */ - #define MDPE 0x40 /* Master Data Parity Error */ - #define BF 0x20 /* Bus Fault */ - #define DABRT 0x10 /* Abort occurred */ - #define SSI 0x08 /* Script Step Interrupt */ - #define SIR 0x04 /* Script Interrupt Inst Received */ -#ifdef notdef - #define WTD 0x02 /* was watchdog timer, now reserved */ -#endif /* notdef */ - #define IID 0x01 /* Illegal Instruction Detected */ - -#define SSTAT0_SIZE 0x01 -#define SSTAT0 0x0000000D /* SCSI status zero Read only */ - #define ILF 0x80 /* ILF SIDL least significant byte full */ - #define ORF 0x40 /* ORF SODR least significant byte full */ - #define OLF 0x20 /* OLF SODL least significant byte full */ - #define AIP 0x10 /* AIP Arbitration in progress */ - #define LOA 0x08 /* LOA Lost arbitration */ - #define WOA 0x04 /* WOA Won arbitration */ - #define RSTB 0x02 /* RST Scsi reset signal */ - #define SDP0 0x01 /* SDP0 Scsi SDP0 parity signal */ - -#define SSTAT1_SIZE 0x01 -#define SSTAT1 0x0000000E /* SCSI status one Read only */ - /* FF3-0 Bytes or word in the Scsi FIFO */ - /* SDP Latched Scsi parity */ - /* MSG Scsi phase status */ - /* C/D */ - /* I/O */ - -#define SSTAT2_SIZE 0x01 -#define SSTAT2 0x0000000F /* Scsi status two Read only */ - #define ILF1 0x80 /* ILF1 SIDL most significant byte full */ - #define ORF1 0x40 /* ORF1 SODR " " " " */ - #define OLF1 0x20 /* OLF1 SODL " " " " */ - /* RES */ - #define SPL1 0x08 /* SPL1 Latched Scsi parity for SIDL15-8 */ - #define FF4 0x04 /* FIFO Flags Bit 4 */ - #define LDSC 0x02 /* LDSC Last disconnect */ - #define SDP1 0x01 /* SDP1 Scsi SDP1 Signal */ - -#define DSA_SIZE 0x04 -#define DSA 0x00000010 -#define DSA_INIT 0x00000000 /* Data structure address */ - -#define ISTAT_SIZE 0x01 -#define ISTAT 0x00000014 -#define ISTAT_INIT 0x00 /* Interrupt Status */ - #define ABRT 0x80 /* Abort Operation */ - #define RST 0x40 /* Software reset */ - #define SIGP 0x20 /* Signal process */ - #define SEM 0x10 /* Semaphore */ - #define ISTAT_CON 0X08 /* Connected to target. */ - #define INTF 0x04 /* Interrupt on the fly */ - #define SIP 0x02 /* SCSI Interrupt Pending */ - #define DIP 0x01 /* DMA Interrupt Pending */ - -#define CTEST0_SIZE 0x01 -#define CTEST0 0x00000018 -#define CTEST0_INIT 0x00 /* Chip test zero (now general purpose, rph) */ - -#define CTEST1_SIZE 0x01 -#define CTEST1 0x00000019 /* Chip test one Read only */ - /* FMT3-0 0 : Byte empty in DMA FIFO */ - /* FFL3-0 0 : Byte full in DMA FIFO */ - -#define CTEST2_SIZE 0x01 -#define CTEST2 0x0000001A /* Chip test two Read only */ - /* DDIR Data transfer direction (1 : Scsi bus -> host) */ - /* SIGP Signal process (Clear SIGP ISTAT when read) */ - /* CIO (read-only, indicates chip configured as I/O space) */ - /* CM (read-only, indicates configured as memory space) */ - /* RES */ - /* TEOP Scsi true end of process */ - /* DREQ Data request status */ - /* DACK Data acknowledge status */ - -#define CTEST3_SIZE 0x01 -#define CTEST3 0x0000001B -#define CTEST3_INIT 0x04 /* Chip test three */ -#define CTEST3_INIT_A 0x05 /* Chip test three for 'A' part */ - - #define VERS 0xf0 /* V3-0 0 : Chip revision level */ - #define FLF 0x08 /* FLF 0 : Flush DMA Fifo */ - #define CLF 0x04 /* CLF 1 : Clear DMA FIFO */ - #define FM 0x02 /* FM 0 : Fetch pin mode */ - #define WRIE 0x01 /* WRIE 1 : Write and Invalidate Enable, for 825A only!!! */ - -#define TEMP_SIZE 0x04 -#define TEMP 0x0000001C -#define TEMP_INIT 0x00000000 /* Tempory stack */ - -#define DFIFO_SIZE 0x01 -#define DFIFO 0x00000020 -#define DFIFO_INIT 0x00 /* DMA FIFO */ - /* upper bit used for 825 'A' part when using large fifo */ - /* BO6-0 0: Byte offset counter */ - -#define CTEST4_SIZE 0x01 -#define CTEST4 0x00000021 /* Chip test four */ -// #define CTEST4_INIT 0x80 /* Chip test four DISABLE BURST!! */ -#define CTEST4_INIT 0x00 /* Chip test four */ - /* BDIS 0 : set for Burst Disable, reset allows burst on data moves */ - /* ZMOD High impedance mode */ - /* ZSD Scsi high impedance mode */ - /* SRTM Shadow register test mode */ -/* NOT for bandit!!!! yes for NEW rev of Dumbarton LATER on, not initial!!! */ - /* MPEE 0 : Master Parity Error Enable Do we want this set???? rph */ - /* FBL2-0 Fifo byte control */ - -#define CTEST5_SIZE 0x01 -#define CTEST5 0x00000022 -#define CTEST5_INIT 0x00 /* Chip test five */ -#define CTEST5_INIT_A 0x00 /* Chip test five 'A' part, upper burst OFF */ -#define CTEST5_INIT_A_revB 0x24 /* Chip test five 'A' part, upper burst OFF - * also Enable 536 byte fifo */ - #define ADCK 0x80 /* ADCK 0 : Clock address incrementor */ - #define BBCK 0x40 /* BBCK 0 : Clock byte counter */ - #define DFS 0x20 /* DFS 0 : fifo size - 0=88 1=536 bytes */ - #define MASR 0x10 /* MASR 0 : Master control for set reset pulses */ - #define DDIR 0x08 /* DDIR 0 : DMA direction */ - #define BL2 0x04 /* BL2 0 : see DMODE bits 6,7 */ - #define BO89 0x03 /* BO89 0 : upper bits of DFIFO count */ - -#define CTEST6_SIZE 0x01 -#define CTEST6 0x00000023 -#define CTEST6_INIT 0x00 /* chip test six */ - /* 7-0 0 : DMA Fifo */ - -#define DBC_SIZE 0x04 -#define DBC 0x00000024 -#define DBC_INIT 0x000000 /* DMA Byte Counter */ - -#define DCMD_SIZE 0x01 -#define DCMD 0x00000027 -#define DCMD_INIT 0x00 /* DMA command */ - -#define DNAD_SIZE 0x04 -#define DNAD 0x00000028 -#define DNAD_INIT 0x00000000 /* DMA Next Data Address */ - -#define DSP_SIZE 0x04 -#define DSP 0x0000002C -#define DSP_INIT 0x00000000 /* DMA script pointer */ - -#define DSPS_SIZE 0x04 -#define DSPS 0x00000030 -#define DSPS_INIT 0x00000000 /* DMA SCRIPTS Pointer Save */ - -#define SCRATCHA_SIZE 0x04 -#define SCRATCHA 0x00000034 -#define SCRATCHA0 0x00000034 -#define SCRATCHA1 0x00000035 -#define SCRATCHA2 0x00000036 -#define SCRATCHA3 0x00000037 -#define SCRATCHA_INIT 0x04030201 /* general purpose register */ - -#define DMODE_SIZE 0x01 -#define DMODE 0x00000038 -/* 825 bug!!!!! 8 is max!!!!!!! rph 8-23-94 - */ -#define DMODE_INIT 0x82 /* DMA mode 8 burst xfers + instruc fetch */ -#define DMODE_INIT_A 0x0A /* DMA mode 32 burst xfers + instruc fetch */ - /* BL1 1 : Burst length, burst size is '8' transfers (4 bytes per) */ - /* BL0 0 : Burst length */ - /* SIOM 0 : Source I/O-Memory Enable (Memory space is default) */ - /* DIOM 0 : Destination I/O-Memory Enable (Memory space is default) */ - /* ER 1 : Enable Read Line Command, set for 825'A' part */ - /* ERM 0 : */ - /* BOF 1 : Burst Op Code Fetch Enable, only for 825!!! rph */ - /* MAN 0 : Manual start mode (leave 0 for auto-start with DSP write */ - -#define DIEN_SIZE 0x01 -#define DIEN 0x00000039 -#define DIEN_INIT 0x7D /* No mask on DMA interrupt */ - /* RES */ - /* MDPE 1 : Master Data Parity Error */ - /* BF 1 : Bus fault */ - /* ABRT 1 : Aborted */ - /* SSI 1 : Script step interrupt */ - /* SIR 1 : Script interrupt instruction received */ - /* RES */ - /* IID 1 : Illegal instruction detected */ - -#define DWT_SIZE 0x01 -#define DWT 0x0000003A -#define DWT_INIT 0xD0 /* DMA watchdog timer to 0xD0*32*BCLK ns*/ - -#define DCNTL_SIZE 0x01 -#define DCNTL 0x0000003B -#define DCNTL_INIT 0x01 /* DMA Control register */ -#define DCNTL_INIT_A 0xA1 /* DMA Control register, 'A' part */ - /* CLE 7: Cache Line Size Enable for 'A' part */ - /* PFF 6: pre-fetch flush bit for 'A' part */ - /* PFEN 5: pre-fetch Enable bit for 'A' part */ - /* RES */ - /* RES */ -#define SSM 0x10 /* 0 : Single step mode */ - /* IRQM 0 : HW driver type for IRQ pin, default is open drain, ask HW rph*/ -#define STD 0x04 /* 0 : start DMA operation */ - /* IRQ 1: IRQ disable for 'A' part */ - /* COM 1 : No Compatibility 700 */ - -#define ADDER_SIZE 0x04 -#define ADDER 0x0000003C /* Adder sum output Read only */ - -#define SIEN_SIZE 0x02 -#define SIEN 0x00000040 -#define SIEN_INIT_RST_OFF 0x048D /* SCSI Interrupt enable SIEN0-1 rph */ -#define SIEN_INIT 0x048F /* SCSI Interrupt enable SIEN0-1 rph */ -/* SIEN0 */ - /* M/A 1 : Scsi phase mismatch */ - /* CMP 0 : Function complete */ - /* SEL 0 : Selected */ - /* RSL 0 : Reselected */ - /* SGE 1 : Scsi Gross error */ - /* UDC 1 : Unexpected disconnect */ - /* RST 1 : Scsi Reset condition */ - /* PAR 1 : Scsi Parity error */ - - /* RES */ - /* RES */ - /* RES */ - /* RES */ - /* RES */ - /* STO 1 : (Re)Selection timeout */ - /* GEM 0 : General purpose timeout*/ - /* HTH 0 : Handshake timeout */ - -#define SIST_SIZE 0x02 -#define SIST 0x00000042 /* Scsi interrupt status Read only */ - /* idem SIEN reg */ - #define STO 0x0400 - #define GEN 0x0200 - #define HTH 0x0100 - - #define MA 0x0080 - #define CMP 0x0040 - #define SEL 0x0020 - #define RSL 0x0010 - #define SGE 0x0008 - #define UDC 0x0004 - #define RSTI 0x0002 - #define PAR 0x0001 - -#define SLPAR_SIZE 0x01 -#define SLPAR 0x00000044 -#define SLPAR_INIT 0x00 /* SCSI longitudinal parity */ - -#define SWIDE_SIZE 0x01 -#define SWIDE 0x00000045 /* Scsi wide residue data Read only */ - -#define MACNTL_SIZE 0x01 -#define MACNTL 0x00000046 -#define MACNTL_INIT 0x00 /* memory access control */ - /* TYP3-0 : Chip Type (read-only) */ - /* DataWr 0 : Data write Far memory */ - /* DataRd 0 : Data read far memory */ - /* Pointer to script fetch 0 : far memory */ - /* Script fetch 0 : far memory */ - -#define GPCNTL_SIZE 0x01 -#define GPCNTL 0x00000047 -#define GPCNTL_INIT 0x0F /* General purpose control Cf appendum ?? */ -// #define GPCNTL_INIT 0xCF /* General purpose control Cf appendum ?? */ - /* ME : 0 Master Enable */ - /* FE : 0 Fetch Enable */ - /* RES */ - /* GPI/O_en4 : 0 GPREG input or output */ - /* GPI/O_en3 : 1 */ - /* GPI/O_en2 : 1 */ - /* GPI/O_en1 : 1 */ - /* GPI/O_en0 : 1 */ - -#define STIME0_SIZE 0x01 -#define STIME0 0x00000048 -#define STIME0_INIT 0x0C /* Scsi timer register 0 */ - /* HTH3 */ - /* HTH2 */ - /* HTH1 0 */ - /* HTH0 0 : Handshake timer period (disabled) */ - /* SEL3 1 */ - /* SEL2 1 */ - /* SEL1 0 */ - /* SEL0 0 : Selection timeout period (204.8ms) */ - -#define STIME1_SIZE 0x01 -#define STIME1 0x00000049 -#define STIME1_INIT 0x00 /* Scsi timer register one */ - /* RES */ - /* RES */ - /* RES */ - /* RES */ - /* GEN3 0 */ - /* GEN2 0 */ - /* GEN1 0 */ - /* GEN0 0 : General purpose timer period (disabled) */ - -#define RESPID0_SIZE 0x01 -#define RESPID0 0x0000004A -#define RESPID0_INIT 0x00 /* Response Id zero */ - /* ID7 - ID0 */ - -#define RESPID1_SIZE 0x01 -#define RESPID1 0x0000004B -#define RESPID1_INIT 0x00 /* Response ID one */ - /* ID15 - ID8 */ - -#define STEST0_SIZE 0x01 -#define STEST0 0x0000004C /* Scsi test register zero Read only */ - /* RES */ - /* RES */ - /* RES */ - /* RES */ - /* SLT Selection response Logic test */ - /* ART Arbitration priority encoder test */ - /* SOZ Scsi synchronous offset zero */ - /* SOM Scsi synchronous offset maximum */ - -#define STEST1_SIZE 0x01 -#define STEST1 0x0000004D /* Scsi test register one Read/Write */ -#define STEST1_INIT 0x00 - #define SCLK 0x80 /* SCLK 0 : 1 = Use PCI Clock 0 = Use SCLK input */ - #define SISIO 0x40 /* SISIO 0 : SCSI Isolation Mode */ - /* 0 : */ - /* 0 : */ - #define DBLEN 0x08 /* DBLEN 0 : SCLK Doubler Enable */ - #define DBLSEL 0x04 /* DBLSEL 0 : SCLK Doubler Select */ - /* 0 : */ - /* 0 : */ - -#define STEST2_SIZE 0x01 -#define STEST2 0x0000004E -#define STEST2_INIT 0x00 /* Scsi Test register two */ -#define STEST2_DIFF_INIT 0x20 /* Scsi Test register two */ - #define SCE 0x80 /* SCE 0 : Scsi control enable */ - #define ROF 0x40 /* ROF 0 : Reset Scsi offset */ - #define DIF 0x20 /* DIF 0/1 : SCSI differential mode, set if we detect differential card */ - #define SLB 0x10 /* SLB 0 : Scsi loopback mode */ - #define SZM 0x08 /* SZM 0 : SCSI high impedance mode */ - #define AWS 0x04 /* AWS 0 : Always wide SCSI */ - #define EXT 0x02 /* EXT 0 : Extend REQ/ACK filtering NEVER want SET for 'fast'!!! */ - #define LOW 0x01 /* LOW 0 : Scsi low level mode */ - -#define STEST3_SIZE 0x01 -#define STEST3 0x0000004F -#define STEST3_INIT 0x92 /* Scsi test register 3 */ - #define EAN 0x80 /* EAN 1 : Enable active negation */ - #define STR 0x40 /* STR 0 : Scsi FIFO test read */ - #define HSC 0x20 /* HSC 0 : Halt Scsi Clock */ - #define DSI 0x10 /* DSI 1 : Disable single initiator response */ - /* RES */ - #define TTM 0x04 /* TTM 0 : Timer test mode */ - #define CSF 0x02 /* CSF 1 : Clear SCSI FIFO */ - #define STW 0x01 /* STW 0 : SCSI FIFO test write */ - -#define SSIDL_SIZE 0x02 -#define SSIDL 0x00000050 /* SCSI input data latch Read only */ - -#define SODL_SIZE 0x02 -#define SODL 0x00000054 -#define SODL_INIT 0x0000 /* SCSI Output Data Latch */ - -#define SBDL_SIZE 0x02 -#define SBDL 0x00000058 /* SCSI bus data line Read only */ - -#define SCRATCHB_SIZE 0x04 -#define SCRATCHB 0x0000005C -#define SCRATCHB0 0x0000005C -#define SCRATCHB1 0x0000005D -#define SCRATCHB2 0x0000005E -#define SCRATCHB3 0x0000005F -#define SCRATCHB_INIT 0x00000000 /* general purpose register */ - -/* ************************* */ - -/* Miscellaneous defines */ -#define CLK_40MHz 40 -#define CLK_80MHz 80 -#define kResetRecoveryTimeMS 5000 - -#define kChipIdSym875 0x000f -#define kChipIdSym895 0x000c -#define kChipIdSym896 0x000b -#define kChipIdSym1010 0x0020 diff --git a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxSRB.h b/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxSRB.h deleted file mode 100644 index b8cd76291..000000000 --- a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxSRB.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* Sym8xxSRB.h created by russb2 on Sat 30-May-1998 */ - -/* - * The SRB is the main per-request data structure used by the driver. - * - * It contains an embedded Nexus structure which is used as a per-request - * communication area between the script and the driver. - */ - -typedef struct SRB SRB; - -struct SRB -{ - SRB *srbPhys; - - IOSCSIParallelCommand *scsiCommand; - - UInt32 srbCDBFlags; - - IOReturn srbReturnCode; - SCSIAdapterStatus srbAdapterStatus; - UInt8 srbSCSIStatus; - - UInt8 srbMsgResid; - UInt8 srbMsgLength; - - UInt8 target; - UInt8 lun; - UInt8 tag; - - UInt8 negotiateSDTRComplete; - UInt8 negotiateWDTRComplete; - - UInt32 directionMask; - - IOMemoryDescriptor *xferDesc; - UInt32 xferOffset; - UInt32 xferOffsetPrev; - UInt32 xferCount; - UInt32 xferDone; - - Nexus nexus; - -}; - diff --git a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.h b/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.h deleted file mode 100644 index 5e2fc0bed..000000000 --- a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.h +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -typedef unsigned long ULONG; - -#ifdef INCL_SCRIPT_TEXT - -ULONG BSC_SCRIPT[] = { - 0x80000000L, 0x00000000L, - 0x80000000L, 0x00000000L, - 0x80000000L, 0x00000000L, - 0x80000000L, 0x00000000L, - 0x80000000L, 0x00000000L, - 0x80000000L, 0x00000000L, - 0x80000000L, 0x00000000L, - 0x80000000L, 0x00000000L, - 0x80000000L, 0x00000000L, - 0x80000000L, 0x0000004CL, - 0x80000000L, 0x0000000FL, - 0xE1340004L, 0x00000028L, - 0x60000400L, 0x00000000L, - 0x79340000L, 0x00000000L, - 0x79350000L, 0x00000000L, - 0x79340000L, 0x00000000L, - 0x79350000L, 0x00000000L, - 0xE0340004L, 0x0000009CL, - 0xE1100004L, 0x00000024L, - 0xF1100004L, 0x00000000L, - 0x72100000L, 0x00000000L, - 0x980C00FFL, 0x00000008L, - 0xE0100004L, 0x0000002CL, - 0x90080000L, 0x00000000L, - 0xE15C0004L, 0x00000020L, - 0x60000400L, 0x00000000L, - 0x795C0000L, 0x00000000L, - 0x795C0000L, 0x00000000L, - 0xE05C0004L, 0x000000F4L, - 0xE1100004L, 0x00000034L, - 0xF15C0004L, 0x00000000L, - 0x725D0000L, 0x00000000L, - 0x6A050000L, 0x00000000L, - 0x725F0000L, 0x00000000L, - 0x6A030000L, 0x00000000L, - 0x90080000L, 0x00000000L, - 0x7A1A0000L, 0x00000000L, - 0xE1340004L, 0x00000010L, - 0x72340000L, 0x00000000L, - 0x80840000L, 0x000005F0L, - 0xE1340004L, 0x0000000CL, - 0x60000400L, 0x00000000L, - 0x79340000L, 0x00000000L, - 0x79350000L, 0x00000000L, - 0x79340000L, 0x00000000L, - 0x79350000L, 0x00000000L, - 0xE0340004L, 0x0000018CL, - 0xE0340004L, 0x0000025CL, - 0xE1100004L, 0x00000018L, - 0xF1100004L, 0x00000000L, - 0xE0100004L, 0x0000002CL, - 0xE1340004L, 0x0000002CL, - 0x72340000L, 0x00000000L, - 0x808C0001L, 0x00000098L, - 0x72B50000L, 0x00000000L, - 0x72B60000L, 0x00000000L, - 0x72B70000L, 0x00000000L, - 0x808C0000L, 0x00000458L, - 0x785C0800L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0xE15C0004L, 0x00000004L, - 0xF15C0001L, 0x00000020L, - 0xE05C0004L, 0x00000028L, - 0xE1100004L, 0x0000002CL, - 0xF15E0001L, 0x00000002L, - 0x725E0000L, 0x00000000L, - 0x6A5C0000L, 0x00000000L, - 0xE05C0001L, 0x00000020L, - 0x88880000L, 0xFFFFFE98L, - 0xE1100004L, 0x0000002CL, - 0xF05D0001L, 0x00000001L, - 0xF05F0001L, 0x00000003L, - 0x47000000L, 0x000003D0L, - 0xE1340004L, 0x00000004L, - 0xE1100004L, 0x00000018L, - 0xF0340004L, 0x00000000L, - 0xE15C0001L, 0x0000000CL, - 0x7E5C0100L, 0x00000000L, - 0xE05C0001L, 0x0000000CL, - 0xE15C0001L, 0x0000002CL, - 0x725C0000L, 0x00000000L, - 0x808C0001L, 0xFFFFFE90L, - 0xE1100004L, 0x0000002CL, - 0x828B0000L, 0x00000088L, - 0x808A0000L, 0x000000A8L, - 0x868A0000L, 0x00000020L, - 0x818A0000L, 0x000000E0L, - 0x838A0000L, 0x00000108L, - 0x878A0000L, 0x00000120L, - 0x98080000L, 0x00000000L, - 0x785C0600L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x1E000000L, 0x00000008L, - 0x80880000L, 0xFFFFFFA0L, - 0x58000008L, 0x00000000L, - 0x60000040L, 0x00000000L, - 0x868B0000L, 0xFFFFFFC8L, - 0x87820000L, 0xFFFFFF80L, - 0x0F000001L, 0x00000039L, - 0x60000040L, 0x00000000L, - 0x80880000L, 0xFFFFFFC8L, - 0x785C0200L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x60000008L, 0x00000000L, - 0x1A000000L, 0x00000010L, - 0x80880000L, 0xFFFFFF40L, - 0x785C0000L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x88880000L, 0x00000008L, - 0x80880000L, 0xFFFFFF20L, - 0xF1340004L, 0x00000004L, - 0xE0340004L, 0x00000394L, - 0x7835FF00L, 0x00000000L, - 0xF0350001L, 0x00000021L, - 0x80080000L, 0x00000333L, - 0x785C0100L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x88880000L, 0xFFFFFFC0L, - 0x81830000L, 0xFFFFFED8L, - 0x01000001L, 0x00000008L, - 0x80880000L, 0xFFFFFFE8L, - 0x785C0300L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x0B000001L, 0x00000008L, - 0x80880000L, 0xFFFFFEA8L, - 0x785C0700L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x0F000001L, 0x00000040L, - 0x808C0000L, 0x000000C0L, - 0x808C0002L, 0x000001A8L, - 0x808C0004L, 0x00000148L, - 0x808C0023L, 0x00000038L, - 0x808C0003L, 0x000001B0L, - 0x808C0001L, 0x00000058L, - 0x808C0007L, 0x00000008L, - 0x98080000L, 0x00000002L, - 0x98080000L, 0x0000000CL, - 0x60000040L, 0x00000000L, - 0x80880000L, 0xFFFFFE38L, - 0x60000040L, 0x00000000L, - 0x0F000001L, 0x00000041L, - 0x6A5E0000L, 0x00000000L, - 0xF05E0001L, 0x00000022L, - 0x60000040L, 0x00000000L, - 0x80880000L, 0xFFFFFE08L, - 0x60000040L, 0x00000000L, - 0x0F000001L, 0x00000041L, - 0x60000040L, 0x00000000L, - 0x0F000001L, 0x00000042L, - 0x60000040L, 0x00000000L, - 0x808C0001L, 0x00000140L, - 0x808C0003L, 0x00000148L, - 0x98080000L, 0x00000003L, - 0x785C0C00L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x7C027F00L, 0x00000000L, - 0x60000040L, 0x00000000L, - 0x48000000L, 0x00000000L, - 0xE1340004L, 0x00000014L, - 0x72370000L, 0x00000000L, - 0x80840000L, 0xFFFFFFE8L, - 0xE1340001L, 0x00000028L, - 0xE15C0001L, 0x00000008L, - 0x725C0000L, 0x00000000L, - 0x6A350000L, 0x00000000L, - 0x78360000L, 0x00000000L, - 0x7837FF00L, 0x00000000L, - 0xE0340004L, 0x00000014L, - 0x72350000L, 0x00000000L, - 0x981CC100L, 0x000000FFL, - 0x808CC100L, 0xFFFFFBC8L, - 0x98080000L, 0x00000001L, - 0xE15C0001L, 0x00000030L, - 0x725C0000L, 0x00000000L, - 0x808C0009L, 0x00000010L, - 0x785C0D00L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x785FFF00L, 0x00000000L, - 0xE05F0001L, 0x0000002BL, - 0x7C027F00L, 0x00000000L, - 0x60000040L, 0x00000000L, - 0x48000000L, 0x00000000L, - 0x80880000L, 0xFFFFFB68L, - 0x785C0E00L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x60000040L, 0x00000000L, - 0x80880000L, 0xFFFFFCB8L, - 0x785C0F00L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x60000040L, 0x00000000L, - 0x80880000L, 0xFFFFFC98L, - 0x0F000002L, 0x00000043L, - 0x98080000L, 0x0000000DL, - 0x0F000001L, 0x00000043L, - 0x98080000L, 0x0000000EL, - 0x7C00DF00L, 0x00000000L, - 0x7A1A0000L, 0x00000000L, - 0x785C0900L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x785FFF00L, 0x00000000L, - 0xE05F0001L, 0x0000002BL, - 0x54000000L, 0xFFFFFAD0L, - 0x720A0000L, 0x00000000L, - 0x980C7F00L, 0x00000007L, - 0x6C5C0F00L, 0x00000000L, - 0xE05C0001L, 0x00000020L, - 0x88880000L, 0xFFFFFA48L, - 0x9F030000L, 0x00000005L, - 0x0F000001L, 0x00000040L, - 0x60000040L, 0x00000000L, - 0x878B0000L, 0x00000048L, - 0x6C340700L, 0x00000000L, - 0xE15C0001L, 0x00000020L, - 0x60000400L, 0x00000000L, - 0x715C0000L, 0x00000000L, - 0x695C0000L, 0x00000000L, - 0x715C0000L, 0x00000000L, - 0x7AB40000L, 0x00000000L, - 0xE0340001L, 0x00000028L, - 0x80880000L, 0x00000030L, - 0x0F000001L, 0x00000040L, - 0x808C0004L, 0xFFFFFE70L, - 0x60000040L, 0x00000000L, - 0x80840020L, 0xFFFFFB90L, - 0x0F000001L, 0x00000028L, - 0x60000040L, 0x00000000L, - 0x785F0000L, 0x00000000L, - 0xE05F0001L, 0x0000002BL, - 0x88880000L, 0xFFFFF930L, - 0x80880000L, 0xFFFFFB60L, - 0x785C0B00L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x785FFF00L, 0x00000000L, - 0xE05F0001L, 0x0000002BL, - 0xE15E0001L, 0x00000012L, - 0xE05E0001L, 0x00000762L, - 0x45000000L, 0xFFFFFEB0L, - 0x72350000L, 0x00000000L, - 0x80840000L, 0x00000038L, - 0x72370000L, 0x00000000L, - 0x6A350000L, 0x00000000L, - 0xE0340002L, 0x00000038L, - 0x78020000L, 0x00000000L, - 0x0E000002L, 0x00000038L, - 0x48000000L, 0x00000000L, - 0x98080000L, 0x00000009L, - 0x72350000L, 0x00000000L, - 0x6A360000L, 0x00000000L, - 0x78352000L, 0x00000000L, - 0xE0340004L, 0x00000038L, - 0x78020000L, 0x00000000L, - 0x0E000004L, 0x00000038L, - 0x48000000L, 0x00000000L, - 0x98080000L, 0x00000009L, - 0x785C0A00L, 0x00000000L, - 0xE05C0001L, 0x00000030L, - 0x74140800L, 0x00000000L, - 0x980C0000L, 0x0000000AL, - 0x58000008L, 0x00000000L, - 0xE1100004L, 0x0000002CL, - 0x60000040L, 0x00000000L, - 0x868B0000L, 0x000000A8L, - 0x838A0000L, 0x00000030L, - 0x878A0000L, 0x00000038L, - 0x818A0000L, 0x00000040L, - 0x7834AD00L, 0x00000000L, - 0x808A0000L, 0x00000040L, - 0x828A0000L, 0x00000058L, - 0x98080000L, 0x00000000L, - 0x0B000001L, 0x00000038L, - 0x80880000L, 0xFFFFFFA8L, - 0x0F000001L, 0x00000038L, - 0x80880000L, 0xFFFFFF98L, - 0x09000001L, 0x00000038L, - 0x80880000L, 0xFFFFFF88L, - 0x7B347300L, 0x00000000L, - 0xE0340001L, 0x00000038L, - 0x08000001L, 0x00000038L, - 0x80880000L, 0xFFFFFF68L, - 0x78340000L, 0x00000000L, - 0xE0340001L, 0x00000038L, - 0x0A000001L, 0x00000038L, - 0x80880000L, 0xFFFFFF48L, - 0x78020000L, 0x00000000L, - 0x0E000001L, 0x00000000L, - 0xE1340004L, 0x00000004L, - 0xE0340004L, 0x00000000L, - 0x48000000L, 0x00000000L, - 0x98080000L, 0x0000000AL - -}; - -#endif /* INCL_SCRIPT_TEXT */ - -#define Rel_Count 76 - -#ifdef INCL_SCRIPT_TEXT - -ULONG Rel_Patches[Rel_Count] = { - 0x0000013DL, - 0x0000014FL, - 0x0000004BL, - 0x000001D5L, - 0x00000051L, - 0x00000099L, - 0x0000009DL, - 0x0000003BL, - 0x000000FFL, - 0x00000119L, - 0x00000125L, - 0x00000129L, - 0x0000017FL, - 0x00000183L, - 0x000001A1L, - 0x000001B9L, - 0x0000002DL, - 0x00000065L, - 0x00000067L, - 0x0000007FL, - 0x0000008BL, - 0x0000009FL, - 0x000000A5L, - 0x00000207L, - 0x00000025L, - 0x00000017L, - 0x0000007DL, - 0x00000143L, - 0x00000165L, - 0x00000191L, - 0x000001B5L, - 0x000001C1L, - 0x000001C7L, - 0x000001D3L, - 0x00000077L, - 0x000000B7L, - 0x000000CDL, - 0x000000D7L, - 0x000000E9L, - 0x000000F5L, - 0x000000FDL, - 0x00000135L, - 0x00000159L, - 0x00000161L, - 0x00000171L, - 0x00000179L, - 0x0000018DL, - 0x000001CFL, - 0x000001FFL, - 0x00000061L, - 0x00000095L, - 0x000000C5L, - 0x000001E3L, - 0x000001E7L, - 0x000001F3L, - 0x000001F7L, - 0x0000021BL, - 0x0000021FL, - 0x00000223L, - 0x00000229L, - 0x0000022BL, - 0x00000231L, - 0x00000233L, - 0x00000031L, - 0x00000087L, - 0x0000019BL, - 0x000001A9L, - 0x00000013L, - 0x000000EFL, - 0x000000F7L, - 0x00000145L, - 0x00000079L, - 0x00000093L, - 0x0000023BL, - 0x00000239L, - 0x0000023DL -}; - -#endif /* INCL_SCRIPT_TEXT */ - -#define R_ld_AbortCode 0x00000000L -#define R_ld_zeroes 0x00000004L -#define R_ld_status 0x00000008L -#define R_ld_counter 0x0000000CL -#define R_ld_AbortBdr_mailbox 0x00000010L -#define R_ld_IOdone_mailbox 0x00000014L -#define R_ld_sched_mlbx_base_adr 0x00000018L -#define R_ld_scsi_id 0x00000020L -#define R_ld_nexus_array_base 0x00000024L -#define R_ld_nexus_index 0x00000028L -#define R_ld_nexus 0x0000002CL -#define R_ld_phase_flag 0x00000030L -#define R_ld_device_table_base_adr 0x00000034L -#define R_ld_scratch 0x00000038L -#define R_ld_message 0x00000040L -#define R_ld_size 0x0000004CL -#define A_kphase_DATA_OUT 0x00000000L -#define A_unknown_phase 0x00000000L -#define A_TLQ_SCSI_ID 0x00000000L -#define A_kphase_DATA_IN 0x00000001L -#define A_status_error 0x00000001L -#define A_unexpected_msg 0x00000002L -#define A_kphase_COMMAND 0x00000002L -#define A_kphase_STATUS 0x00000003L -#define A_unexpected_ext_msg 0x00000003L -#define A_TLQ_xferAdr 0x00000004L -#define A_no_msgin_after_reselect 0x00000005L -#define A_kphase_MSG_OUT 0x00000006L -#define A_kphase_MSG_IN 0x00000007L -#define A_unknown_reselect 0x00000007L -#define A_kphase_SELECT 0x00000008L -#define A_unallocated_nexus 0x00000008L -#define A_TLQ_MSGOp 0x00000008L -#define A_kphase_RESELECT 0x00000009L -#define A_abort_mailbox 0x00000009L -#define A_abort_current 0x0000000AL -#define A_kphase_ABORT_CURRENT 0x0000000AL -#define A_kphase_ABORT_MAILBOX 0x0000000BL -#define A_kphase_CMD_COMPLETE 0x0000000CL -#define A_unknown_msg_reject 0x0000000CL -#define A_kphase_DISCONNECT 0x0000000DL -#define A_negotiateSDTR 0x0000000DL -#define A_negotiateWDTR 0x0000000EL -#define A_kphase_saveDataPointer 0x0000000EL -#define A_sglist_complete 0x0000000FL -#define A_kphase_restoreDataPointer 0x0000000FL -#define A_TLQ_CDBp 0x00000010L -#define A_TLQ_index 0x00000020L -#define A_TLQ_xferStarted 0x00000021L -#define A_TLQ_IWR 0x00000022L -#define Ent_clearACK 0x00000448L -#define Ent_issueAbort_BDR 0x000007F0L -#define Ent_issueMessageOut 0x000002F0L -#define Ent_phase_handler 0x00000290L -#define Ent_select_phase 0x00000120L - -#ifdef INCL_SCRIPT_TEXT - -ULONG LABELPATCHES[] = { - 0x00000023L, - 0x00000039L, - 0x0000005DL, - 0x0000005FL, - 0x000000DFL, - 0x000001D7L -}; - -#endif /* INCL_SCRIPT_TEXT */ diff --git a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.lis b/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.lis deleted file mode 100644 index 6b690920f..000000000 --- a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.lis +++ /dev/null @@ -1,993 +0,0 @@ - 1 - 2 ; Copyright (c) 1997-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 ; File Ownership: - 23 ; - 24 ; DRI: Mike Johnson - 25 ; - 26 ; Other Contact: Russ Berkoff - 27 ; - 28 ; Technology: SCSI - 29 ; - 30 ; Writers: - 31 ; - 32 ; (MLJ) Mike Johnson - 33 ; (RRA) Rick Auricchio - 34 - 35 - 36 ; NCR Errata Listing 125 Item 1 : Clear the SCNTL0 start bit - 37 ; when jump to reselect during select (try_reselect) - 38 ; - 39 ; NCR Errata Listing 117 Item 4 : Bad parity if odd bytes during - 40 ; wide transfer. Only for DATA OUT in Initiator mode. - 41 ; (Confirm by Manfred Eierle 3rd June 93 not during DATA IN) - 42 - 43 ARCH 825A ;specifically for 825a and 875 (new instructions) - 44 - 45 - 46 ;***************************************************************** - 47 ; - 48 ; Phase codes - These values represent which action is being handled - 49 ; - 50 ;***************************************************************** - 51 - 52 ABSOLUTE kphase_DATA_OUT = 0x00 - 53 ABSOLUTE kphase_DATA_IN = 0x01 - 54 ABSOLUTE kphase_COMMAND = 0x02 - 55 ABSOLUTE kphase_STATUS = 0x03 - 56 ABSOLUTE kphase_MSG_OUT = 0x06 - 57 ABSOLUTE kphase_MSG_IN = 0x07 - 58 ABSOLUTE kphase_SELECT = 0x08 - 59 ABSOLUTE kphase_RESELECT = 0x09 - 60 ABSOLUTE kphase_ABORT_CURRENT = 0x0A - 61 ABSOLUTE kphase_ABORT_MAILBOX = 0x0B - 62 ABSOLUTE kphase_CMD_COMPLETE = 0x0C - 63 ABSOLUTE kphase_DISCONNECT = 0x0D - 64 ABSOLUTE kphase_saveDataPointer = 0x0E ; ??? driver work to be done - 65 ABSOLUTE kphase_restoreDataPointer = 0x0F ; ??? driver work to be done - 66 - 67 - 68 ;***************************************************************** - 69 ; interrupt codes - 70 ;***************************************************************** - 71 - 72 ABSOLUTE unknown_phase = 0x00 ; A spurious phase on SCSI Bus - 73 ABSOLUTE status_error = 0x01 ; IO completes, but with status error - 74 ABSOLUTE unexpected_msg = 0x02 ; An 'unknown' message is in ld_message var - 75 ABSOLUTE unexpected_ext_msg = 0x03 ; An 'unknown' extended message in ld_message - 76 ABSOLUTE wide_32_not_supported = 0x04 ; The device wants 32 bits data phase - 77 ABSOLUTE no_msgin_after_reselect = 0x05 ; No message-in after reselection - 78 ABSOLUTE reqack_too_large = 0x06 ; The device answer ReqAck offset is greater than 8 - 79 ABSOLUTE unknown_reselect = 0x07 ; The valid bit in SFBR reg not set - 80 ABSOLUTE unallocated_nexus = 0x08 ; nexus index -> 0xFFFFFFFF - 81 ABSOLUTE abort_mailbox = 0x09 ; Abort/BDR mailbox completed - 82 ABSOLUTE abort_current = 0x0A ; Abort/BDR current op completed - 83 ABSOLUTE unknown_message_out = 0x0B ; Unknown phase before message out - 84 ABSOLUTE unknown_msg_reject = 0x0C ; Unknown message reject - 85 ABSOLUTE negotiateSDTR = 0x0D ; Sync negotiation rx'd - 86 ABSOLUTE negotiateWDTR = 0x0E ; Wide negotiation rx'd - 87 ABSOLUTE sglist_complete = 0x0F ; SGList complete - 88 - 89 - 90 ;***************************************************************** - 91 ; - 92 ; Data structure for T/L/Q Nexus: - 93 ; - 94 ;***************************************************************** - 95 - 96 ABSOLUTE TLQ_SCSI_ID = 0 ; 4 SCSI ID et al for SELECT instruction - 97 ABSOLUTE TLQ_xferAdr = 4 ; 4 Physical address of CHMOV instructions - 98 ABSOLUTE TLQ_MSGOp = 8 ; 8 Byte count, data adr -> TLQ_MSGO - 99 ABSOLUTE TLQ_CDBp = 16 ; 8 Byte count, data adr -> TLQ_CDB - 100 ABSOLUTE TLQ_CDP = 24 ; 4 Current Data Pointer - 101 ABSOLUTE TLQ_SDP = 28 ; 4 Saved Data Pointer - 102 ABSOLUTE TLQ_index = 32 ; 1 index into nexus array - 103 ABSOLUTE TLQ_xferStarted= 33 ; 1 transfer started flag - 104 ABSOLUTE TLQ_IWR = 34 ; 1 flag to Ignore Wide Residue - 105 ABSOLUTE TLQ_pad = 35 ; 1 pad byte - 106 - 107 - 108 ;***************************************************************** - 109 ; - 110 ; ENTRY declarations - Declare entry points for driver - 111 ; - 112 ;***************************************************************** - 113 - 114 ENTRY select_phase - 115 ENTRY phase_handler - 116 ENTRY issueMessageOut ; for negotiation and Reject messages - 117 ENTRY issueAbort_BDR ; to immediately Abort or Bus-Device-Reset - 118 ENTRY clearACK ; MsgIn done - clr ACK, jump to phase handler - 119 - 120 - 121 ;***************************************************************** - 122 ; - 123 ; Define local data structure at start of SCRIPTS. - 124 ; This structure is allocated by the following nops. - 125 ; - 126 ;***************************************************************** - 127 ; - 128 - 129 RELATIVE local_data \ - 130 00000000: ld_AbortCode = 4{??}\ ; 1 byte code to Abort or BDR - 131 00000004: ld_zeroes = 4{??}\ ; 4 bytes of 0 to clear registers - 132 00000008: ld_status = 4{??}\ ; Status byte from target - 133 0000000C: ld_counter = 4{??}\ ; index into mailbox array - 134 00000010: ld_AbortBdr_mailbox = 4{??}\ ; Abort/BusDeviceReset mailbox - 135 00000014: ld_IOdone_mailbox = 4{??}\ ; [ nexus 0 0 semaphore ] - 136 00000018: ld_sched_mlbx_base_adr = 4{??}\ ; base addr of mailbox array - 137 0000001C: ld_mailboxp = 4{??}\ ; address of current mailbox - 138 00000020: ld_scsi_id = 4{??}\ ; ptr to current mailbox - 139 00000024: ld_nexus_array_base = 4{??}\ ; base address of Nexus pointers - 140 00000028: ld_nexus_index = 4{??}\ ; index to Nexus pointer - 141 0000002C: ld_nexus = 4{??}\ ; address of Nexus - 142 00000030: ld_phase_flag = 4{??}\ ; for debugging - 143 00000034: ld_device_table_base_adr = 4{??}\ ; device configuration table - 144 00000038: ld_scratch = 4{??}\ ; scratch memory - 145 0000003C: ld_unused = 4{??}\ ; unused - 146 00000040: ld_message = 4{??}\ ; buffer for MsgIn bytes - 147 00000044: ld_message4 = 4{??}\ ; buffer continuation - 148 00000048: ld_pad = 4{??}\ ; padding - 149 0000004C: ld_size = 4{??} ; size of this structure - 150 - 151 - 152 00000000: PROC BSC_SCRIPT: - 153 - 154 ; *** These NOPs must be at address 0. *** - 155 ; *** This is reserved space for the structure "local_data". *** - 156 ; *** The driver inits this area to zero. *** - 157 - 158 00000000: 80000000 00000000 nop 0 ; ld_AbortCode, ld_zeroes - 159 00000008: 80000000 00000000 nop 0 ; ld_status, ld_counter - 160 - 161 00000010: 80000000 00000000 nop 0 ; ld_AbortBdr_mailbox, ld_IOdone_mailbox - 162 00000018: 80000000 00000000 nop 0 ; ld_sched_mlbx_base_adr, ld_mailboxp - 163 - 164 00000020: 80000000 00000000 nop 0 ; ld_scsi_id, ld_nexus_array_base - 165 00000028: 80000000 00000000 nop 0 ; ld_nexus_index, ld_nexus - 166 - 167 00000030: 80000000 00000000 nop 0 ; ld_phase_flag, ld_device_table_base_adr - 168 00000038: 80000000 00000000 nop 0 ; ld_scratch, ld_unused - 169 - 170 00000040: 80000000 00000000 nop 0 ; ld_message, ld_message4 - 171 00000048: 80000000 0000004C nop ld_size ; ld_pad, ld_size (Use ld_size or lose it) - 172 - 173 00000050: 80000000 0000000F nop sglist_complete ; use sglist_complete or lose it from gen'd output file - 174 - 175 ;**************************************************************************** - 176 ; - 177 ; findNexusFromIndex - load DSA with pointer to Nexus given a Nexus index: - 178 ; - 179 ;**************************************************************************** - 180 - 181 00000058: findNexusFromIndex: - 182 - 183 00000058: E1340004 00000028 load SCRATCHA0, 4, ld_nexus_index ; load index and leading zeroes - 184 00000060: 60000400 00000000 clear CARRY - 185 00000068: 79340000 00000000 move SCRATCHA0 SHL 0 to SCRATCHA0 ; double the index - 186 00000070: 79350000 00000000 move SCRATCHA1 SHL 0 to SCRATCHA1 - 187 00000078: 79340000 00000000 move SCRATCHA0 SHL 0 to SCRATCHA0 ; double again - 188 00000080: 79350000 00000000 move SCRATCHA1 SHL 0 to SCRATCHA1 ; A0 now has index to 4-byte address - 189 00000088: E0340004 0000009C store SCRATCHA0, 4, patchArrayOffset+4 ; *** patch the code - 190 - 191 00000090: E1100004 00000024 load DSA0, 4, ld_nexus_array_base ; load base address of array of Nexus pointers - 192 00000098: patchArrayOffset: - 193 00000098: F1100004 00000000 load DSA0, 4, DSAREL( 0 ) ; *** patched offset. Load pointer. - 194 - 195 000000A0: 72100000 00000000 move DSA0 to SFBR ; Ensure pointer is not 0xFFFFFFFF - 196 000000A8: 980C00FF 00000008 int unallocated_nexus, if 0xFF ; Interrupt if NFG - 197 - 198 000000B0: E0100004 0000002C store DSA0, 4, ld_nexus ; Store the Nexus pointer - 199 000000B8: 90080000 00000000 return ; end findNexusFromIndex - 200 - 201 - 202 ;**************************************************************************** - 203 ; - 204 ; initContext - Initialize the registers for Sync and Wide using - 205 ; values stored in the device configuration table. - 206 ; Return with values in SCRATCHB for Select code. - 207 ; - 208 ;**************************************************************************** - 209 - 210 000000C0: initContext: - 211 - 212 000000C0: E15C0004 00000020 load SCRATCHB0, 4, ld_scsi_id ; load 4-bit SCSI ID and zeroes - 213 000000C8: 60000400 00000000 clear CARRY - 214 000000D0: 795C0000 00000000 move SCRATCHB0 SHL SCRATCHB0 ; * 2 - 215 000000D8: 795C0000 00000000 move SCRATCHB0 SHL SCRATCHB0 ; * 2 -> UInt32 index - 216 000000E0: E05C0004 000000F4 store SCRATCHB0, 4, patchGetDevConfigOffset+4 ; *** Patch load code - 217 - 218 000000E8: E1100004 00000034 load DSA0, 4, ld_device_table_base_adr ; load base physical addr of tables - 219 - 220 000000F0: patchGetDevConfigOffset: - 221 000000F0: F15C0004 00000000 load SCRATCHB0, 4, DSAREL( 0 ) ; *** Patched table offset *** - 222 - 223 ; SCRATCHB0 = 0 - 224 ; SCRATCHB1 = TP,MO (SXFER bits7-5 bits3-0) - 225 ; SCRATCHB2 = 0 (position for SCSI ID) - 226 ; SCRATCHB3 = SCCF,EWS (SCNTL3 bits6-4 bit 3) - 227 - 228 000000F8: 725D0000 00000000 move SCRATCHB1 to SFBR ; init SXFER from B1 - 229 00000100: 6A050000 00000000 move SFBR to SXFER - 230 ; Init SCNTL3 from B3 - 231 00000108: 725F0000 00000000 move SCRATCHB3 to SFBR - 232 00000110: 6A030000 00000000 move SFBR to SCNTL3 - 233 00000118: 90080000 00000000 return ; return with SCRATCHB intact. - 234 - 235 - 236 ;***************************************************************** - 237 ; - 238 ; Select_phase: - 239 ; Clear the SIGP bit. - 240 ; Check if any Abort/BusDeviceReset request waiting. - 241 ; Nexus is found in the list of 256 mailboxes. - 242 ; If current mailbox is empty, jump to reselect_phase. - 243 ; SCRIPTS tries to select device. - 244 ; If select fails due to reselect, jump to reselect_phase - 245 ; Select Timeout handled by driver. - 246 ; If select succeeds, clear the mailbox entry - 247 ; and increment the mailbox counter. - 248 ; Jump to the phase_handler (hopefully for MSG_OUT) - 249 ; - 250 ;***************************************************************** - 251 - 252 00000120: select_phase: - 253 - 254 00000120: 7A1A0000 00000000 move CTEST2 | 0x00 to CTEST2 ; Clear SIGP bit from ISTAT reg - 255 - 256 ; Check abort mailbox: - 257 - 258 00000128: E1340004 00000010 load SCRATCHA0, 4, ld_AbortBdr_mailbox ; Get AbortBdr mailbox - 259 ; The Identify byte in byte 0 is also the semaphore - 260 ; A0 = Identify byte (0xC0 + LUN N.B. Disconnect allowed) - 261 ; A1 = Tag, if any - 262 ; A2 = SCSI ID - 263 ; A3 = Abort code Abort=0x06; Abort Tag=0D; Bus Device Reset=0x0C - 264 00000130: 72340000 00000000 move SCRATCHA0 to SFBR ; test the semaphore/Identify - 265 00000138: 80840000 000005F0 jump rel( AbortMailbox ), if not 0 ; jump if aborting - 266 - 267 - 268 ; Get the next IO nexus in the mailboxes circular list. - 269 ; Calculate current mailbox address as so: - 270 ; counter byte index * 4 to get mailbox index - 271 ; add base physical address of mailboxes giving current mailbox address - 272 - 273 00000140: E1340004 0000000C load SCRATCHA0, 4, ld_counter ; get 1-byte mailbox counter & 0s - 274 00000148: 60000400 00000000 clear CARRY - 275 00000150: 79340000 00000000 move SCRATCHA0 SHL 0 to SCRATCHA0 ; double it - 276 00000158: 79350000 00000000 move SCRATCHA1 SHL 0 to SCRATCHA1 - 277 00000160: 79340000 00000000 move SCRATCHA0 SHL 0 to SCRATCHA0 ; double it again - 278 00000168: 79350000 00000000 move SCRATCHA1 SHL 0 to SCRATCHA1 ; now have a UInt32 index - 279 00000170: E0340004 0000018C store SCRATCHA0, 4, fetchMailbox+4 ; *** patch the load DSA instruction - 280 00000178: E0340004 0000025C store SCRATCHA0, 4, clear_mailbox+4 ; *** patch the store DSA instruction - 281 - 282 00000180: E1100004 00000018 load DSA0, 4, ld_sched_mlbx_base_adr ; load base physical address of mailboxes - 283 - 284 00000188: fetchMailbox: - 285 00000188: F1100004 00000000 load DSA0, 4, DSAREL( 0 ) ; *** Patched offset. Load Nexus address - 286 00000190: E0100004 0000002C store DSA0, 4, ld_nexus ; save pointer to current Nexus - 287 00000198: E1340004 0000002C load SCRATCHA0, 4, ld_nexus ; copy to A0 - 288 - 289 000001A0: 72340000 00000000 move SCRATCHA0 to SFBR ; - 290 000001A8: 808C0001 00000098 jump rel( next_mailbox ), if 1 ; if low-byte == 0x01 then cancelled mailbox - 291 - 292 000001B0: 72B50000 00000000 move SCRATCHA1 | SFBR to SFBR ; if non-zero, have implicit semaphore - 293 000001B8: 72B60000 00000000 move SCRATCHA2 | SFBR to SFBR - 294 000001C0: 72B70000 00000000 move SCRATCHA3 | SFBR to SFBR - 295 000001C8: 808C0000 00000458 jump rel( reselect_phase ), if 0 ; go to reselect_phase if empty - 296 - 297 ;***************************************************************** - 298 ; - 299 ; Something in mailbox: we have work to do - 300 ; - 301 ;***************************************************************** - 302 - 303 000001D0: 785C0800 00000000 move kphase_SELECT to SCRATCHB0 ; set phase indicator - 304 000001D8: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 305 - 306 000001E0: E15C0004 00000004 load SCRATCHB0, 4, ld_zeroes ; clr the invalid-nexus-index flag - 307 000001E8: F15C0001 00000020 load SCRATCHB0, 1, DSAREL( TLQ_index ) ; get index byte from nexus - 308 000001F0: E05C0004 00000028 store SCRATCHB0, 4, ld_nexus_index ; save it in local data - 309 - 310 000001F8: E1100004 0000002C load DSA0, 4, ld_nexus ; restore DSA register - 311 00000200: F15E0001 00000002 load SCRATCHB2, 1, DSAREL( TLQ_SCSI_ID+2 ) ; get Target's SCSI ID - 312 00000208: 725E0000 00000000 move SCRATCHB2 to SFBR - 313 00000210: 6A5C0000 00000000 move SFBR to SCRATCHB0 ; position it - 314 00000218: E05C0001 00000020 store SCRATCHB0, 1, ld_scsi_id ; save it - 315 00000220: 88880000 FFFFFE98 call rel( initContext ) ; setup Sync/Wide regs in SCRATCHB - 316 00000228: E1100004 0000002C load DSA0, 4, ld_nexus ; restore DSA register - 317 00000230: F05D0001 00000001 store SCRATCHB1, 1, DSAREL( TLQ_SCSI_ID+1 ) ; SXFER - 318 00000238: F05F0001 00000003 store SCRATCHB3, 1, DSAREL( TLQ_SCSI_ID+3 ) ; SCNTL3 - 319 - 320 ;********************** select the device ******************************** - 321 00000240: 47000000 000003D0 SELECT ATN from TLQ_SCSI_ID, rel( try_reselect ) ; ************************ - 322 ;************************************************************************* - 323 - 324 ; looking good - clear the mailbox: - 325 - 326 00000248: next_mailbox: - 327 00000248: E1340004 00000004 load SCRATCHA0, 4, ld_zeroes ; zero out scratch register A - 328 00000250: E1100004 00000018 load DSA0, 4, ld_sched_mlbx_base_adr ; load base physical address of mailboxes - 329 00000258: clear_mailbox: - 330 00000258: F0340004 00000000 store SCRATCHA0, 4, DSAREL( 0 ) ; *** Patched offset. Zero the mailbox - 331 - 332 ; Update the index to the mailbox circular list: - 333 00000260: E15C0001 0000000C load SCRATCHB0, 1, ld_counter ; get counter (mailbox index) - 334 00000268: 7E5C0100 00000000 move SCRATCHB0 + 1 to SCRATCHB0 ; add 1 - 335 00000270: E05C0001 0000000C store SCRATCHB0, 1, ld_counter ; put it back - 336 - 337 00000278: E15C0001 0000002C load SCRATCHB0, 1, ld_nexus ; if low-byte == 0x01 then cancelled mailbox - 338 00000280: 725C0000 00000000 move SCRATCHB0 to SFBR - 339 00000288: 808C0001 FFFFFE90 jump rel( select_phase ), if 1 - 340 - 341 ; *** FALL THROUGH TO phase_handler *** - 342 - 343 - 344 ;***************************************************************** - 345 ; - 346 ; Phase_handler - 347 ; The phase handler script is a dispatcher function of SCSI phase - 348 ; - 349 ;***************************************************************** - 350 - 351 00000290: phase_handler: - 352 00000290: E1100004 0000002C load DSA0, 4, ld_nexus ; reload DSA - 353 00000298: 828B0000 00000088 jump rel( command_phase ), when CMD ; wait for REQ - 354 000002A0: 808A0000 000000A8 jump rel( data_out_phase ), if DATA_OUT ; already latched REQ signal - 355 000002A8: 868A0000 00000020 jump rel( message_out_phase ), if MSG_OUT - 356 000002B0: 818A0000 000000E0 jump rel( data_in_phase ), if DATA_IN - 357 000002B8: 838A0000 00000108 jump rel( status_phase ), if STATUS - 358 000002C0: 878A0000 00000120 jump rel( message_in_phase ), if MSG_IN - 359 000002C8: 98080000 00000000 int unknown_phase - 360 - 361 - 362 ;***************************************************************** - 363 ; - 364 ; Message-Out phase - 365 ; - 366 ;***************************************************************** - 367 - 368 000002D0: message_out_phase: - 369 000002D0: 785C0600 00000000 move kphase_MSG_OUT to SCRATCHB0 ; Set phase indicator - 370 000002D8: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 371 - 372 000002E0: 1E000000 00000008 move from TLQ_MSGOp, when MSG_OUT ; put out the message(s) - 373 000002E8: 80880000 FFFFFFA0 jump rel( phase_handler ) - 374 - 375 - 376 ; issueMessageOut - Driver entry point for Sync/Wide negotiation and - 377 ; to issue message Reject: - 378 - 379 000002F0: issueMessageOut: - 380 000002F0: 58000008 00000000 set ATN ; tell Target we have something to say - 381 000002F8: 60000040 00000000 clear ACK - 382 00000300: 868B0000 FFFFFFC8 jump rel( message_out_phase ), when MSG_OUT ; wait for REQ. Jump if msg-out phase. - 383 00000308: 87820000 FFFFFF80 jump rel( phase_handler ), if not MSG_IN ; jump if weird phase - 384 00000310: 0F000001 00000039 move 1, ld_scratch+1, when MSG_IN ; dump the msg byte - 385 00000318: 60000040 00000000 clear ACK ; accept Target's last msg-in byte - 386 00000320: 80880000 FFFFFFC8 jump rel( issueMessageOut ) - 387 - 388 - 389 ;***************************************************************** - 390 ; - 391 ; Command phase - 392 ; - 393 ;***************************************************************** - 394 - 395 00000328: command_phase: - 396 00000328: 785C0200 00000000 move kphase_COMMAND to SCRATCHB0 ; Set phase indicator - 397 00000330: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 398 - 399 00000338: 60000008 00000000 clear ATN ; In case we missed the sending nego - 400 00000340: 1A000000 00000010 move FROM TLQ_CDBp, when CMD ; issue the CDB - 401 00000348: 80880000 FFFFFF40 jump rel( phase_handler ) - 402 - 403 - 404 ;***************************************************************** - 405 ; - 406 ; Data_out_phase - 407 ; - 408 ;***************************************************************** - 409 - 410 00000350: data_out_phase: - 411 00000350: 785C0000 00000000 move kphase_DATA_OUT to SCRATCHB0 ; Set phase indicator - 412 00000358: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 413 - 414 00000360: 88880000 00000008 call rel( driverXfer ) ; call driver-built CHMOV instructions - 415 00000368: 80880000 FFFFFF20 jump rel( phase_handler ) ; if all data xfer'd, get next phase - 416 - 417 00000370: driverXfer: ; get here from data-in code also - 418 00000370: F1340004 00000004 load SCRATCHA0, 4, DSAREL( TLQ_xferAdr ) - 419 00000378: E0340004 00000394 store SCRATCHA0, 4, doItPatch+4 ; *** patch the JUMP address - 420 00000380: 7835FF00 00000000 move 0xFF to SCRATCHA1 - 421 00000388: F0350001 00000021 store SCRATCHA1, 1, DSAREL( TLQ_xferStarted ) - 422 - 423 00000390: doItPatch: - 424 00000390: 80080000 00000333 jump 0x0333 ; *** patched address - 425 - 426 - 427 - 428 ;***************************************************************** - 429 ; - 430 ; Data_in_phase - 431 ; 875 sets ATN if bad parity detected. - 432 ; Use of CHMOV instructions assures that we properly handle - 433 ; a leftover wide byte in the SWIDE or SODL register, depending - 434 ; on the data direction. This can happen in either of two conditions: - 435 ; 1. The Target disconnects at an odd boundary. This is - 436 ; extremely unlikely with disk devices. - 437 ; 2. The client passes either an odd buffer address or - 438 ; an odd transfer count. When the Target disconnects (at - 439 ; an even boundary, we end up with the extra wide - 440 ; byte in SWIDE or SODL. MacOS does this with VM on. - 441 ; - 442 ;***************************************************************** - 443 - 444 00000398: data_in_phase: - 445 00000398: 785C0100 00000000 move kphase_DATA_IN to SCRATCHB0 ; Set phase indicator - 446 000003A0: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 447 - 448 000003A8: 88880000 FFFFFFC0 call rel( driverXfer ) ; call driver-built CHMOV instructions - 449 - 450 ; The driver gets interrupted if a phase mismatch occurs as when - 451 ; the Target goes MSG-IN with a Disconnect. - 452 ; The driver codes either a RETURN if the Scatter/Gather list is complete or - 453 ; an INT if more Scatter/Gather elements need to be generated. - 454 ; On the Macintosh, client programs expect extra incoming data to be dumped. - 455 ; For example, during boot the ROM reads 512 bytes from a 2K-byte-sector CD. - 456 - 457 000003B0: bucket_loop: - 458 000003B0: 81830000 FFFFFED8 jump rel( phase_handler ), when not DATA_IN ; wait for phase, exit if changed - 459 000003B8: 01000001 00000008 CHMOV 1, ld_status, when DATA_IN ; eat a byte - 460 000003C0: 80880000 FFFFFFE8 jump rel( bucket_loop ); ; keep dumping bytes - 461 - 462 - 463 ;***************************************************************** - 464 ; - 465 ; Status phase - 466 ; - 467 ;***************************************************************** - 468 - 469 000003C8: status_phase: - 470 000003C8: 785C0300 00000000 move kphase_STATUS to SCRATCHB0 ; Set phase indicator - 471 000003D0: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 472 - 473 000003D8: 0B000001 00000008 move 1, ld_status, when STATUS ; Read Status byte from bus - 474 000003E0: 80880000 FFFFFEA8 jump rel( phase_handler ) - 475 - 476 - 477 ;***************************************************************** - 478 ; - 479 ; Message-In phase - 480 ; - 481 ;***************************************************************** - 482 - 483 000003E8: message_in_phase: - 484 000003E8: 785C0700 00000000 move kphase_MSG_IN to SCRATCHB0 ; Set phase indicator - 485 000003F0: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 486 - 487 000003F8: 0F000001 00000040 move 1, ld_message, when MSG_IN ; Read byte from bus - 488 - 489 00000400: 808C0000 000000C0 jump rel( cmdComplete ), if 0x00 ; Command Complete - 490 00000408: 808C0002 000001A8 jump rel( saveDataPointer ), if 0x02 ; Save Data Pointer - 491 00000410: 808C0004 00000148 jump rel( disconnect_msg ), if 0x04 ; Disconnect - 492 00000418: 808C0023 00000038 jump rel( ignoreWideResidue ), if 0x23 ; Ignore Wide Residue - 493 00000420: 808C0003 000001B0 jump rel( restoreDataPointer ), if 0x03 ; Restore Data Pointer - 494 00000428: 808C0001 00000058 jump rel( extended_msg ), if 0x01 ; Extended message - 495 00000430: 808C0007 00000008 jump rel( msg_reject ), if 0x07 ; Message Reject - 496 ; Identify, if 0x80-FF ; Identify + LUN - 497 ; simple_queue_tag, if 0x20 ; Simple Queue Tag - 498 ; initiate_recovery, if 0x0F ; Initiate Recovery - 499 ; linked_cde_complete, if 0x0A/0x0B - 500 00000438: 98080000 00000002 int unexpected_msg ; unknown - 501 - 502 00000440: msg_reject: - 503 00000440: 98080000 0000000C int unknown_msg_reject - 504 - 505 00000448: clearACK: ; ENTRY point to end negotiation - 506 00000448: 60000040 00000000 clear ACK - 507 00000450: 80880000 FFFFFE38 jump rel( phase_handler ) - 508 - 509 - 510 - 511 ;***************************************************************** - 512 ; - 513 ; Ignore Wide Residue - 514 ; - 515 ;***************************************************************** - 516 - 517 00000458: ignoreWideResidue: ; this is a two byte message so snag the 2nd byte here - 518 00000458: 60000040 00000000 clear ACK - 519 00000460: 0F000001 00000041 move 1, ld_message+1, when MSG_IN ; save residue count - 520 00000468: 6A5E0000 00000000 move SFBR to SCRATCHB2 ; byte is still in SFBR. Position it. - 521 00000470: F05E0001 00000022 store SCRATCHB2, 1, DSAREL( TLQ_IWR ) ; Store residue count in Nexus for driver. - 522 00000478: 60000040 00000000 clear ACK - 523 00000480: 80880000 FFFFFE08 jump rel( phase_handler ) - 524 - 525 - 526 ;***************************************************************** - 527 ; - 528 ; Extended message - 529 ; Accept Wide and Synchronous Data Transfer messages - 530 ; - 531 ;***************************************************************** - 532 - 533 00000488: extended_msg: - 534 00000488: 60000040 00000000 clear ACK - 535 00000490: 0F000001 00000041 move 1, ld_message+1, when MSG_IN ; read msg length byte from bus - 536 00000498: 60000040 00000000 clear ACK - 537 000004A0: 0F000001 00000042 move 1, ld_message+2, when MSG_IN ; read ext msg code from bus - 538 000004A8: 60000040 00000000 clear ACK - 539 ; extended_identify, IF 0x02 - 540 ; modify_data_pointer, if 0x00 - 541 000004B0: 808C0001 00000140 jump rel( sdtr ), if 0x01 ; jump if SDTR, sync negotiation msg - 542 000004B8: 808C0003 00000148 jump rel( wdtr ), if 0x03 ; jump if WDTR, wide negotiation msg - 543 000004C0: 98080000 00000003 int unexpected_ext_msg ; let driver deal with unknown - 544 - 545 - 546 ;***************************************************************** - 547 ; - 548 ; Command complete - 549 ; The Command-Complete message is sent to indicate that the - 550 ; IO operation has completed and valid status has been sent. - 551 ; The Target should then disconnect. - 552 ; SCRIPTS must spin until the IOdone mailbox is empty. - 553 ; Then it sets the IOdone mailbox with the current Nexus. - 554 ; The status message is analyzed. - 555 ; If status is good, INTF the driver and jump to select_phase. - 556 ; If status is NG, save it in the NEXUS and INT the driver. - 557 ; - 558 ;***************************************************************** - 559 - 560 000004C8: cmdComplete: - 561 000004C8: 785C0C00 00000000 move kphase_CMD_COMPLETE to SCRATCHB0 ; Set phase indicator - 562 000004D0: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 563 - 564 000004D8: 7C027F00 00000000 move SCNTL2 & 0X7F to SCNTL2 ; Clr SDU: SCSI Disconnect Unexpected - 565 000004E0: 60000040 00000000 clear ACK - 566 000004E8: 48000000 00000000 WAIT DISCONNECT - 567 - 568 000004F0: testMbxLp: ; loop until IOdone mailbox empty - 569 000004F0: E1340004 00000014 load SCRATCHA0, 4, ld_IOdone_mailbox - 570 000004F8: 72370000 00000000 move SCRATCHA3 to SFBR ; A3 = semaphore - 571 00000500: 80840000 FFFFFFE8 jump rel( testMbxLp ), if not 0 - 572 - 573 ; Fill in the IOdone mailbox with the following: - 574 ; A0 = index to Nexus - 575 ; A1 = Status - 576 ; A2 = 0 - 577 ; A3 = semaphore (FF = set) - 578 00000508: E1340001 00000028 load SCRATCHA0, 1, ld_nexus_index ; A0 = index to Nexus - 579 00000510: E15C0001 00000008 load SCRATCHB0, 1, ld_status - 580 00000518: 725C0000 00000000 move SCRATCHB0 to SFBR - 581 00000520: 6A350000 00000000 move SFBR to SCRATCHA1 ; A1 = Status - 582 00000528: 78360000 00000000 move 0x00 to SCRATCHA2 ; A2 = 0 - 583 00000530: 7837FF00 00000000 move 0xFF to SCRATCHA3 ; A3 = semaphore IOdone mailbox - 584 00000538: E0340004 00000014 store SCRATCHA0, 4, ld_IOdone_mailbox - 585 - 586 00000540: 72350000 00000000 move SCRATCHA1 to SFBR ; Test the Status of this IO - 587 ; SFBR = status msg - 588 ; Test status - If good, Interrupt on the fly and jump to select phase - 589 00000548: 981CC100 000000FF intfly 0xFF, if 0 and mask 0xC1 ; mask off reserved bits - 590 00000550: 808CC100 FFFFFBC8 jump rel( select_phase ), if 0 and mask 0xC1 - 591 00000558: 98080000 00000001 int status_error ; Status err. Interrupt driver & stop - 592 - 593 - 594 ;***************************************************************** - 595 ; - 596 ; Disconnect - 597 ; The 8xx Accepts the disconnection and jumps to the select_phase - 598 ; to check for another IO - 599 ; - 600 ;***************************************************************** - 601 - 602 00000560: disconnect_msg: - 603 00000560: E15C0001 00000030 load SCRATCHB0, 1, ld_phase_flag - 604 00000568: 725C0000 00000000 move SCRATCHB0 to SFBR - 605 ; If we got here from reselect just bailout since ld_nexus is - 606 ; not setup and the code using it is not needed anyway (no data xfer) - 607 00000570: 808C0009 00000010 jump rel( bailout ), if kphase_RESELECT - 608 - 609 00000578: 785C0D00 00000000 move kphase_DISCONNECT to SCRATCHB0 - 610 00000580: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 611 - 612 00000588: bailout: - 613 00000588: 785FFF00 00000000 move 0xFF to SCRATCHB3 ; invalidate nexus index for driver - 614 00000590: E05F0001 0000002B store SCRATCHB3, 1, ld_nexus_index+3 - 615 00000598: 7C027F00 00000000 move SCNTL2 & 0x7F to SCNTL2 ; Clr SDU: SCSI Disconnect Unexpected - 616 000005A0: 60000040 00000000 clear ACK - 617 000005A8: 48000000 00000000 WAIT DISCONNECT ; wait for bus-free - 618 000005B0: 80880000 FFFFFB68 jump rel( select_phase ) ; go see if more to do - 619 - 620 - 621 ;****************************************************************** - 622 ; - 623 ; ??? mlj - saveDataPointer and restoreDataPointer are incorrect. - 624 ; ??? They basically do nothing. - 625 ; Save Data Pointer - 626 ; - 627 ;***************************************************************** - 628 - 629 000005B8: saveDataPointer: - 630 000005B8: 785C0E00 00000000 move kphase_saveDataPointer to SCRATCHB0 - 631 000005C0: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 632 000005C8: 60000040 00000000 clear ACK - 633 000005D0: 80880000 FFFFFCB8 jump rel( phase_handler ) - 634 - 635 - 636 ;****************************************************************** - 637 ; - 638 ; ??? mlj - saveDataPointer and restoreDataPointer are incorrect. - 639 ; ??? They basically do nothing. - 640 ; Restore Data Pointer - 641 ; The local values still blocks, still bytes and data address - 642 ; must be loaded from the corresponding NEXUS data set. - 643 ; This message should followed an IDE (parity error) - 644 ; - 645 ;***************************************************************** - 646 - 647 000005D8: restoreDataPointer: - 648 000005D8: 785C0F00 00000000 move kphase_restoreDataPointer to SCRATCHB0 - 649 000005E0: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 650 000005E8: 60000040 00000000 clear ACK - 651 000005F0: 80880000 FFFFFC98 jump rel( phase_handler ) - 652 - 653 - 654 ;***************************************************************** - 655 ; - 656 ; Synchronous data transfer request or response - 657 ; - 658 ;***************************************************************** - 659 000005F8: sdtr: - 660 000005F8: 0F000002 00000043 move 2, ld_message+3, when MSG_IN ; Read period & offset from bus - 661 00000600: 98080000 0000000D int negotiateSDTR - 662 - 663 - 664 ;*************************************************************************** - 665 ; - 666 ; Wide Data Transfer request or response - 667 ; - 668 ;*************************************************************************** - 669 00000608: wdtr: - 670 00000608: 0F000001 00000043 move 1, ld_message+3, when MSG_IN ; get Transfer Width Exponent fm bus - 671 00000610: 98080000 0000000E int negotiateWDTR - 672 - 673 - 674 ;***************************************************************** - 675 ; - 676 ; Reselect phase - 677 ; The chip waits here either for a Reselection from a Target or - 678 ; a SIGP from the driver indicating something in the mailbox. - 679 ; If reselected, the script uses the Nexus value which is either - 680 ; a Tag or a SCSI ID/LUN combo to lookup the Nexus. - 681 ; Then init the SXFER and SCNTL3 registers from the device config table. - 682 ; - 683 ;***************************************************************** - 684 - 685 00000618: try_reselect: ; Select failed - probably reselecting - 686 ; Cf NCR Errata Listing 117 Item 1: - 687 00000618: 7C00DF00 00000000 move SCNTL0 & 0xDF to SCNTL0 ; clr Start bit - 688 00000620: 7A1A0000 00000000 move CTEST2 | 0x00 to CTEST2 ; Clear SIGP bit from ISTAT reg - 689 - 690 00000628: reselect_phase: - 691 00000628: 785C0900 00000000 move kphase_RESELECT to SCRATCHB0 ; Set phase indicator - 692 00000630: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 693 - 694 00000638: 785FFF00 00000000 move 0xFF to SCRATCHB3 ; invalidate nexus index for driver - 695 00000640: E05F0001 0000002B store SCRATCHB3, 1, ld_nexus_index+3 - 696 - 697 ; wait here for reselect from a Target - 698 ; or SIGP from the driver - 699 - 700 00000648: 54000000 FFFFFAD0 WAIT RESELECT REL( select_phase ) ; jump if SIGP - 701 - 702 ; Reselected: - 703 - 704 00000650: 720A0000 00000000 move SSID to SFBR ; SSID = [ Valxxx Scsi_id ] - 705 00000658: 980C7F00 00000007 int unknown_reselect, if 0 and mask 0x7F; Interrupt if VAL bit not set - 706 00000660: 6C5C0F00 00000000 move SFBR & 0x0F to SCRATCHB0 ; B0 = Target ID - 707 00000668: E05C0001 00000020 store SCRATCHB0, 1, ld_scsi_id ; save it - 708 - 709 00000670: 88880000 FFFFFA48 call rel( initContext ) ; setup sync regs here - 710 - 711 00000678: 9F030000 00000005 int no_msgin_after_reselect, when not MSG_IN - 712 - 713 00000680: 0F000001 00000040 move 1, ld_message, when MSG_IN ; Read Identify byte from bus - 714 - 715 ; if another REQ is asserted, a SimpleQueueTag message should be next - 716 - 717 00000688: 60000040 00000000 clear ACK ; notify Target: msg byte rx'd - 718 00000690: 878B0000 00000048 jump rel( getNextMsg ), when MSG_IN ; jump if SimpleQueueTag coming - 719 - 720 ; untagged operation: - 721 - 722 00000698: 6C340700 00000000 move SFBR & 0x07 to SCRATCHA0 ; isolate LUN from Identify byte - 723 - 724 000006A0: E15C0001 00000020 load SCRATCHB0, 1, ld_scsi_id ; B0 = Target ID - 725 000006A8: 60000400 00000000 clear CARRY - 726 000006B0: 715C0000 00000000 move SCRATCHB0 SHL SFBR ; shift left #1 - 727 000006B8: 695C0000 00000000 move SFBR SHL SCRATCHB0 ; shift left #2 - 728 000006C0: 715C0000 00000000 move SCRATCHB0 SHL SFBR ; shift left #3 - 729 000006C8: 7AB40000 00000000 move SCRATCHA0 | SFBR to SCRATCHA0 ; form Nexus index = 0b0TTTTLLL - 730 - 731 000006D0: E0340001 00000028 store SCRATCHA0, 1, ld_nexus_index ; store as index to Nexus - 732 000006D8: 80880000 00000030 jump rel( haveNexusIndex ) - 733 - 734 ; should be tagged operation: - 735 - 736 000006E0: getNextMsg: - 737 000006E0: 0F000001 00000040 move 1, ld_message, when MSG_IN ; read message byte from bus - 738 000006E8: 808C0004 FFFFFE70 jump rel( disconnect_msg ), if 0x04 ; if Disconnect, oh well. - 739 000006F0: 60000040 00000000 clear ACK - 740 000006F8: 80840020 FFFFFB90 jump rel( phase_handler ), if not 0x20; Branch if not Queue tag code - 741 ; get the Queue Tag and save as the nexus index - 742 00000700: 0F000001 00000028 move 1, ld_nexus_index, when MSG_IN ; Nexus index <- Tag from bus - 743 00000708: 60000040 00000000 clear ACK ; acknowledge it - 744 - 745 00000710: haveNexusIndex: - 746 00000710: 785F0000 00000000 move 0x00 to SCRATCHB3 ; clear invalid-nexus-index flag - 747 00000718: E05F0001 0000002B store SCRATCHB3, 1, ld_nexus_index+3 - 748 00000720: 88880000 FFFFF930 call rel( findNexusFromIndex ) ; set DSA <- Nexus pointer - 749 00000728: 80880000 FFFFFB60 jump rel( phase_handler ) ; start handling phases. - 750 - 751 - 752 ;***************************************************************** - 753 ; - 754 ; AbortMailbox - Abort (or BusDeviceReset) the mailbox entry. - 755 ; This is a queued operation - not an immediate - 756 ; operation as is issueAbort_BDR. - 757 ; The Abort message clears all IO processes for the - 758 ; selecting Initiator on the specified LUN. - 759 ; - 760 ; The Bus Device Reset message clears all IO processes for - 761 ; all Initiators on all LUNs of selected Target. - 762 ; It forces a hard reset condition to the selected SCSI device. - 763 ; - 764 ; A0 = Identify byte (0xC0 + LUN N.B. Disconnect allowed) - 765 ; A1 = Tag, if any - 766 ; A2 = SCSI ID - 767 ; A3 = Abort code Abort=0x06; Abort Tag=0D; Bus Device Reset=0x0C - 768 ; - 769 ; Mailbox not cleared by SCRIPTS so that driver can find SCSI ID when done - 770 ; N.B.: Device is Async and Narrow after BDR!!! - 771 ; Driver must set the device config table values accordingly. - 772 ;***************************************************************** - 773 - 774 00000730: AbortMailbox: - 775 00000730: 785C0B00 00000000 move kphase_ABORT_MAILBOX to SCRATCHB0 ; Set phase code - 776 00000738: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 777 - 778 00000740: 785FFF00 00000000 move 0xFF to SCRATCHB3 ; invalidate nexus index for driver - 779 00000748: E05F0001 0000002B store SCRATCHB3, 1, ld_nexus_index+3 - 780 - 781 00000750: E15E0001 00000012 load SCRATCHB2, 1, ld_AbortBdr_mailbox+2 ; get SCSI ID - 782 00000758: E05E0001 00000762 store SCRATCHB2, 1, AbortSelect+2 ; *** Patch the Select/ATN instruction - 783 - 784 00000760: AbortSelect: - 785 00000760: 45000000 FFFFFEB0 SELECT ATN 0, REL( try_reselect ) ; *** Patched SCSI ID - 786 - 787 00000768: 72350000 00000000 move SCRATCHA1 to SFBR ; check for Tag - 788 00000770: 80840000 00000038 jump rel( taggedAbort ) if not 0x00 ; jump if tagged abort - 789 - 790 ; untagged Abort or BusDeviceReset: - 791 - 792 00000778: 72370000 00000000 move SCRATCHA3 to SFBR ; position the abort code - 793 00000780: 6A350000 00000000 move SFBR to SCRATCHA1 - 794 00000788: E0340002 00000038 store SCRATCHA0, 2, ld_scratch ; Store Identify and Abort msgs - 795 00000790: 78020000 00000000 move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected - 796 00000798: 0E000002 00000038 move 2, ld_scratch , when MSG_OUT ; emit Identify and Abort messages - 797 000007A0: 48000000 00000000 WAIT DISCONNECT - 798 000007A8: 98080000 00000009 int abort_mailbox - 799 - 800 ; AbortTag: - 801 - 802 000007B0: taggedAbort: - 803 000007B0: 72350000 00000000 move SCRATCHA1 to SFBR ; position the Tag - 804 000007B8: 6A360000 00000000 move SFBR to SCRATCHA2 - 805 000007C0: 78352000 00000000 move 0x20 to SCRATCHA1 ; gen SimpleQueueTag code - 806 000007C8: E0340004 00000038 store SCRATCHA0, 4, ld_scratch ; store Identify, SQT, Tag, AbortTag - 807 000007D0: 78020000 00000000 move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected - 808 000007D8: 0E000004 00000038 move 4, ld_scratch, when MSG_OUT ; emit all 4 bytes - 809 000007E0: 48000000 00000000 WAIT DISCONNECT - 810 000007E8: 98080000 00000009 int abort_mailbox - 811 - 812 - 813 ;***************************************************************** - 814 ; - 815 ; issueAbort_BDR - Abort (or BusDeviceReset) the current operation. - 816 ; This is an immediate operation - not a queued operation - 817 ; as is AbortMailbox. - 818 ; The Abort message clears all IO processes for the - 819 ; selecting Initiator on the specified LUN. - 820 ; - 821 ; The Bus Device Reset message clears all IO processes for - 822 ; all Initiators on all LUNs of selected Target. - 823 ; It forces a hard reset condition to the selected SCSI device. - 824 ; - 825 ;***************************************************************** - 826 - 827 000007F0: issueAbort_BDR: - 828 000007F0: 785C0A00 00000000 move kphase_ABORT_CURRENT to SCRATCHB0 ; Set phase code - 829 000007F8: E05C0001 00000030 store SCRATCHB0, 1, ld_phase_flag - 830 - 831 00000800: 74140800 00000000 move ISTAT & 0x08 to SFBR ; see if Target connected to bus - 832 00000808: 980C0000 0000000A int abort_current, if 0 ; interrupt driver if not connected - 833 - 834 00000810: 58000008 00000000 SET ATN ; get Target's attention - 835 00000818: E1100004 0000002C load DSA0, 4, ld_nexus ; load pointer to Nexus - 836 - 837 00000820: bucketLoop: - 838 00000820: 60000040 00000000 clear ACK - 839 00000828: 868B0000 000000A8 jump rel( sendAbortBDR ), when MSG_OUT ; wait for REQ. Jump if OK. - 840 - 841 00000830: 838A0000 00000030 jump rel( BucketInStatus ), if STATUS ; bit bucket in - 842 00000838: 878A0000 00000038 jump rel( BucketInMsg ), if MSG_IN ; bit bucket in - 843 00000840: 818A0000 00000040 jump rel( BucketInData ), if DATA_IN ; bit bucket in - 844 - 845 00000848: 7834AD00 00000000 move 0xAD to SCRATCHA0 - 846 00000850: 808A0000 00000040 jump rel( BucketOutData ), if DATA_OUT ; bit bucket out - 847 00000858: 828A0000 00000058 jump rel( BucketOutCmd ), if CMD ; bit bucket out - 848 00000860: 98080000 00000000 int unknown_phase ; back to driver for harsher measures - 849 - 850 - 851 00000868: BucketInStatus: - 852 00000868: 0B000001 00000038 move 1, ld_scratch, when STATUS ; eat the Status byte - 853 00000870: 80880000 FFFFFFA8 jump rel( bucketLoop ); ; keep bit-bucketing bytes - 854 - 855 00000878: BucketInMsg: - 856 00000878: 0F000001 00000038 move 1, ld_scratch, when MSG_IN ; eat a message byte - 857 00000880: 80880000 FFFFFF98 jump rel( bucketLoop ); ; keep bit-bucketing bytes - 858 - 859 00000888: BucketInData: - 860 00000888: 09000001 00000038 move 1, ld_scratch, when DATA_IN ; eat a data byte - 861 00000890: 80880000 FFFFFF88 jump rel( bucketLoop ); ; keep bit-bucketing bytes - 862 - 863 00000898: BucketOutData: - 864 00000898: 7B347300 00000000 move SCRATCHA0 xor 0x73 to SCRATCHA0 ; gen 0xDEAD ... - 865 000008A0: E0340001 00000038 store SCRATCHA0, 1, ld_scratch - 866 000008A8: 08000001 00000038 move 1, ld_scratch, when DATA_OUT ; pad a byte out - 867 000008B0: 80880000 FFFFFF68 jump rel( bucketLoop ); ; keep bit-bucketing bytes - 868 - 869 000008B8: BucketOutCmd: - 870 000008B8: 78340000 00000000 move 0x00 to SCRATCHA0 ; load Null, TestUnitReady, whatever - 871 000008C0: E0340001 00000038 store SCRATCHA0, 1, ld_scratch - 872 000008C8: 0A000001 00000038 move 1, ld_scratch, when CMD ; pad a byte out - 873 000008D0: 80880000 FFFFFF48 jump rel( bucketLoop ); ; keep bit-bucketing bytes - 874 - 875 - 876 000008D8: sendAbortBDR: - 877 000008D8: 78020000 00000000 move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected - 878 000008E0: 0E000001 00000000 move 1, ld_AbortCode, when MSG_OUT ; Send Abort(06) or BDR(0C) message - 879 000008E8: E1340004 00000004 load SCRATCHA0, 4, ld_zeroes ; load 0's - 880 000008F0: E0340004 00000000 store SCRATCHA0, 4, ld_AbortCode ; clear the Abort code - 881 000008F8: 48000000 00000000 WAIT DISCONNECT - 882 00000900: 98080000 0000000A int abort_current ; went BusFree - tell Driver - ---SYMBOL---------------------------VALUE------TYPE------- -abort_current 0000000A ABSOLUTE -abort_mailbox 00000009 ABSOLUTE -kphase_ABORT_MAILBOX 0000000B ABSOLUTE -kphase_ABORT_CURRENT 0000000A ABSOLUTE -kphase_CMD_COMPLETE 0000000C ABSOLUTE -kphase_COMMAND 00000002 ABSOLUTE -kphase_DATA_IN 00000001 ABSOLUTE -kphase_DATA_OUT 00000000 ABSOLUTE -kphase_DISCONNECT 0000000D ABSOLUTE -kphase_MSG_IN 00000007 ABSOLUTE -kphase_MSG_OUT 00000006 ABSOLUTE -kphase_RESELECT 00000009 ABSOLUTE -kphase_SELECT 00000008 ABSOLUTE -kphase_STATUS 00000003 ABSOLUTE -kphase_restoreDataPointer 0000000F ABSOLUTE -kphase_saveDataPointer 0000000E ABSOLUTE -negotiateWDTR 0000000E ABSOLUTE -negotiateSDTR 0000000D ABSOLUTE -no_msgin_after_reselect 00000005 ABSOLUTE -reqack_too_large 00000006 ABSOLUTE -sglist_complete 0000000F ABSOLUTE -status_error 00000001 ABSOLUTE -TLQ_CDP 00000018 ABSOLUTE -TLQ_CDBp 00000010 ABSOLUTE -TLQ_IWR 00000022 ABSOLUTE -TLQ_MSGOp 00000008 ABSOLUTE -TLQ_SDP 0000001C ABSOLUTE -TLQ_index 00000020 ABSOLUTE -TLQ_pad 00000023 ABSOLUTE -TLQ_xferAdr 00000004 ABSOLUTE -TLQ_SCSI_ID 00000000 ABSOLUTE -TLQ_xferStarted 00000021 ABSOLUTE -unallocated_nexus 00000008 ABSOLUTE -unexpected_ext_msg 00000003 ABSOLUTE -unexpected_msg 00000002 ABSOLUTE -unknown_message_out 0000000B ABSOLUTE -unknown_msg_reject 0000000C ABSOLUTE -unknown_phase 00000000 ABSOLUTE -unknown_reselect 00000007 ABSOLUTE -wide_32_not_supported 00000004 ABSOLUTE -BSC_SCRIPT 00000000 CODE SEGMENT -SCRIPT 00000000 CODE SEGMENT -local_data 00000000 DATA SEGMENT -clearACK 00000448 ENTRY -issueAbort_BDR 000007F0 ENTRY -issueMessageOut 000002F0 ENTRY -phase_handler 00000290 ENTRY -select_phase 00000120 ENTRY -AbortSelect 00000760 LABEL -AbortMailbox 00000730 LABEL -BucketInData 00000888 LABEL -BucketInMsg 00000878 LABEL -BucketInStatus 00000868 LABEL -BucketOutCmd 000008B8 LABEL -BucketOutData 00000898 LABEL -bucketLoop 00000820 LABEL -bailout 00000588 LABEL -bucket_loop 000003B0 LABEL -clear_mailbox 00000258 LABEL -cmdComplete 000004C8 LABEL -command_phase 00000328 LABEL -data_in_phase 00000398 LABEL -data_out_phase 00000350 LABEL -disconnect_msg 00000560 LABEL -doItPatch 00000390 LABEL -driverXfer 00000370 LABEL -extended_msg 00000488 LABEL -fetchMailbox 00000188 LABEL -findNexusFromIndex 00000058 LABEL -getNextMsg 000006E0 LABEL -haveNexusIndex 00000710 LABEL -ignoreWideResidue 00000458 LABEL -initContext 000000C0 LABEL -message_in_phase 000003E8 LABEL -message_out_phase 000002D0 LABEL -msg_reject 00000440 LABEL -next_mailbox 00000248 LABEL -patchGetDevConfigOffset 000000F0 LABEL -patchArrayOffset 00000098 LABEL -reselect_phase 00000628 LABEL -restoreDataPointer 000005D8 LABEL -sdtr 000005F8 LABEL -saveDataPointer 000005B8 LABEL -sendAbortBDR 000008D8 LABEL -status_phase 000003C8 LABEL -taggedAbort 000007B0 LABEL -testMbxLp 000004F0 LABEL -try_reselect 00000618 LABEL -wdtr 00000608 LABEL -ld_IOdone_mailbox 00000014 RELATIVE. -ld_AbortBdr_mailbox 00000010 RELATIVE. -ld_counter 0000000C RELATIVE. -ld_device_table_base_adr 00000034 RELATIVE. -ld_mailboxp 0000001C RELATIVE. -ld_message 00000040 RELATIVE. -ld_message4 00000044 RELATIVE. -ld_nexus 0000002C RELATIVE. -ld_nexus_array_base 00000024 RELATIVE. -ld_nexus_index 00000028 RELATIVE. -ld_pad 00000048 RELATIVE. -ld_phase_flag 00000030 RELATIVE. -ld_sched_mlbx_base_adr 00000018 RELATIVE. -ld_scratch 00000038 RELATIVE. -ld_scsi_id 00000020 RELATIVE. -ld_size 0000004C RELATIVE. -ld_status 00000008 RELATIVE. -ld_unused 0000003C RELATIVE. -ld_zeroes 00000004 RELATIVE. -ld_AbortCode 00000000 RELATIVE. \ No newline at end of file diff --git a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.ss b/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.ss deleted file mode 100644 index 0d7381b3b..000000000 --- a/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.ss +++ /dev/null @@ -1,882 +0,0 @@ - -; Copyright (c) 1997-1999 Apple Computer, Inc. All rights reserved. -; -; @APPLE_LICENSE_HEADER_START@ -; -; The contents of this file constitute Original Code as defined in and -; are subject to the Apple Public Source License Version 1.1 (the -; "License"). You may not use this file except in compliance with the -; License. Please obtain a copy of the License at -; http://www.apple.com/publicsource and read it before using this file. -; -; This Original Code and all software distributed under the License are -; distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER -; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, -; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, -; FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the -; License for the specific language governing rights and limitations -; under the License. -; -; @APPLE_LICENSE_HEADER_END@ -; -; File Ownership: -; -; DRI: Mike Johnson -; -; Other Contact: Russ Berkoff -; -; Technology: SCSI -; -; Writers: -; -; (MLJ) Mike Johnson -; (RRA) Rick Auricchio - - -; NCR Errata Listing 125 Item 1 : Clear the SCNTL0 start bit -; when jump to reselect during select (try_reselect) -; -; NCR Errata Listing 117 Item 4 : Bad parity if odd bytes during -; wide transfer. Only for DATA OUT in Initiator mode. -; (Confirm by Manfred Eierle 3rd June 93 not during DATA IN) - - ARCH 825A ;specifically for 825a and 875 (new instructions) - - - ;***************************************************************** - ; - ; Phase codes - These values represent which action is being handled - ; - ;***************************************************************** - - ABSOLUTE kphase_DATA_OUT = 0x00 - ABSOLUTE kphase_DATA_IN = 0x01 - ABSOLUTE kphase_COMMAND = 0x02 - ABSOLUTE kphase_STATUS = 0x03 - ABSOLUTE kphase_MSG_OUT = 0x06 - ABSOLUTE kphase_MSG_IN = 0x07 - ABSOLUTE kphase_SELECT = 0x08 - ABSOLUTE kphase_RESELECT = 0x09 - ABSOLUTE kphase_ABORT_CURRENT = 0x0A - ABSOLUTE kphase_ABORT_MAILBOX = 0x0B - ABSOLUTE kphase_CMD_COMPLETE = 0x0C - ABSOLUTE kphase_DISCONNECT = 0x0D - ABSOLUTE kphase_saveDataPointer = 0x0E ; ??? driver work to be done - ABSOLUTE kphase_restoreDataPointer = 0x0F ; ??? driver work to be done - - - ;***************************************************************** - ; interrupt codes - ;***************************************************************** - - ABSOLUTE unknown_phase = 0x00 ; A spurious phase on SCSI Bus - ABSOLUTE status_error = 0x01 ; IO completes, but with status error - ABSOLUTE unexpected_msg = 0x02 ; An 'unknown' message is in ld_message var - ABSOLUTE unexpected_ext_msg = 0x03 ; An 'unknown' extended message in ld_message - ABSOLUTE wide_32_not_supported = 0x04 ; The device wants 32 bits data phase - ABSOLUTE no_msgin_after_reselect = 0x05 ; No message-in after reselection - ABSOLUTE reqack_too_large = 0x06 ; The device answer ReqAck offset is greater than 8 - ABSOLUTE unknown_reselect = 0x07 ; The valid bit in SFBR reg not set - ABSOLUTE unallocated_nexus = 0x08 ; nexus index -> 0xFFFFFFFF - ABSOLUTE abort_mailbox = 0x09 ; Abort/BDR mailbox completed - ABSOLUTE abort_current = 0x0A ; Abort/BDR current op completed - ABSOLUTE unknown_message_out = 0x0B ; Unknown phase before message out - ABSOLUTE unknown_msg_reject = 0x0C ; Unknown message reject - ABSOLUTE negotiateSDTR = 0x0D ; Sync negotiation rx'd - ABSOLUTE negotiateWDTR = 0x0E ; Wide negotiation rx'd - ABSOLUTE sglist_complete = 0x0F ; SGList complete - - - ;***************************************************************** - ; - ; Data structure for T/L/Q Nexus: - ; - ;***************************************************************** - - ABSOLUTE TLQ_SCSI_ID = 0 ; 4 SCSI ID et al for SELECT instruction - ABSOLUTE TLQ_xferAdr = 4 ; 4 Physical address of CHMOV instructions - ABSOLUTE TLQ_MSGOp = 8 ; 8 Byte count, data adr -> TLQ_MSGO - ABSOLUTE TLQ_CDBp = 16 ; 8 Byte count, data adr -> TLQ_CDB - ABSOLUTE TLQ_CDP = 24 ; 4 Current Data Pointer - ABSOLUTE TLQ_SDP = 28 ; 4 Saved Data Pointer - ABSOLUTE TLQ_index = 32 ; 1 index into nexus array - ABSOLUTE TLQ_xferStarted= 33 ; 1 transfer started flag - ABSOLUTE TLQ_IWR = 34 ; 1 flag to Ignore Wide Residue - ABSOLUTE TLQ_pad = 35 ; 1 pad byte - - - ;***************************************************************** - ; - ; ENTRY declarations - Declare entry points for driver - ; - ;***************************************************************** - - ENTRY select_phase - ENTRY phase_handler - ENTRY issueMessageOut ; for negotiation and Reject messages - ENTRY issueAbort_BDR ; to immediately Abort or Bus-Device-Reset - ENTRY clearACK ; MsgIn done - clr ACK, jump to phase handler - - - ;***************************************************************** - ; - ; Define local data structure at start of SCRIPTS. - ; This structure is allocated by the following nops. - ; - ;***************************************************************** - ; - - RELATIVE local_data \ - ld_AbortCode = 4{??}\ ; 1 byte code to Abort or BDR - ld_zeroes = 4{??}\ ; 4 bytes of 0 to clear registers - ld_status = 4{??}\ ; Status byte from target - ld_counter = 4{??}\ ; index into mailbox array - ld_AbortBdr_mailbox = 4{??}\ ; Abort/BusDeviceReset mailbox - ld_IOdone_mailbox = 4{??}\ ; [ nexus 0 0 semaphore ] - ld_sched_mlbx_base_adr = 4{??}\ ; base addr of mailbox array - ld_mailboxp = 4{??}\ ; address of current mailbox - ld_scsi_id = 4{??}\ ; ptr to current mailbox - ld_nexus_array_base = 4{??}\ ; base address of Nexus pointers - ld_nexus_index = 4{??}\ ; index to Nexus pointer - ld_nexus = 4{??}\ ; address of Nexus - ld_phase_flag = 4{??}\ ; for debugging - ld_device_table_base_adr = 4{??}\ ; device configuration table - ld_scratch = 4{??}\ ; scratch memory - ld_unused = 4{??}\ ; unused - ld_message = 4{??}\ ; buffer for MsgIn bytes - ld_message4 = 4{??}\ ; buffer continuation - ld_pad = 4{??}\ ; padding - ld_size = 4{??} ; size of this structure - - -PROC BSC_SCRIPT: - - ; *** These NOPs must be at address 0. *** - ; *** This is reserved space for the structure "local_data". *** - ; *** The driver inits this area to zero. *** - - nop 0 ; ld_AbortCode, ld_zeroes - nop 0 ; ld_status, ld_counter - - nop 0 ; ld_AbortBdr_mailbox, ld_IOdone_mailbox - nop 0 ; ld_sched_mlbx_base_adr, ld_mailboxp - - nop 0 ; ld_scsi_id, ld_nexus_array_base - nop 0 ; ld_nexus_index, ld_nexus - - nop 0 ; ld_phase_flag, ld_device_table_base_adr - nop 0 ; ld_scratch, ld_unused - - nop 0 ; ld_message, ld_message4 - nop ld_size ; ld_pad, ld_size (Use ld_size or lose it) - - nop sglist_complete ; use sglist_complete or lose it from gen'd output file - - ;**************************************************************************** - ; - ; findNexusFromIndex - load DSA with pointer to Nexus given a Nexus index: - ; - ;**************************************************************************** - -findNexusFromIndex: - - load SCRATCHA0, 4, ld_nexus_index ; load index and leading zeroes - clear CARRY - move SCRATCHA0 SHL 0 to SCRATCHA0 ; double the index - move SCRATCHA1 SHL 0 to SCRATCHA1 - move SCRATCHA0 SHL 0 to SCRATCHA0 ; double again - move SCRATCHA1 SHL 0 to SCRATCHA1 ; A0 now has index to 4-byte address - store SCRATCHA0, 4, patchArrayOffset+4 ; *** patch the code - - load DSA0, 4, ld_nexus_array_base ; load base address of array of Nexus pointers -patchArrayOffset: - load DSA0, 4, DSAREL( 0 ) ; *** patched offset. Load pointer. - - move DSA0 to SFBR ; Ensure pointer is not 0xFFFFFFFF - int unallocated_nexus, if 0xFF ; Interrupt if NFG - - store DSA0, 4, ld_nexus ; Store the Nexus pointer - return ; end findNexusFromIndex - - - ;**************************************************************************** - ; - ; initContext - Initialize the registers for Sync and Wide using - ; values stored in the device configuration table. - ; Return with values in SCRATCHB for Select code. - ; - ;**************************************************************************** - -initContext: - - load SCRATCHB0, 4, ld_scsi_id ; load 4-bit SCSI ID and zeroes - clear CARRY - move SCRATCHB0 SHL SCRATCHB0 ; * 2 - move SCRATCHB0 SHL SCRATCHB0 ; * 2 -> UInt32 index - store SCRATCHB0, 4, patchGetDevConfigOffset+4 ; *** Patch load code - - load DSA0, 4, ld_device_table_base_adr ; load base physical addr of tables - -patchGetDevConfigOffset: - load SCRATCHB0, 4, DSAREL( 0 ) ; *** Patched table offset *** - - ; SCRATCHB0 = 0 - ; SCRATCHB1 = TP,MO (SXFER bits7-5 bits3-0) - ; SCRATCHB2 = 0 (position for SCSI ID) - ; SCRATCHB3 = SCCF,EWS (SCNTL3 bits6-4 bit 3) - - move SCRATCHB1 to SFBR ; init SXFER from B1 - move SFBR to SXFER - ; Init SCNTL3 from B3 - move SCRATCHB3 to SFBR - move SFBR to SCNTL3 - return ; return with SCRATCHB intact. - - - ;***************************************************************** - ; - ; Select_phase: - ; Clear the SIGP bit. - ; Check if any Abort/BusDeviceReset request waiting. - ; Nexus is found in the list of 256 mailboxes. - ; If current mailbox is empty, jump to reselect_phase. - ; SCRIPTS tries to select device. - ; If select fails due to reselect, jump to reselect_phase - ; Select Timeout handled by driver. - ; If select succeeds, clear the mailbox entry - ; and increment the mailbox counter. - ; Jump to the phase_handler (hopefully for MSG_OUT) - ; - ;***************************************************************** - -select_phase: - - move CTEST2 | 0x00 to CTEST2 ; Clear SIGP bit from ISTAT reg - - ; Check abort mailbox: - - load SCRATCHA0, 4, ld_AbortBdr_mailbox ; Get AbortBdr mailbox - ; The Identify byte in byte 0 is also the semaphore - ; A0 = Identify byte (0xC0 + LUN N.B. Disconnect allowed) - ; A1 = Tag, if any - ; A2 = SCSI ID - ; A3 = Abort code Abort=0x06; Abort Tag=0D; Bus Device Reset=0x0C - move SCRATCHA0 to SFBR ; test the semaphore/Identify - jump rel( AbortMailbox ), if not 0 ; jump if aborting - - - ; Get the next IO nexus in the mailboxes circular list. - ; Calculate current mailbox address as so: - ; counter byte index * 4 to get mailbox index - ; add base physical address of mailboxes giving current mailbox address - - load SCRATCHA0, 4, ld_counter ; get 1-byte mailbox counter & 0s - clear CARRY - move SCRATCHA0 SHL 0 to SCRATCHA0 ; double it - move SCRATCHA1 SHL 0 to SCRATCHA1 - move SCRATCHA0 SHL 0 to SCRATCHA0 ; double it again - move SCRATCHA1 SHL 0 to SCRATCHA1 ; now have a UInt32 index - store SCRATCHA0, 4, fetchMailbox+4 ; *** patch the load DSA instruction - store SCRATCHA0, 4, clear_mailbox+4 ; *** patch the store DSA instruction - - load DSA0, 4, ld_sched_mlbx_base_adr ; load base physical address of mailboxes - -fetchMailbox: - load DSA0, 4, DSAREL( 0 ) ; *** Patched offset. Load Nexus address - store DSA0, 4, ld_nexus ; save pointer to current Nexus - load SCRATCHA0, 4, ld_nexus ; copy to A0 - - move SCRATCHA0 to SFBR ; - jump rel( next_mailbox ), if 1 ; if low-byte == 0x01 then cancelled mailbox - - move SCRATCHA1 | SFBR to SFBR ; if non-zero, have implicit semaphore - move SCRATCHA2 | SFBR to SFBR - move SCRATCHA3 | SFBR to SFBR - jump rel( reselect_phase ), if 0 ; go to reselect_phase if empty - - ;***************************************************************** - ; - ; Something in mailbox: we have work to do - ; - ;***************************************************************** - - move kphase_SELECT to SCRATCHB0 ; set phase indicator - store SCRATCHB0, 1, ld_phase_flag - - load SCRATCHB0, 4, ld_zeroes ; clr the invalid-nexus-index flag - load SCRATCHB0, 1, DSAREL( TLQ_index ) ; get index byte from nexus - store SCRATCHB0, 4, ld_nexus_index ; save it in local data - - load DSA0, 4, ld_nexus ; restore DSA register - load SCRATCHB2, 1, DSAREL( TLQ_SCSI_ID+2 ) ; get Target's SCSI ID - move SCRATCHB2 to SFBR - move SFBR to SCRATCHB0 ; position it - store SCRATCHB0, 1, ld_scsi_id ; save it - call rel( initContext ) ; setup Sync/Wide regs in SCRATCHB - load DSA0, 4, ld_nexus ; restore DSA register - store SCRATCHB1, 1, DSAREL( TLQ_SCSI_ID+1 ) ; SXFER - store SCRATCHB3, 1, DSAREL( TLQ_SCSI_ID+3 ) ; SCNTL3 - - ;********************** select the device ******************************** - SELECT ATN from TLQ_SCSI_ID, rel( try_reselect ) ; ************************ - ;************************************************************************* - - ; looking good - clear the mailbox: - -next_mailbox: - load SCRATCHA0, 4, ld_zeroes ; zero out scratch register A - load DSA0, 4, ld_sched_mlbx_base_adr ; load base physical address of mailboxes -clear_mailbox: - store SCRATCHA0, 4, DSAREL( 0 ) ; *** Patched offset. Zero the mailbox - - ; Update the index to the mailbox circular list: - load SCRATCHB0, 1, ld_counter ; get counter (mailbox index) - move SCRATCHB0 + 1 to SCRATCHB0 ; add 1 - store SCRATCHB0, 1, ld_counter ; put it back - - load SCRATCHB0, 1, ld_nexus ; if low-byte == 0x01 then cancelled mailbox - move SCRATCHB0 to SFBR - jump rel( select_phase ), if 1 - -; *** FALL THROUGH TO phase_handler *** - - - ;***************************************************************** - ; - ; Phase_handler - ; The phase handler script is a dispatcher function of SCSI phase - ; - ;***************************************************************** - -phase_handler: - load DSA0, 4, ld_nexus ; reload DSA - jump rel( command_phase ), when CMD ; wait for REQ - jump rel( data_out_phase ), if DATA_OUT ; already latched REQ signal - jump rel( message_out_phase ), if MSG_OUT - jump rel( data_in_phase ), if DATA_IN - jump rel( status_phase ), if STATUS - jump rel( message_in_phase ), if MSG_IN - int unknown_phase - - - ;***************************************************************** - ; - ; Message-Out phase - ; - ;***************************************************************** - -message_out_phase: - move kphase_MSG_OUT to SCRATCHB0 ; Set phase indicator - store SCRATCHB0, 1, ld_phase_flag - - move from TLQ_MSGOp, when MSG_OUT ; put out the message(s) - jump rel( phase_handler ) - - - ; issueMessageOut - Driver entry point for Sync/Wide negotiation and - ; to issue message Reject: - -issueMessageOut: - set ATN ; tell Target we have something to say - clear ACK - jump rel( message_out_phase ), when MSG_OUT ; wait for REQ. Jump if msg-out phase. - jump rel( phase_handler ), if not MSG_IN ; jump if weird phase - move 1, ld_scratch+1, when MSG_IN ; dump the msg byte - clear ACK ; accept Target's last msg-in byte - jump rel( issueMessageOut ) - - - ;***************************************************************** - ; - ; Command phase - ; - ;***************************************************************** - -command_phase: - move kphase_COMMAND to SCRATCHB0 ; Set phase indicator - store SCRATCHB0, 1, ld_phase_flag - - clear ATN ; In case we missed the sending nego - move FROM TLQ_CDBp, when CMD ; issue the CDB - jump rel( phase_handler ) - - - ;***************************************************************** - ; - ; Data_out_phase - ; - ;***************************************************************** - -data_out_phase: - move kphase_DATA_OUT to SCRATCHB0 ; Set phase indicator - store SCRATCHB0, 1, ld_phase_flag - - call rel( driverXfer ) ; call driver-built CHMOV instructions - jump rel( phase_handler ) ; if all data xfer'd, get next phase - -driverXfer: ; get here from data-in code also - load SCRATCHA0, 4, DSAREL( TLQ_xferAdr ) - store SCRATCHA0, 4, doItPatch+4 ; *** patch the JUMP address - move 0xFF to SCRATCHA1 - store SCRATCHA1, 1, DSAREL( TLQ_xferStarted ) - -doItPatch: - jump 0x0333 ; *** patched address - - - - ;***************************************************************** - ; - ; Data_in_phase - ; 875 sets ATN if bad parity detected. - ; Use of CHMOV instructions assures that we properly handle - ; a leftover wide byte in the SWIDE or SODL register, depending - ; on the data direction. This can happen in either of two conditions: - ; 1. The Target disconnects at an odd boundary. This is - ; extremely unlikely with disk devices. - ; 2. The client passes either an odd buffer address or - ; an odd transfer count. When the Target disconnects (at - ; an even boundary, we end up with the extra wide - ; byte in SWIDE or SODL. MacOS does this with VM on. - ; - ;***************************************************************** - -data_in_phase: - move kphase_DATA_IN to SCRATCHB0 ; Set phase indicator - store SCRATCHB0, 1, ld_phase_flag - - call rel( driverXfer ) ; call driver-built CHMOV instructions - - ; The driver gets interrupted if a phase mismatch occurs as when - ; the Target goes MSG-IN with a Disconnect. - ; The driver codes either a RETURN if the Scatter/Gather list is complete or - ; an INT if more Scatter/Gather elements need to be generated. - ; On the Macintosh, client programs expect extra incoming data to be dumped. - ; For example, during boot the ROM reads 512 bytes from a 2K-byte-sector CD. - -bucket_loop: - jump rel( phase_handler ), when not DATA_IN ; wait for phase, exit if changed - CHMOV 1, ld_status, when DATA_IN ; eat a byte - jump rel( bucket_loop ); ; keep dumping bytes - - - ;***************************************************************** - ; - ; Status phase - ; - ;***************************************************************** - -status_phase: - move kphase_STATUS to SCRATCHB0 ; Set phase indicator - store SCRATCHB0, 1, ld_phase_flag - - move 1, ld_status, when STATUS ; Read Status byte from bus - jump rel( phase_handler ) - - - ;***************************************************************** - ; - ; Message-In phase - ; - ;***************************************************************** - -message_in_phase: - move kphase_MSG_IN to SCRATCHB0 ; Set phase indicator - store SCRATCHB0, 1, ld_phase_flag - - move 1, ld_message, when MSG_IN ; Read byte from bus - - jump rel( cmdComplete ), if 0x00 ; Command Complete - jump rel( saveDataPointer ), if 0x02 ; Save Data Pointer - jump rel( disconnect_msg ), if 0x04 ; Disconnect - jump rel( ignoreWideResidue ), if 0x23 ; Ignore Wide Residue - jump rel( restoreDataPointer ), if 0x03 ; Restore Data Pointer - jump rel( extended_msg ), if 0x01 ; Extended message - jump rel( msg_reject ), if 0x07 ; Message Reject - ; Identify, if 0x80-FF ; Identify + LUN - ; simple_queue_tag, if 0x20 ; Simple Queue Tag - ; initiate_recovery, if 0x0F ; Initiate Recovery - ; linked_cde_complete, if 0x0A/0x0B - int unexpected_msg ; unknown - -msg_reject: - int unknown_msg_reject - -clearACK: ; ENTRY point to end negotiation - clear ACK - jump rel( phase_handler ) - - - - ;***************************************************************** - ; - ; Ignore Wide Residue - ; - ;***************************************************************** - -ignoreWideResidue: ; this is a two byte message so snag the 2nd byte here - clear ACK - move 1, ld_message+1, when MSG_IN ; save residue count - move SFBR to SCRATCHB2 ; byte is still in SFBR. Position it. - store SCRATCHB2, 1, DSAREL( TLQ_IWR ) ; Store residue count in Nexus for driver. - clear ACK - jump rel( phase_handler ) - - - ;***************************************************************** - ; - ; Extended message - ; Accept Wide and Synchronous Data Transfer messages - ; - ;***************************************************************** - -extended_msg: - clear ACK - move 1, ld_message+1, when MSG_IN ; read msg length byte from bus - clear ACK - move 1, ld_message+2, when MSG_IN ; read ext msg code from bus - clear ACK - ; extended_identify, IF 0x02 - ; modify_data_pointer, if 0x00 - jump rel( sdtr ), if 0x01 ; jump if SDTR, sync negotiation msg - jump rel( wdtr ), if 0x03 ; jump if WDTR, wide negotiation msg - int unexpected_ext_msg ; let driver deal with unknown - - - ;***************************************************************** - ; - ; Command complete - ; The Command-Complete message is sent to indicate that the - ; IO operation has completed and valid status has been sent. - ; The Target should then disconnect. - ; SCRIPTS must spin until the IOdone mailbox is empty. - ; Then it sets the IOdone mailbox with the current Nexus. - ; The status message is analyzed. - ; If status is good, INTF the driver and jump to select_phase. - ; If status is NG, save it in the NEXUS and INT the driver. - ; - ;***************************************************************** - -cmdComplete: - move kphase_CMD_COMPLETE to SCRATCHB0 ; Set phase indicator - store SCRATCHB0, 1, ld_phase_flag - - move SCNTL2 & 0X7F to SCNTL2 ; Clr SDU: SCSI Disconnect Unexpected - clear ACK - WAIT DISCONNECT - -testMbxLp: ; loop until IOdone mailbox empty - load SCRATCHA0, 4, ld_IOdone_mailbox - move SCRATCHA3 to SFBR ; A3 = semaphore - jump rel( testMbxLp ), if not 0 - - ; Fill in the IOdone mailbox with the following: - ; A0 = index to Nexus - ; A1 = Status - ; A2 = 0 - ; A3 = semaphore (FF = set) - load SCRATCHA0, 1, ld_nexus_index ; A0 = index to Nexus - load SCRATCHB0, 1, ld_status - move SCRATCHB0 to SFBR - move SFBR to SCRATCHA1 ; A1 = Status - move 0x00 to SCRATCHA2 ; A2 = 0 - move 0xFF to SCRATCHA3 ; A3 = semaphore IOdone mailbox - store SCRATCHA0, 4, ld_IOdone_mailbox - - move SCRATCHA1 to SFBR ; Test the Status of this IO - ; SFBR = status msg - ; Test status - If good, Interrupt on the fly and jump to select phase - intfly 0xFF, if 0 and mask 0xC1 ; mask off reserved bits - jump rel( select_phase ), if 0 and mask 0xC1 - int status_error ; Status err. Interrupt driver & stop - - - ;***************************************************************** - ; - ; Disconnect - ; The 8xx Accepts the disconnection and jumps to the select_phase - ; to check for another IO - ; - ;***************************************************************** - -disconnect_msg: - load SCRATCHB0, 1, ld_phase_flag - move SCRATCHB0 to SFBR - ; If we got here from reselect just bailout since ld_nexus is - ; not setup and the code using it is not needed anyway (no data xfer) - jump rel( bailout ), if kphase_RESELECT - - move kphase_DISCONNECT to SCRATCHB0 - store SCRATCHB0, 1, ld_phase_flag - -bailout: - move 0xFF to SCRATCHB3 ; invalidate nexus index for driver - store SCRATCHB3, 1, ld_nexus_index+3 - move SCNTL2 & 0x7F to SCNTL2 ; Clr SDU: SCSI Disconnect Unexpected - clear ACK - WAIT DISCONNECT ; wait for bus-free - jump rel( select_phase ) ; go see if more to do - - - ;****************************************************************** - ; - ; ??? mlj - saveDataPointer and restoreDataPointer are incorrect. - ; ??? They basically do nothing. - ; Save Data Pointer - ; - ;***************************************************************** - -saveDataPointer: - move kphase_saveDataPointer to SCRATCHB0 - store SCRATCHB0, 1, ld_phase_flag - clear ACK - jump rel( phase_handler ) - - - ;****************************************************************** - ; - ; ??? mlj - saveDataPointer and restoreDataPointer are incorrect. - ; ??? They basically do nothing. - ; Restore Data Pointer - ; The local values still blocks, still bytes and data address - ; must be loaded from the corresponding NEXUS data set. - ; This message should followed an IDE (parity error) - ; - ;***************************************************************** - -restoreDataPointer: - move kphase_restoreDataPointer to SCRATCHB0 - store SCRATCHB0, 1, ld_phase_flag - clear ACK - jump rel( phase_handler ) - - - ;***************************************************************** - ; - ; Synchronous data transfer request or response - ; - ;***************************************************************** -sdtr: - move 2, ld_message+3, when MSG_IN ; Read period & offset from bus - int negotiateSDTR - - - ;*************************************************************************** - ; - ; Wide Data Transfer request or response - ; - ;*************************************************************************** -wdtr: - move 1, ld_message+3, when MSG_IN ; get Transfer Width Exponent fm bus - int negotiateWDTR - - - ;***************************************************************** - ; - ; Reselect phase - ; The chip waits here either for a Reselection from a Target or - ; a SIGP from the driver indicating something in the mailbox. - ; If reselected, the script uses the Nexus value which is either - ; a Tag or a SCSI ID/LUN combo to lookup the Nexus. - ; Then init the SXFER and SCNTL3 registers from the device config table. - ; - ;***************************************************************** - -try_reselect: ; Select failed - probably reselecting - ; Cf NCR Errata Listing 117 Item 1: - move SCNTL0 & 0xDF to SCNTL0 ; clr Start bit - move CTEST2 | 0x00 to CTEST2 ; Clear SIGP bit from ISTAT reg - -reselect_phase: - move kphase_RESELECT to SCRATCHB0 ; Set phase indicator - store SCRATCHB0, 1, ld_phase_flag - - move 0xFF to SCRATCHB3 ; invalidate nexus index for driver - store SCRATCHB3, 1, ld_nexus_index+3 - - ; wait here for reselect from a Target - ; or SIGP from the driver - - WAIT RESELECT REL( select_phase ) ; jump if SIGP - - ; Reselected: - - move SSID to SFBR ; SSID = [ Valxxx Scsi_id ] - int unknown_reselect, if 0 and mask 0x7F; Interrupt if VAL bit not set - move SFBR & 0x0F to SCRATCHB0 ; B0 = Target ID - store SCRATCHB0, 1, ld_scsi_id ; save it - - call rel( initContext ) ; setup sync regs here - - int no_msgin_after_reselect, when not MSG_IN - - move 1, ld_message, when MSG_IN ; Read Identify byte from bus - - ; if another REQ is asserted, a SimpleQueueTag message should be next - - clear ACK ; notify Target: msg byte rx'd - jump rel( getNextMsg ), when MSG_IN ; jump if SimpleQueueTag coming - - ; untagged operation: - - move SFBR & 0x07 to SCRATCHA0 ; isolate LUN from Identify byte - - load SCRATCHB0, 1, ld_scsi_id ; B0 = Target ID - clear CARRY - move SCRATCHB0 SHL SFBR ; shift left #1 - move SFBR SHL SCRATCHB0 ; shift left #2 - move SCRATCHB0 SHL SFBR ; shift left #3 - move SCRATCHA0 | SFBR to SCRATCHA0 ; form Nexus index = 0b0TTTTLLL - - store SCRATCHA0, 1, ld_nexus_index ; store as index to Nexus - jump rel( haveNexusIndex ) - - ; should be tagged operation: - -getNextMsg: - move 1, ld_message, when MSG_IN ; read message byte from bus - jump rel( disconnect_msg ), if 0x04 ; if Disconnect, oh well. - clear ACK - jump rel( phase_handler ), if not 0x20; Branch if not Queue tag code - ; get the Queue Tag and save as the nexus index - move 1, ld_nexus_index, when MSG_IN ; Nexus index <- Tag from bus - clear ACK ; acknowledge it - -haveNexusIndex: - move 0x00 to SCRATCHB3 ; clear invalid-nexus-index flag - store SCRATCHB3, 1, ld_nexus_index+3 - call rel( findNexusFromIndex ) ; set DSA <- Nexus pointer - jump rel( phase_handler ) ; start handling phases. - - - ;***************************************************************** - ; - ; AbortMailbox - Abort (or BusDeviceReset) the mailbox entry. - ; This is a queued operation - not an immediate - ; operation as is issueAbort_BDR. - ; The Abort message clears all IO processes for the - ; selecting Initiator on the specified LUN. - ; - ; The Bus Device Reset message clears all IO processes for - ; all Initiators on all LUNs of selected Target. - ; It forces a hard reset condition to the selected SCSI device. - ; - ; A0 = Identify byte (0xC0 + LUN N.B. Disconnect allowed) - ; A1 = Tag, if any - ; A2 = SCSI ID - ; A3 = Abort code Abort=0x06; Abort Tag=0D; Bus Device Reset=0x0C - ; - ; Mailbox not cleared by SCRIPTS so that driver can find SCSI ID when done - ; N.B.: Device is Async and Narrow after BDR!!! - ; Driver must set the device config table values accordingly. - ;***************************************************************** - -AbortMailbox: - move kphase_ABORT_MAILBOX to SCRATCHB0 ; Set phase code - store SCRATCHB0, 1, ld_phase_flag - - move 0xFF to SCRATCHB3 ; invalidate nexus index for driver - store SCRATCHB3, 1, ld_nexus_index+3 - - load SCRATCHB2, 1, ld_AbortBdr_mailbox+2 ; get SCSI ID - store SCRATCHB2, 1, AbortSelect+2 ; *** Patch the Select/ATN instruction - -AbortSelect: - SELECT ATN 0, REL( try_reselect ) ; *** Patched SCSI ID - - move SCRATCHA1 to SFBR ; check for Tag - jump rel( taggedAbort ) if not 0x00 ; jump if tagged abort - - ; untagged Abort or BusDeviceReset: - - move SCRATCHA3 to SFBR ; position the abort code - move SFBR to SCRATCHA1 - store SCRATCHA0, 2, ld_scratch ; Store Identify and Abort msgs - move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected - move 2, ld_scratch , when MSG_OUT ; emit Identify and Abort messages - WAIT DISCONNECT - int abort_mailbox - - ; AbortTag: - -taggedAbort: - move SCRATCHA1 to SFBR ; position the Tag - move SFBR to SCRATCHA2 - move 0x20 to SCRATCHA1 ; gen SimpleQueueTag code - store SCRATCHA0, 4, ld_scratch ; store Identify, SQT, Tag, AbortTag - move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected - move 4, ld_scratch, when MSG_OUT ; emit all 4 bytes - WAIT DISCONNECT - int abort_mailbox - - - ;***************************************************************** - ; - ; issueAbort_BDR - Abort (or BusDeviceReset) the current operation. - ; This is an immediate operation - not a queued operation - ; as is AbortMailbox. - ; The Abort message clears all IO processes for the - ; selecting Initiator on the specified LUN. - ; - ; The Bus Device Reset message clears all IO processes for - ; all Initiators on all LUNs of selected Target. - ; It forces a hard reset condition to the selected SCSI device. - ; - ;***************************************************************** - -issueAbort_BDR: - move kphase_ABORT_CURRENT to SCRATCHB0 ; Set phase code - store SCRATCHB0, 1, ld_phase_flag - - move ISTAT & 0x08 to SFBR ; see if Target connected to bus - int abort_current, if 0 ; interrupt driver if not connected - - SET ATN ; get Target's attention - load DSA0, 4, ld_nexus ; load pointer to Nexus - -bucketLoop: - clear ACK - jump rel( sendAbortBDR ), when MSG_OUT ; wait for REQ. Jump if OK. - - jump rel( BucketInStatus ), if STATUS ; bit bucket in - jump rel( BucketInMsg ), if MSG_IN ; bit bucket in - jump rel( BucketInData ), if DATA_IN ; bit bucket in - - move 0xAD to SCRATCHA0 - jump rel( BucketOutData ), if DATA_OUT ; bit bucket out - jump rel( BucketOutCmd ), if CMD ; bit bucket out - int unknown_phase ; back to driver for harsher measures - - -BucketInStatus: - move 1, ld_scratch, when STATUS ; eat the Status byte - jump rel( bucketLoop ); ; keep bit-bucketing bytes - -BucketInMsg: - move 1, ld_scratch, when MSG_IN ; eat a message byte - jump rel( bucketLoop ); ; keep bit-bucketing bytes - -BucketInData: - move 1, ld_scratch, when DATA_IN ; eat a data byte - jump rel( bucketLoop ); ; keep bit-bucketing bytes - -BucketOutData: - move SCRATCHA0 xor 0x73 to SCRATCHA0 ; gen 0xDEAD ... - store SCRATCHA0, 1, ld_scratch - move 1, ld_scratch, when DATA_OUT ; pad a byte out - jump rel( bucketLoop ); ; keep bit-bucketing bytes - -BucketOutCmd: - move 0x00 to SCRATCHA0 ; load Null, TestUnitReady, whatever - store SCRATCHA0, 1, ld_scratch - move 1, ld_scratch, when CMD ; pad a byte out - jump rel( bucketLoop ); ; keep bit-bucketing bytes - - -sendAbortBDR: - move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected - move 1, ld_AbortCode, when MSG_OUT ; Send Abort(06) or BDR(0C) message - load SCRATCHA0, 4, ld_zeroes ; load 0's - store SCRATCHA0, 4, ld_AbortCode ; clear the Abort code - WAIT DISCONNECT - int abort_current ; went BusFree - tell Driver diff --git a/iokit/Drivers/scsi/drvSymbios8xx/nasmpb b/iokit/Drivers/scsi/drvSymbios8xx/nasmpb deleted file mode 100755 index 3398f9a8507d7ef5d1837a1273fb7c76d37b644f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 344008 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

EOC&RX&)V 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

4CoScoDWH29DL-1Bml)j7>hy^zXm+ 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 zsGa_50gz3ntargetParmsCurrent; - if ( tpCur->transferWidth != 1 ) + if ( tpCur->transferWidth > 1 ) { reqSenseCmd->scsiCmd.cdbFlags |= kCDBFlagsNegotiateWDTR; if (tpCur->transferOptions & kSCSITransferOptionPPR) { diff --git a/iokit/Kernel/IOInterruptController.cpp b/iokit/Kernel/IOInterruptController.cpp index 3b7d49b5a..bd3baa04d 100644 --- a/iokit/Kernel/IOInterruptController.cpp +++ b/iokit/Kernel/IOInterruptController.cpp @@ -556,23 +556,26 @@ IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub, long vectorNumber; IOInterruptVector *vector; OSData *vectorData; - IOInterruptState interruptState;; + IOInterruptState interruptState; interruptSources = nub->_interruptSources; vectorData = interruptSources[source].vectorData; vectorNumber = *(long *)vectorData->getBytesNoCopy(); vector = &vectors[vectorNumber]; - if (vector->interruptDisabledSoft) { - interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); - vector->interruptDisabledSoft = 0; - vectorsEnabled++; + interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); + if (!vector->interruptDisabledSoft) { IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); - - if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) { - controllerDisabled = 0; - provider->enableInterrupt(0); - } + return kIOReturnSuccess; + } + + vector->interruptDisabledSoft = 0; + vectorsEnabled++; + IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); + + if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) { + controllerDisabled = 0; + provider->enableInterrupt(0); } return kIOReturnSuccess; @@ -585,23 +588,23 @@ IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub, long vectorNumber; IOInterruptVector *vector; OSData *vectorData; - IOInterruptState interruptState;; + IOInterruptState interruptState; interruptSources = nub->_interruptSources; vectorData = interruptSources[source].vectorData; vectorNumber = *(long *)vectorData->getBytesNoCopy(); vector = &vectors[vectorNumber]; + interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); if (!vector->interruptDisabledSoft) { - interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); vector->interruptDisabledSoft = 1; #if __ppc__ sync(); isync(); #endif vectorsEnabled--; - IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); } + IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); if (!getPlatform()->atInterruptLevel()) { while (vector->interruptActive); diff --git a/iokit/KernelConfigTables.cpp b/iokit/KernelConfigTables.cpp index 33c8a75b9..2d74ff7f9 100644 --- a/iokit/KernelConfigTables.cpp +++ b/iokit/KernelConfigTables.cpp @@ -28,11 +28,11 @@ */ const char * gIOKernelKmods = "{ - 'com.apple.kernel' = '5.3'; - 'com.apple.kernel.bsd' = '5.3'; - 'com.apple.kernel.iokit' = '5.3'; - 'com.apple.kernel.libkern' = '5.3'; - 'com.apple.kernel.mach' = '5.3'; + 'com.apple.kernel' = '5.4'; + 'com.apple.kernel.bsd' = '5.4'; + 'com.apple.kernel.iokit' = '5.4'; + 'com.apple.kernel.libkern' = '5.4'; + 'com.apple.kernel.mach' = '5.4'; 'com.apple.iokit.IOADBFamily' = '1.1'; 'com.apple.iokit.IOSystemManagementFamily' = '1.1'; }"; diff --git a/iokit/conf/files.ppc b/iokit/conf/files.ppc index a129bfc6d..2321ea052 100644 --- a/iokit/conf/files.ppc +++ b/iokit/conf/files.ppc @@ -49,11 +49,6 @@ iokit/Drivers/platform/drvApplePowerExpressPE/PowerExpress.cpp optional iokitcpp iokit/Drivers/platform/drvAppleGrandCentral/GrandCentral.cpp optional disabled-iokitcpp iokit/Drivers/platform/drvAppleOHare/OHare.cpp optional iokitcpp -# Symbios 8xx SCSI Driver -#iokit/Drivers/scsi/drvSymbios8xx/Sym8xxClient.cpp optional iokitcpp -#iokit/Drivers/scsi/drvSymbios8xx/Sym8xxExecute.cpp optional iokitcpp -#iokit/Drivers/scsi/drvSymbios8xx/Sym8xxInit.cpp optional iokitcpp -#iokit/Drivers/scsi/drvSymbios8xx/Sym8xxMisc.cpp optional iokitcpp # ATA driver #iokit/Drivers/ata/drvAppleUltra66ATA/AppleUltra66ATA.cpp optional iokitcpp diff --git a/iokit/conf/version.minor b/iokit/conf/version.minor index 00750edc0..b8626c4cf 100644 --- a/iokit/conf/version.minor +++ b/iokit/conf/version.minor @@ -1 +1 @@ -3 +4 diff --git a/libkern/conf/version.minor b/libkern/conf/version.minor index 00750edc0..b8626c4cf 100644 --- a/libkern/conf/version.minor +++ b/libkern/conf/version.minor @@ -1 +1 @@ -3 +4 diff --git a/libsa/conf/version.minor b/libsa/conf/version.minor index 00750edc0..b8626c4cf 100644 --- a/libsa/conf/version.minor +++ b/libsa/conf/version.minor @@ -1 +1 @@ -3 +4 diff --git a/osfmk/conf/kernelversion.minor b/osfmk/conf/kernelversion.minor index 00750edc0..b8626c4cf 100644 --- a/osfmk/conf/kernelversion.minor +++ b/osfmk/conf/kernelversion.minor @@ -1 +1 @@ -3 +4 diff --git a/osfmk/conf/version.minor b/osfmk/conf/version.minor index 00750edc0..b8626c4cf 100644 --- a/osfmk/conf/version.minor +++ b/osfmk/conf/version.minor @@ -1 +1 @@ -3 +4 diff --git a/pexpert/conf/version.minor b/pexpert/conf/version.minor index 00750edc0..b8626c4cf 100644 --- a/pexpert/conf/version.minor +++ b/pexpert/conf/version.minor @@ -1 +1 @@ -3 +4 -- 2.45.2