/* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights * Reserved. This file contains Original Code and/or Modifications of * Original Code as defined in and that are subject to the Apple Public * Source License Version 1.0 (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. * * The 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@ */ #include "SRuntime.h" #if BSD #include #include #include #include #else #include #include #include #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 /* Various Mac OS device constants */ enum { /* return format list status code */ kFmtLstCode = 6, /* reference number of .SONY driver */ kSonyRefNum = 0xfffb, /* values returned by DriveStatus in DrvSts.twoSideFmt */ kSingleSided = 0, kDoubleSided = -1, kSingleSidedSize = 800, /* 400K */ kDoubleSidedSize = 1600, /* 800K */ /* values in DrvQEl.qType */ kWordDrvSiz = 0, kLongDrvSiz = 1, /* more than enough formatListRecords */ kMaxFormatListRecs = 16 }; ParamBlockRec pb; FormatListRec formatListRecords[kMaxFormatListRecs]; DrvSts status; short formatListRecIndex; OSErr result; unsigned long blocks = 0; /* Attempt to get the drive's format list. */ /* (see the Technical Note "What Your Sony Drives For You") */ 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 ) { /* The drive supports ReturnFormatList status call. */ /* Get the current disk's size. */ for( formatListRecIndex = 0; formatListRecIndex < pb.cntrlParam.csParam[0]; ++formatListRecIndex ) { if ( (formatListRecords[formatListRecIndex].formatFlags & diCIFmtFlagsCurrentMask) != 0 ) { blocks = formatListRecords[formatListRecIndex].volSize; } } if ( blocks == 0 ) { /* This should never happen */ result = paramErr; } } else if ( driveQElementPtr->dQRefNum == (short)kSonyRefNum ) { /* The drive is a non-SuperDrive floppy which only supports 400K and 800K disks */ result = DriveStatus(driveQElementPtr->dQDrive, &status); if ( result == noErr ) { switch ( status.twoSideFmt ) { case kSingleSided: blocks = kSingleSidedSize; break; case kDoubleSided: blocks = kDoubleSidedSize; break; default: // This should never happen result = paramErr; break; } } } else { /* The drive is not a floppy and it doesn't support ReturnFormatList */ /* so use the dQDrvSz field(s) */ result = noErr; /* reset result */ switch ( driveQElementPtr->qType ) { case kWordDrvSiz: blocks = driveQElementPtr->dQDrvSz; break; case kLongDrvSiz: blocks = ((unsigned long)driveQElementPtr->dQDrvSz2 << 16) + driveQElementPtr->dQDrvSz; break; default: // This should never happen result = paramErr; break; } } *numBlocks = blocks; *blockSize = 512; return( result ); #endif } off_t io_bytes_read = 0; int io_count = 0; void printIOstats(void) { printf("IO Summary: %d I/O calls, for %qd bytes\n", io_count, io_bytes_read); } 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", (long)offset/512); return (5); } io_count++; io_bytes_read += nbytes; *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", (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 }