+ ref->device = device;
+
+ // generate the block list
+
+ error = do_ioctl(p1, p2, DKIOCLOCKPHYSICALEXTENTS, NULL);
+ if (error)
+ goto out;
+ locked = TRUE;
+
+ // get block size
+
+ error = do_ioctl(p1, p2, DKIOCGETBLOCKSIZE, (caddr_t) &blksize);
+ if (error)
+ goto out;
+
+ if (ref->vp->v_type == VREG)
+ filelength = va.va_data_size;
+ else
+ {
+ error = do_ioctl(p1, p2, DKIOCGETBLOCKCOUNT, (caddr_t) &fileblk);
+ if (error)
+ goto out;
+ filelength = fileblk * blksize;
+ }
+
+ f_offset = 0;
+ while (f_offset < filelength)
+ {
+ if (ref->vp->v_type == VREG)
+ {
+ filechunk = 1*1024*1024*1024;
+ daddr64_t blkno;
+
+ error = VNOP_BLOCKMAP(ref->vp, f_offset, filechunk, &blkno, &filechunk, NULL, 0, NULL);
+ if (error)
+ goto out;
+
+ fileblk = blkno * blksize;
+ }
+ else if ((ref->vp->v_type == VBLK) || (ref->vp->v_type == VCHR))
+ {
+ fileblk = f_offset;
+ filechunk = f_offset ? 0 : filelength;
+ }
+
+ physoffset = 0;
+ while (physoffset < filechunk)
+ {
+ dk_physical_extent_t getphysreq;
+ bzero(&getphysreq, sizeof(getphysreq));
+
+ getphysreq.offset = fileblk + physoffset;
+ getphysreq.length = (filechunk - physoffset);
+ error = do_ioctl(p1, p2, DKIOCGETPHYSICALEXTENT, (caddr_t) &getphysreq);
+ if (error)
+ goto out;
+ if (!target)
+ {
+ target = getphysreq.dev;
+ }
+ else if (target != getphysreq.dev)
+ {
+ error = ENOTSUP;
+ goto out;
+ }
+ callback(callback_ref, getphysreq.offset, getphysreq.length);
+ physoffset += getphysreq.length;
+ }
+ f_offset += filechunk;
+ }
+ callback(callback_ref, 0ULL, 0ULL);
+
+ if (ref->vp->v_type == VREG)
+ p1 = ⌖