This was necessary for archiving TI Explorer discs,
which have 256 byte
blocks but are SCSI devices (MFM drive and ACB 4000 host adapter).
Interesting. What OS platform and HBA was this for?
--
TI Explorer Lisp Machines.
The Eve should be readable, I was thinking of the Lilith.
This is how I read 256 byte blocks under Mac OS9. Bad blocks are
filled with 0x0bad
/*
* DoReadDiscBlocks.c
*/
/*
*/
#include "SCSISimpleSample.h"
#include <stdio.h>
/*
* Read block zero from the indicated device..
*/
void
DoReadDiscBlocks(
DeviceIdent scsiDevice /* -> Bus/target/LUN */
)
{
char msg[256];
FILE *fp;
int badblkcnt;
int blklen;
unsigned long count, maxblocks;
unsigned char badBlockData[512];
ScsiCmdBlock scsiCmdBlock;
SCSI_Capacity_Data getCapacity;
unsigned long transferLength;
for(count = 0; count<512; count+=2){ /* init the bad data */
badBlockData[count] = 0xb;
badBlockData[count+1] = 0xad;
}
#define SCB (scsiCmdBlock)
ShowSCSIBusID(scsiDevice, "\pGet Capacity");
CLEAR(SCB);
SCB.scsiDevice = scsiDevice;
SCB.command.scsi6.opcode = kScsiCmdReadCapacity;
SCB.command.scsi6.len = 0;
SCB.bufferPtr = (Ptr) &getCapacity;
SCB.transferSize = sizeof getCapacity;
SCB.transferQuantum = 1; /* Force handshake */
/* All other command bytes are zero */
DoSCSICommandWithSense(&scsiCmdBlock, TRUE, TRUE);
blklen = getCapacity.len1;
blklen |= getCapacity.len2 <<8 ;
blklen |= getCapacity.len3 <<16;
blklen |= getCapacity.len4 <<24;
if(blklen != 256){
ShowSCSIBusID(scsiDevice, "\pBlock Len != 256!");
return;
}
maxblocks = getCapacity.lbn1;
count = getCapacity.lbn2;
maxblocks |= (count << 8);
count = getCapacity.lbn3;
maxblocks |= (count << 16);
count = getCapacity.lbn4;
maxblocks |= (count << 24);
maxblocks++;
/*
*
*/
sprintf(msg, "%lu blocks", maxblocks);
LOG(c2pstr(msg));
fp = fopen("discDump","wb");
ShowSCSIBusID(scsiDevice, "\pStarting Dump");
#define kLogicalBlockLength 256
#define kNumberOfBlocks 1
transferLength = 256; /* allways do a block at a time */
CLEAR(SCB);
SCB.scsiDevice = scsiDevice;
/*
* The 6-byte read command can read up to 128 blocks of data (1-127
* reads that number of blocks, while zero reads 128 blocks). For more
* flexibility, you should use the 10-byte Read command.
*/
SCB.command.scsi6.opcode = kScsiCmdRead6;
SCB.command.scsi6.len = transferLength / kLogicalBlockLength;
SCB.bufferPtr = NewPtrClear(transferLength);
if (SCB.bufferPtr == NULL){
LOG("\pNo Memory for ReadBlockZero data buffer");
return;
}
SCB.transferSize = transferLength;
SCB.transferQuantum = kLogicalBlockLength;
badblkcnt = 0;
for(count = 0; count < maxblocks; count++){
SCB.command.scsi6.lbn3 = (count >>16 ) & 0xff; /* set the blk # */
SCB.command.scsi6.lbn2 = (count >> 8 ) & 0xff;
SCB.command.scsi6.lbn1 = (count ) & 0xff;
DoSCSICommandWithSense(&scsiCmdBlock, TRUE, TRUE);
if (SCB.status == noErr){
fwrite(SCB.bufferPtr, 256, 1, fp); /* write the data */
}
else {
badblkcnt++;
fwrite(badBlockData, 256, 1, fp); /* write a bad block */
sprintf(msg, "blk %lx bad\n", count);
LOG(c2pstr(msg));
}
if((count % 256) == 0){
sprintf(msg, "blk %ld\n", count);
LOG(c2pstr(msg));
}
}
DisposePtr(SCB.bufferPtr);
fclose(fp);
#undef SCB
ShowSCSIBusID(scsiDevice, "\pDump Done");
sprintf(msg, "%d bad blocks\n", badblkcnt);
LOG(c2pstr(msg));
}