#include "SRuntime.h"
#if BSD
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <IOKit/storage/IOMediaBSDClient.h>
#else
#include <Files.h>
#include <Device.h>
#include <Disks.h>
#endif
OSErr GetDeviceSize(int driveRefNum, UInt64 *numBlocks, UInt32 *blockSize)
{
#if BSD
UInt64 devBlockCount = 0;
int devBlockSize = 0;
if (ioctl(driveRefNum, DKIOCGETBLOCKCOUNT, &devBlockCount) < 0) {
printf("ioctl(DKIOCGETBLOCKCOUNT) for fd %d: %s\n", driveRefNum, strerror(errno));
return (-1);
}
if (ioctl(driveRefNum, DKIOCGETBLOCKSIZE, &devBlockSize) < 0) {
printf("ioctl(DKIOCGETBLOCKSIZE) for fd %d: %s\n", driveRefNum, strerror(errno));
return (-1);
}
if (devBlockSize != 512) {
*numBlocks = (devBlockCount * (UInt64)devBlockSize) / 512;
*blockSize = 512;
} else {
*numBlocks = devBlockCount;
*blockSize = devBlockSize;
}
return (0);
#else
enum
{
kFmtLstCode = 6,
kSonyRefNum = 0xfffb,
kSingleSided = 0,
kDoubleSided = -1,
kSingleSidedSize = 800,
kDoubleSidedSize = 1600,
kWordDrvSiz = 0,
kLongDrvSiz = 1,
kMaxFormatListRecs = 16
};
ParamBlockRec pb;
FormatListRec formatListRecords[kMaxFormatListRecs];
DrvSts status;
short formatListRecIndex;
OSErr result;
unsigned long blocks = 0;
pb.cntrlParam.ioVRefNum = driveQElementPtr->dQDrive;
pb.cntrlParam.ioCRefNum = driveQElementPtr->dQRefNum;
pb.cntrlParam.csCode = kFmtLstCode;
pb.cntrlParam.csParam[0] = kMaxFormatListRecs;
*(long *)&pb.cntrlParam.csParam[1] = (long)&formatListRecords[0];
result = PBStatusSync(&pb);
if ( result == noErr )
{
for( formatListRecIndex = 0;
formatListRecIndex < pb.cntrlParam.csParam[0];
++formatListRecIndex )
{
if ( (formatListRecords[formatListRecIndex].formatFlags &
diCIFmtFlagsCurrentMask) != 0 )
{
blocks = formatListRecords[formatListRecIndex].volSize;
}
}
if ( blocks == 0 )
{
result = paramErr;
}
}
else if ( driveQElementPtr->dQRefNum == (short)kSonyRefNum )
{
result = DriveStatus(driveQElementPtr->dQDrive, &status);
if ( result == noErr )
{
switch ( status.twoSideFmt )
{
case kSingleSided:
blocks = kSingleSidedSize;
break;
case kDoubleSided:
blocks = kDoubleSidedSize;
break;
default: result = paramErr;
break;
}
}
}
else
{
result = noErr;
switch ( driveQElementPtr->qType )
{
case kWordDrvSiz:
blocks = driveQElementPtr->dQDrvSz;
break;
case kLongDrvSiz:
blocks = ((unsigned long)driveQElementPtr->dQDrvSz2 << 16) +
driveQElementPtr->dQDrvSz;
break;
default: result = paramErr;
break;
}
}
*numBlocks = blocks;
*blockSize = 512;
return( result );
#endif
}
OSErr DeviceRead(int device, int drive, void* buffer, SInt64 offset, UInt32 reqBytes, UInt32 *actBytes)
{
#if BSD
off_t seek_off;
ssize_t nbytes;
*actBytes = 0;
seek_off = lseek(device, offset, SEEK_SET);
if (seek_off == -1) {
printf("# DeviceRead: lseek(%qd) failed with %d\n", offset, errno);
return (errno);
}
nbytes = read(device, buffer, reqBytes);
if (nbytes == -1)
return (errno);
if (nbytes == 0) {
printf("CANNOT READ: BLK %ld\n", (long)offset/512);
return (5);
}
*actBytes = nbytes;
return (0);
#else
OSErr err;
XIOParam pb;
pb.ioVRefNum = drive;
pb.ioRefNum = device;
pb.ioPosMode = fsFromStart;
pb.ioReqCount = reqBytes;
pb.ioBuffer = buffer;
if ( (offset & 0xFFFFFFFF00000000) != 0 )
{
*(SInt64*)&pb.ioWPosOffset = offset;
pb.ioPosMode |= (1 << kWidePosOffsetBit);
}
else
{
((IOParam*)&pb)->ioPosOffset = offset;
}
err = PBReadSync( (ParamBlockRec *)&pb );
return (err);
#endif
}
OSErr DeviceWrite(int device, int drive, void* buffer, SInt64 offset, UInt32 reqBytes, UInt32 *actBytes)
{
#if BSD
off_t seek_off;
ssize_t nbytes;
*actBytes = 0;
seek_off = lseek(device, offset, SEEK_SET);
if (seek_off == -1) {
printf("# DeviceRead: lseek(%qd) failed with %d\n", offset, errno);
return (errno);
}
nbytes = write(device, buffer, reqBytes);
if (nbytes == -1) {
return (errno);
}
if (nbytes == 0) {
printf("CANNOT WRITE: BLK %ld\n", (long)offset/512);
return (5);
}
*actBytes = nbytes;
return (0);
#else
OSErr err;
XIOParam pb;
pb.ioVRefNum = drive;
pb.ioRefNum = device;
pb.ioPosMode = fsFromStart;
pb.ioReqCount = reqBytes;
pb.ioBuffer = buffer;
if ( (offset & 0xFFFFFFFF00000000) != 0 )
{
*(SInt64*)&pb.ioWPosOffset = offset;
pb.ioPosMode |= (1 << kWidePosOffsetBit);
}
else
{
((IOParam*)&pb)->ioPosOffset = offset;
}
err = PBWriteSync( (ParamBlockRec *)&pb );
return (err);
#endif
}