2 * Copyright (c) 1999-2000, 2002, 2005, 2007-2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include "../fsck_hfs.h"
30 #include <sys/ioctl.h>
32 #include <IOKit/storage/IOMediaBSDClient.h>
43 OSErr
GetDeviceSize(int driveRefNum
, UInt64
*numBlocks
, UInt32
*blockSize
)
46 UInt64 devBlockCount
= 0;
49 if (ioctl(driveRefNum
, DKIOCGETBLOCKCOUNT
, &devBlockCount
) < 0) {
50 if (debug
) plog("ioctl(DKIOCGETBLOCKCOUNT) for fd %d: %s\n", driveRefNum
, strerror(errno
));
54 if (ioctl(driveRefNum
, DKIOCGETBLOCKSIZE
, &devBlockSize
) < 0) {
55 if (debug
) plog("ioctl(DKIOCGETBLOCKSIZE) for fd %d: %s\n", driveRefNum
, strerror(errno
));
59 if (devBlockSize
!= 512) {
60 *numBlocks
= (devBlockCount
* (UInt64
)devBlockSize
) / 512;
63 *numBlocks
= devBlockCount
;
64 *blockSize
= devBlockSize
;
68 /* Various Mac OS device constants */
71 /* return format list status code */
74 /* reference number of .SONY driver */
77 /* values returned by DriveStatus in DrvSts.twoSideFmt */
80 kSingleSidedSize
= 800, /* 400K */
81 kDoubleSidedSize
= 1600, /* 800K */
83 /* values in DrvQEl.qType */
87 /* more than enough formatListRecords */
88 kMaxFormatListRecs
= 16
92 FormatListRec formatListRecords
[kMaxFormatListRecs
];
94 short formatListRecIndex
;
96 unsigned long blocks
= 0;
99 /* Attempt to get the drive's format list. */
100 /* (see the Technical Note "What Your Sony Drives For You") */
102 pb
.cntrlParam
.ioVRefNum
= driveQElementPtr
->dQDrive
;
103 pb
.cntrlParam
.ioCRefNum
= driveQElementPtr
->dQRefNum
;
104 pb
.cntrlParam
.csCode
= kFmtLstCode
;
105 pb
.cntrlParam
.csParam
[0] = kMaxFormatListRecs
;
106 *(long *)&pb
.cntrlParam
.csParam
[1] = (long)&formatListRecords
[0];
108 result
= PBStatusSync(&pb
);
110 if ( result
== noErr
)
112 /* The drive supports ReturnFormatList status call. */
114 /* Get the current disk's size. */
115 for( formatListRecIndex
= 0;
116 formatListRecIndex
< pb
.cntrlParam
.csParam
[0];
117 ++formatListRecIndex
)
119 if ( (formatListRecords
[formatListRecIndex
].formatFlags
&
120 diCIFmtFlagsCurrentMask
) != 0 )
122 blocks
= formatListRecords
[formatListRecIndex
].volSize
;
127 /* This should never happen */
131 else if ( driveQElementPtr
->dQRefNum
== (short)kSonyRefNum
)
133 /* The drive is a non-SuperDrive floppy which only supports 400K and 800K disks */
135 result
= DriveStatus(driveQElementPtr
->dQDrive
, &status
);
136 if ( result
== noErr
)
138 switch ( status
.twoSideFmt
)
141 blocks
= kSingleSidedSize
;
145 blocks
= kDoubleSidedSize
;
148 default: // This should never happen
156 /* The drive is not a floppy and it doesn't support ReturnFormatList */
157 /* so use the dQDrvSz field(s) */
159 result
= noErr
; /* reset result */
161 switch ( driveQElementPtr
->qType
)
164 blocks
= driveQElementPtr
->dQDrvSz
;
168 blocks
= ((unsigned long)driveQElementPtr
->dQDrvSz2
<< 16) +
169 driveQElementPtr
->dQDrvSz
;
172 default: // This should never happen
186 OSErr
DeviceRead(int device
, int drive
, void* buffer
, SInt64 offset
, UInt32 reqBytes
, UInt32
*actBytes
)
194 seek_off
= lseek(device
, offset
, SEEK_SET
);
195 if (seek_off
== -1) {
196 if (debug
) plog("# DeviceRead: lseek(%qd) failed with %d\n", offset
, errno
);
200 nbytes
= read(device
, buffer
, reqBytes
);
204 if (debug
) plog("CANNOT READ: BLK %ld\n", (long)offset
/512);
208 *actBytes
= (UInt32
)nbytes
;
215 pb
.ioVRefNum
= drive
;
216 pb
.ioRefNum
= device
;
217 pb
.ioPosMode
= fsFromStart
;
218 pb
.ioReqCount
= reqBytes
;
219 pb
.ioBuffer
= buffer
;
221 if ( (offset
& 0xFFFFFFFF00000000) != 0 )
223 *(SInt64
*)&pb
.ioWPosOffset
= offset
;
224 pb
.ioPosMode
|= (1 << kWidePosOffsetBit
);
228 ((IOParam
*)&pb
)->ioPosOffset
= offset
;
231 err
= PBReadSync( (ParamBlockRec
*)&pb
);
238 OSErr
DeviceWrite(int device
, int drive
, void* buffer
, SInt64 offset
, UInt32 reqBytes
, UInt32
*actBytes
)
246 seek_off
= lseek(device
, offset
, SEEK_SET
);
247 if (seek_off
== -1) {
248 if (debug
) plog("# DeviceRead: lseek(%qd) failed with %d\n", offset
, errno
);
252 nbytes
= write(device
, buffer
, reqBytes
);
257 if (debug
) plog("CANNOT WRITE: BLK %ld\n", (long)offset
/512);
261 *actBytes
= (UInt32
)nbytes
;
267 pb
.ioVRefNum
= drive
;
268 pb
.ioRefNum
= device
;
269 pb
.ioPosMode
= fsFromStart
;
270 pb
.ioReqCount
= reqBytes
;
271 pb
.ioBuffer
= buffer
;
273 if ( (offset
& 0xFFFFFFFF00000000) != 0 )
275 *(SInt64
*)&pb
.ioWPosOffset
= offset
;
276 pb
.ioPosMode
|= (1 << kWidePosOffsetBit
);
280 ((IOParam
*)&pb
)->ioPosOffset
= offset
;
283 err
= PBWriteSync( (ParamBlockRec
*)&pb
);