ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/disk.cpp
(Generate patch)

Comparing BasiliskII/src/disk.cpp (file contents):
Revision 1.1.1.1 by cebix, 1999-10-03T14:16:25Z vs.
Revision 1.19 by gbeauche, 2008-01-01T09:40:31Z

# Line 1 | Line 1
1   /*
2   *  disk.cpp - Generic disk driver
3   *
4 < *  Basilisk II (C) 1997-1999 Christian Bauer
4 > *  Basilisk II (C) 1997-2008 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 26 | Line 26
26   *    Technote FL 24: "Don't Look at ioPosOffset for Devices"
27   */
28  
29 + #include "sysdeps.h"
30 +
31   #include <string.h>
32 + #include <vector>
33 +
34 + #ifndef NO_STD_NAMESPACE
35 + using std::vector;
36 + #endif
37  
31 #include "sysdeps.h"
38   #include "cpu_emulation.h"
39   #include "main.h"
40   #include "macos_util.h"
# Line 65 | Line 71 | const uint8 DiskIcon[258] = {
71  
72  
73   // Struct for each drive
74 < struct DriveInfo {
75 <        DriveInfo()
76 <        {
77 <                next = NULL;
78 <                num = 0;
73 <                fh = NULL;
74 <                read_only = false;
75 <                status = 0;
76 <        }
74 > struct disk_drive_info {
75 >        disk_drive_info() : num(0), fh(NULL), start_byte(0), read_only(false), status(0) {}
76 >        disk_drive_info(void *fh_, bool ro) : num(0), fh(fh_), read_only(ro), status(0) {}
77 >
78 >        void close_fh(void) { Sys_close(fh); }
79  
78        DriveInfo *next;        // Pointer to next DriveInfo (must be first in struct!)
80          int num;                        // Drive number
81          void *fh;                       // File handle
82 +        loff_t start_byte;      // Start of HFS partition on disk
83          uint32 num_blocks;      // Size in 512-byte blocks
84          bool to_be_mounted;     // Flag: drive must be mounted in accRun
85          bool read_only;         // Flag: force write protection
86          uint32 status;          // Mac address of drive status record
87   };
88  
89 < // Linked list of DriveInfos
90 < static DriveInfo *first_drive_info;
89 > // List of drives handled by this driver
90 > typedef vector<disk_drive_info> drive_vec;
91 > static drive_vec drives;
92  
93   // Icon address (Mac address space, set by PatchROM())
94   uint32 DiskIconAddr;
95  
96 + // Flag: Control(accRun) has been called, interrupt routine is now active
97 + static bool acc_run_called = false;
98 +
99  
100   /*
101 < *  Get pointer to drive info, NULL = invalid drive number
101 > *  Get pointer to drive info or drives.end() if not found
102   */
103  
104 < static DriveInfo *get_drive_info(int num)
104 > static drive_vec::iterator get_drive_info(int num)
105   {
106 <        DriveInfo *info = first_drive_info;
107 <        while (info != NULL) {
106 >        drive_vec::iterator info, end = drives.end();
107 >        for (info = drives.begin(); info != end; ++info) {
108                  if (info->num == num)
109                          return info;
104                info = info->next;
110          }
111 <        return NULL;
111 >        return info;
112 > }
113 >
114 >
115 > /*
116 > *  Find HFS partition, set info->start_byte and info->num_blocks
117 > *  (0 = no partition map or HFS partition found, assume flat disk image)
118 > */
119 >
120 > static void find_hfs_partition(disk_drive_info &info)
121 > {
122 >        info.start_byte = 0;
123 >        info.num_blocks = 0;
124 >        uint8 *map = new uint8[512];
125 >
126 >        // Search first 64 blocks for HFS partition
127 >        for (int i=0; i<64; i++) {
128 >                if (Sys_read(info.fh, map, i * 512, 512) != 512)
129 >                        break;
130 >
131 >                // Not a partition map block? Then look at next block
132 >                uint16 sig = (map[0] << 8) | map[1];
133 >                if (sig != 0x504d)
134 >                        continue;
135 >
136 >                // Partition map block found, Apple HFS partition?
137 >                if (strcmp((char *)(map + 48), "Apple_HFS") == 0) {
138 >                        info.start_byte = (loff_t)((map[8] << 24) | (map[9] << 16) | (map[10] << 8) | map[11]) << 9;
139 >                        info.num_blocks = (map[12] << 24) | (map[13] << 16) | (map[14] << 8) | map[15];
140 >                        D(bug(" HFS partition found at %d, %d blocks\n", info.start_byte, info.num_blocks));
141 >                        break;
142 >                }
143 >        }
144 >        delete[] map;
145   }
146  
147  
# Line 113 | Line 151 | static DriveInfo *get_drive_info(int num
151  
152   void DiskInit(void)
153   {
116        first_drive_info = NULL;
117
154          // No drives specified in prefs? Then add defaults
155          if (PrefsFindString("disk", 0) == NULL)
156                  SysAddDiskPrefs();
157  
158          // Add drives specified in preferences
159 <        int32 index = 0;
159 >        int index = 0;
160          const char *str;
161          while ((str = PrefsFindString("disk", index++)) != NULL) {
162                  bool read_only = false;
# Line 129 | Line 165 | void DiskInit(void)
165                          str++;
166                  }
167                  void *fh = Sys_open(str, read_only);
168 <                if (fh) {
169 <                        D(bug(" adding drive '%s'\n", str));
134 <                        DriveInfo *info = new DriveInfo;
135 <                        info->fh = fh;
136 <                        info->read_only = SysIsReadOnly(fh);
137 <                        DriveInfo *p = (DriveInfo *)&first_drive_info;
138 <                        while (p->next != NULL)
139 <                                p = p->next;
140 <                        p->next = info;
141 <                }
168 >                if (fh)
169 >                        drives.push_back(disk_drive_info(fh, SysIsReadOnly(fh)));
170          }
171   }
172  
# Line 149 | Line 177 | void DiskInit(void)
177  
178   void DiskExit(void)
179   {
180 <        DriveInfo *info = first_drive_info, *next;
181 <        while (info != NULL) {
182 <                Sys_close(info->fh);
183 <                next = info->next;
156 <                delete info;
157 <                info = next;
158 <        }
180 >        drive_vec::iterator info, end = drives.end();
181 >        for (info = drives.begin(); info != end; ++info)
182 >                info->close_fh();
183 >        drives.clear();
184   }
185  
186  
# Line 165 | Line 190 | void DiskExit(void)
190  
191   bool DiskMountVolume(void *fh)
192   {
193 <        DriveInfo *info;
194 <        for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
195 <        if (info) {
193 >        drive_vec::iterator info = drives.begin(), end = drives.end();
194 >        while (info != end && info->fh != fh)
195 >                ++info;
196 >        if (info != end) {
197                  if (SysIsDiskInserted(info->fh)) {
198                          info->read_only = SysIsReadOnly(info->fh);
199                          WriteMacInt8(info->status + dsDiskInPlace, 1);  // Inserted removable disk
200                          WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
201 <                        info->num_blocks = SysGetFileSize(info->fh) / 512;
201 >                        find_hfs_partition(*info);
202 >                        if (info->start_byte == 0)
203 >                                info->num_blocks = SysGetFileSize(info->fh) / 512;
204                          WriteMacInt16(info->status + dsDriveSize, info->num_blocks & 0xffff);
205                          WriteMacInt16(info->status + dsDriveS1, info->num_blocks >> 16);
206                          info->to_be_mounted = true;
# Line 184 | Line 212 | bool DiskMountVolume(void *fh)
212  
213  
214   /*
215 + *  Mount volumes for which the to_be_mounted flag is set
216 + *  (called during interrupt time)
217 + */
218 +
219 + static void mount_mountable_volumes(void)
220 + {
221 +        drive_vec::iterator info, end = drives.end();
222 +        for (info = drives.begin(); info != end; ++info) {
223 +
224 +                // Disk in drive?
225 +                if (!ReadMacInt8(info->status + dsDiskInPlace)) {
226 +
227 +                        // No, check if disk was inserted
228 +                        if (SysIsDiskInserted(info->fh))
229 +                                DiskMountVolume(info->fh);
230 +                }
231 +
232 +                // Mount disk if flagged
233 +                if (info->to_be_mounted) {
234 +                        D(bug(" mounting drive %d\n", info->num));
235 +                        M68kRegisters r;
236 +                        r.d[0] = info->num;
237 +                        r.a[0] = 7;     // diskEvent
238 +                        Execute68kTrap(0xa02f, &r);             // PostEvent()
239 +                        info->to_be_mounted = false;
240 +                }
241 +        }
242 + }
243 +
244 +
245 + /*
246   *  Driver Open() routine
247   */
248  
# Line 193 | Line 252 | int16 DiskOpen(uint32 pb, uint32 dce)
252  
253          // Set up DCE
254          WriteMacInt32(dce + dCtlPosition, 0);
255 +        acc_run_called = false;
256  
257          // Install drives
258 <        for (DriveInfo *info = first_drive_info; info; info = info->next) {
258 >        drive_vec::iterator info, end = drives.end();
259 >        for (info = drives.begin(); info != end; ++info) {
260  
261                  info->num = FindFreeDriveNumber(1);
262                  info->to_be_mounted = false;
# Line 225 | Line 286 | int16 DiskOpen(uint32 pb, uint32 dce)
286                          if (disk_in_place) {
287                                  D(bug(" disk inserted\n"));
288                                  WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0x80 : 0);
289 <                                info->num_blocks = SysGetFileSize(info->fh) / 512;
289 >                                find_hfs_partition(*info);
290 >                                if (info->start_byte == 0)
291 >                                        info->num_blocks = SysGetFileSize(info->fh) / 512;
292                                  info->to_be_mounted = true;
293                          }
294 <                        D(bug(" %ld blocks\n", info->num_blocks));
294 >                        D(bug(" %d blocks\n", info->num_blocks));
295                          WriteMacInt16(info->status + dsDriveSize, info->num_blocks & 0xffff);
296                          WriteMacInt16(info->status + dsDriveS1, info->num_blocks >> 16);
297  
# Line 252 | Line 315 | int16 DiskPrime(uint32 pb, uint32 dce)
315          WriteMacInt32(pb + ioActCount, 0);
316  
317          // Drive valid and disk inserted?
318 <        DriveInfo *info;
319 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
318 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
319 >        if (info == drives.end())
320                  return nsDrvErr;
321          if (!ReadMacInt8(info->status + dsDiskInPlace))
322                  return offLinErr;
# Line 263 | Line 326 | int16 DiskPrime(uint32 pb, uint32 dce)
326          size_t length = ReadMacInt32(pb + ioReqCount);
327          loff_t position = ReadMacInt32(dce + dCtlPosition);
328          if (ReadMacInt16(pb + ioPosMode) & 0x100)       // 64 bit positioning
329 <                position = ((loff_t)ReadMacInt32(pb + ioWPosOffset) << 32) || ReadMacInt32(pb + ioWPosOffset + 4);
329 >                position = ((loff_t)ReadMacInt32(pb + ioWPosOffset) << 32) | ReadMacInt32(pb + ioWPosOffset + 4);
330          if ((length & 0x1ff) || (position & 0x1ff))
331                  return paramErr;
332  
# Line 271 | Line 334 | int16 DiskPrime(uint32 pb, uint32 dce)
334          if ((ReadMacInt16(pb + ioTrap) & 0xff) == aRdCmd) {
335  
336                  // Read
337 <                actual = Sys_read(info->fh, buffer, position, length);
337 >                actual = Sys_read(info->fh, buffer, position + info->start_byte, length);
338                  if (actual != length)
339                          return readErr;
340  
# Line 280 | Line 343 | int16 DiskPrime(uint32 pb, uint32 dce)
343                  // Write
344                  if (info->read_only)
345                          return wPrErr;
346 <                actual = Sys_write(info->fh, buffer, position, length);
346 >                actual = Sys_write(info->fh, buffer, position + info->start_byte, length);
347                  if (actual != length)
348                          return writErr;
349          }
# Line 306 | Line 369 | int16 DiskControl(uint32 pb, uint32 dce)
369                  case 1:         // KillIO
370                          return noErr;
371  
372 <                case 65: {      // Periodic action ("insert" disks on startup and check for disk changes)
373 <                        DriveInfo *info = first_drive_info;
374 <                        while (info != NULL) {
375 <
313 <                                // Disk in drive?
314 <                                if (!ReadMacInt8(info->status + dsDiskInPlace)) {
315 <
316 <                                        // No, check if disk was inserted
317 <                                        if (SysIsDiskInserted(info->fh))
318 <                                                DiskMountVolume(info->fh);
319 <                                }
320 <
321 <                                // Mount disk if flagged
322 <                                if (info->to_be_mounted) {
323 <                                        D(bug(" mounting drive %d\n", info->num));
324 <                                        M68kRegisters r;
325 <                                        r.d[0] = info->num;
326 <                                        r.a[0] = 7;     // diskEvent
327 <                                        Execute68kTrap(0xa02f, &r);             // PostEvent()
328 <                                        info->to_be_mounted = false;
329 <                                }
330 <
331 <                                info = info->next;
332 <                        }
372 >                case 65: {      // Periodic action (accRun, "insert" disks on startup)
373 >                        mount_mountable_volumes();
374 >                        WriteMacInt16(dce + dCtlFlags, ReadMacInt16(dce + dCtlFlags) & ~0x2000);        // Disable periodic action
375 >                        acc_run_called = true;
376                          return noErr;
377                  }
378          }
379  
380          // Drive valid?
381 <        DriveInfo *info;
382 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
381 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
382 >        if (info == drives.end())
383                  return nsDrvErr;
384  
385          // Drive-specific codes
# Line 400 | Line 443 | int16 DiskControl(uint32 pb, uint32 dce)
443  
444   int16 DiskStatus(uint32 pb, uint32 dce)
445   {
446 <        DriveInfo *info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
446 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
447          uint16 code = ReadMacInt16(pb + csCode);
448          D(bug("DiskStatus %d\n", code));
449  
450 <        // General codes
450 >        // General codes (we can get these even if the drive was invalid)
451          switch (code) {
452                  case 43: {      // Driver gestalt
453                          uint32 sel = ReadMacInt32(pb + csParam);
454                          D(bug(" driver gestalt %c%c%c%c\n", sel >> 24, sel >> 16,  sel >> 8, sel));
455                          switch (sel) {
456 <                                case 'vers':    // Version
456 >                                case FOURCC('v','e','r','s'):   // Version
457                                          WriteMacInt32(pb + csParam + 4, 0x01008000);
458                                          break;
459 <                                case 'devt':    // Device type
460 <                                        if (info != NULL) {
459 >                                case FOURCC('d','e','v','t'):   // Device type
460 >                                        if (info != drives.end()) {
461                                                  if (ReadMacInt8(info->status + dsDiskInPlace) == 8)
462 <                                                        WriteMacInt32(pb + csParam + 4, 'disk');
462 >                                                        WriteMacInt32(pb + csParam + 4, FOURCC('d','i','s','k'));
463                                                  else
464 <                                                        WriteMacInt32(pb + csParam + 4, 'rdsk');
464 >                                                        WriteMacInt32(pb + csParam + 4, FOURCC('r','d','s','k'));
465                                          } else
466 <                                                WriteMacInt32(pb + csParam + 4, 'disk');
466 >                                                WriteMacInt32(pb + csParam + 4, FOURCC('d','i','s','k'));
467                                          break;
468 <                                case 'intf':    // Interface type
469 <                                        WriteMacInt32(pb + csParam + 4, 'basi');
468 >                                case FOURCC('i','n','t','f'):   // Interface type
469 >                                        WriteMacInt32(pb + csParam + 4, EMULATOR_ID_4);
470                                          break;
471 <                                case 'sync':    // Only synchronous operation?
471 >                                case FOURCC('s','y','n','c'):   // Only synchronous operation?
472                                          WriteMacInt32(pb + csParam + 4, 0x01000000);
473                                          break;
474 <                                case 'boot':    // Boot ID
475 <                                        if (info != NULL)
474 >                                case FOURCC('b','o','o','t'):   // Boot ID
475 >                                        if (info != drives.end())
476                                                  WriteMacInt16(pb + csParam + 4, info->num);
477                                          else
478                                                  WriteMacInt16(pb + csParam + 4, 0);
479                                          WriteMacInt16(pb + csParam + 6, (uint16)DiskRefNum);
480                                          break;
481 <                                case 'wide':    // 64-bit access supported?
481 >                                case FOURCC('w','i','d','e'):   // 64-bit access supported?
482                                          WriteMacInt16(pb + csParam + 4, 0x0100);
483                                          break;
484 <                                case 'purg':    // Purge flags
484 >                                case FOURCC('p','u','r','g'):   // Purge flags
485                                          WriteMacInt32(pb + csParam + 4, 0);
486                                          break;
487 <                                case 'ejec':    // Eject flags
487 >                                case FOURCC('e','j','e','c'):   // Eject flags
488                                          WriteMacInt32(pb + csParam + 4, 0x00030003);    // Don't eject on shutdown/restart
489                                          break;
490 <                                case 'flus':    // Flush flags
490 >                                case FOURCC('f','l','u','s'):   // Flush flags
491                                          WriteMacInt16(pb + csParam + 4, 0);
492                                          break;
493 <                                case 'vmop':    // Virtual memory attributes
493 >                                case FOURCC('v','m','o','p'):   // Virtual memory attributes
494                                          WriteMacInt32(pb + csParam + 4, 0);     // Drive not available for VM
495                                          break;
496                                  default:
# Line 458 | Line 501 | int16 DiskStatus(uint32 pb, uint32 dce)
501          }
502  
503          // Drive valid?
504 <        if (info == NULL)
504 >        if (info == drives.end())
505                  return nsDrvErr;
506  
507          // Drive-specific codes
508          switch (code) {
509                  case 8:         // Get drive status
510 <                        memcpy(Mac2HostAddr(pb + csParam), Mac2HostAddr(info->status), 22);
510 >                        Mac2Mac_memcpy(pb + csParam, info->status, 22);
511                          return noErr;
512  
513 +                case 44: // get startup partition status: http://developer.apple.com/documentation/Hardware/DeviceManagers/ata/ata_ref/ATA.21.html
514 +                        printf("WARNING: DiskStatus(44:'get startup partition status') Not Implemented\n");
515 +                        return statusErr;
516 +
517 +                case 45: // get partition write protect status: http://developer.apple.com/documentation/Hardware/DeviceManagers/ata/ata_ref/ATA.23.html
518 +                        printf("WARNING: DiskStatus(45:'get partition write protect status') Not Implemented\n");
519 +                        return statusErr;
520 +
521 +                case 46: // get partition mount status: http://developer.apple.com/documentation/Hardware/DeviceManagers/ata/ata_ref/ATA.22.html
522 +                        printf("WARNING: DiskStatus(46:'get partition mount status') Not Implemented\n");
523 +                        return statusErr;
524 +
525 +                case 70: // get power mode status: http://developer.apple.com/documentation/Hardware/DeviceManagers/ata/ata_ref/ATA.24.html
526 +                        printf("WARNING: DiskStatus(70:'get power mode status') Not Implemented\n");
527 +                        return statusErr;
528 +
529                  default:
530                          printf("WARNING: Unknown DiskStatus(%d)\n", code);
531                          return statusErr;
532          }
533   }
534 +
535 +
536 + /*
537 + *  Driver interrupt routine (1Hz) - check for volumes to be mounted
538 + */
539 +
540 + void DiskInterrupt(void)
541 + {
542 +        if (!acc_run_called)
543 +                return;
544 +
545 +        mount_mountable_volumes();
546 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines