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.10 by cebix, 2001-07-01T14:38:02Z

# 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-2001 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 27 | Line 27
27   */
28  
29   #include <string.h>
30 + #include <vector>
31 +
32 + #ifndef NO_STD_NAMESPACE
33 + using std::vector;
34 + #endif
35  
36   #include "sysdeps.h"
37   #include "cpu_emulation.h"
# Line 65 | Line 70 | const uint8 DiskIcon[258] = {
70  
71  
72   // Struct for each drive
73 < struct DriveInfo {
74 <        DriveInfo()
75 <        {
76 <                next = NULL;
77 <                num = 0;
73 <                fh = NULL;
74 <                read_only = false;
75 <                status = 0;
76 <        }
73 > struct disk_drive_info {
74 >        disk_drive_info() : num(0), fh(NULL), read_only(false), status(0) {}
75 >        disk_drive_info(void *fh_, bool ro) : num(0), fh(fh_), read_only(ro), status(0) {}
76 >
77 >        void close_fh(void) { Sys_close(fh); }
78  
78        DriveInfo *next;        // Pointer to next DriveInfo (must be first in struct!)
79          int num;                        // Drive number
80          void *fh;                       // File handle
81          uint32 num_blocks;      // Size in 512-byte blocks
# Line 84 | Line 84 | struct DriveInfo {
84          uint32 status;          // Mac address of drive status record
85   };
86  
87 < // Linked list of DriveInfos
88 < static DriveInfo *first_drive_info;
87 > // List of drives handled by this driver
88 > typedef vector<disk_drive_info> drive_vec;
89 > static drive_vec drives;
90  
91   // Icon address (Mac address space, set by PatchROM())
92   uint32 DiskIconAddr;
93  
94 + // Flag: Control(accRun) has been called, interrupt routine is now active
95 + static bool acc_run_called = false;
96 +
97  
98   /*
99 < *  Get pointer to drive info, NULL = invalid drive number
99 > *  Get pointer to drive info or drives.end() if not found
100   */
101  
102 < static DriveInfo *get_drive_info(int num)
102 > static drive_vec::iterator get_drive_info(int num)
103   {
104 <        DriveInfo *info = first_drive_info;
105 <        while (info != NULL) {
104 >        drive_vec::iterator info, end = drives.end();
105 >        for (info = drives.begin(); info != end; ++info) {
106                  if (info->num == num)
107                          return info;
104                info = info->next;
108          }
109 <        return NULL;
109 >        return info;
110   }
111  
112  
# Line 113 | Line 116 | static DriveInfo *get_drive_info(int num
116  
117   void DiskInit(void)
118   {
116        first_drive_info = NULL;
117
119          // No drives specified in prefs? Then add defaults
120          if (PrefsFindString("disk", 0) == NULL)
121                  SysAddDiskPrefs();
122  
123          // Add drives specified in preferences
124 <        int32 index = 0;
124 >        int index = 0;
125          const char *str;
126          while ((str = PrefsFindString("disk", index++)) != NULL) {
127                  bool read_only = false;
# Line 129 | Line 130 | void DiskInit(void)
130                          str++;
131                  }
132                  void *fh = Sys_open(str, read_only);
133 <                if (fh) {
134 <                        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 <                }
133 >                if (fh)
134 >                        drives.push_back(disk_drive_info(fh, SysIsReadOnly(fh)));
135          }
136   }
137  
# Line 149 | Line 142 | void DiskInit(void)
142  
143   void DiskExit(void)
144   {
145 <        DriveInfo *info = first_drive_info, *next;
146 <        while (info != NULL) {
147 <                Sys_close(info->fh);
148 <                next = info->next;
156 <                delete info;
157 <                info = next;
158 <        }
145 >        drive_vec::iterator info, end = drives.end();
146 >        for (info = drives.begin(); info != end; ++info)
147 >                info->close_fh();
148 >        drives.clear();
149   }
150  
151  
# Line 165 | Line 155 | void DiskExit(void)
155  
156   bool DiskMountVolume(void *fh)
157   {
158 <        DriveInfo *info;
159 <        for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
160 <        if (info) {
158 >        drive_vec::iterator info = drives.begin(), end = drives.end();
159 >        while (info != end && info->fh != fh)
160 >                ++info;
161 >        if (info != end) {
162                  if (SysIsDiskInserted(info->fh)) {
163                          info->read_only = SysIsReadOnly(info->fh);
164                          WriteMacInt8(info->status + dsDiskInPlace, 1);  // Inserted removable disk
# Line 184 | Line 175 | bool DiskMountVolume(void *fh)
175  
176  
177   /*
178 + *  Mount volumes for which the to_be_mounted flag is set
179 + *  (called during interrupt time)
180 + */
181 +
182 + static void mount_mountable_volumes(void)
183 + {
184 +        drive_vec::iterator info, end = drives.end();
185 +        for (info = drives.begin(); info != end; ++info) {
186 +
187 +                // Disk in drive?
188 +                if (!ReadMacInt8(info->status + dsDiskInPlace)) {
189 +
190 +                        // No, check if disk was inserted
191 +                        if (SysIsDiskInserted(info->fh))
192 +                                DiskMountVolume(info->fh);
193 +                }
194 +
195 +                // Mount disk if flagged
196 +                if (info->to_be_mounted) {
197 +                        D(bug(" mounting drive %d\n", info->num));
198 +                        M68kRegisters r;
199 +                        r.d[0] = info->num;
200 +                        r.a[0] = 7;     // diskEvent
201 +                        Execute68kTrap(0xa02f, &r);             // PostEvent()
202 +                        info->to_be_mounted = false;
203 +                }
204 +        }
205 + }
206 +
207 +
208 + /*
209   *  Driver Open() routine
210   */
211  
# Line 193 | Line 215 | int16 DiskOpen(uint32 pb, uint32 dce)
215  
216          // Set up DCE
217          WriteMacInt32(dce + dCtlPosition, 0);
218 +        acc_run_called = false;
219  
220          // Install drives
221 <        for (DriveInfo *info = first_drive_info; info; info = info->next) {
221 >        drive_vec::iterator info, end = drives.end();
222 >        for (info = drives.begin(); info != end; ++info) {
223  
224                  info->num = FindFreeDriveNumber(1);
225                  info->to_be_mounted = false;
# Line 228 | Line 252 | int16 DiskOpen(uint32 pb, uint32 dce)
252                                  info->num_blocks = SysGetFileSize(info->fh) / 512;
253                                  info->to_be_mounted = true;
254                          }
255 <                        D(bug(" %ld blocks\n", info->num_blocks));
255 >                        D(bug(" %d blocks\n", info->num_blocks));
256                          WriteMacInt16(info->status + dsDriveSize, info->num_blocks & 0xffff);
257                          WriteMacInt16(info->status + dsDriveS1, info->num_blocks >> 16);
258  
# Line 252 | Line 276 | int16 DiskPrime(uint32 pb, uint32 dce)
276          WriteMacInt32(pb + ioActCount, 0);
277  
278          // Drive valid and disk inserted?
279 <        DriveInfo *info;
280 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
279 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
280 >        if (info == drives.end())
281                  return nsDrvErr;
282          if (!ReadMacInt8(info->status + dsDiskInPlace))
283                  return offLinErr;
# Line 306 | Line 330 | int16 DiskControl(uint32 pb, uint32 dce)
330                  case 1:         // KillIO
331                          return noErr;
332  
333 <                case 65: {      // Periodic action ("insert" disks on startup and check for disk changes)
334 <                        DriveInfo *info = first_drive_info;
335 <                        while (info != NULL) {
336 <
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 <                        }
333 >                case 65: {      // Periodic action (accRun, "insert" disks on startup)
334 >                        mount_mountable_volumes();
335 >                        WriteMacInt16(dce + dCtlFlags, ReadMacInt16(dce + dCtlFlags) & ~0x2000);        // Disable periodic action
336 >                        acc_run_called = true;
337                          return noErr;
338                  }
339          }
340  
341          // Drive valid?
342 <        DriveInfo *info;
343 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
342 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
343 >        if (info == drives.end())
344                  return nsDrvErr;
345  
346          // Drive-specific codes
# Line 400 | Line 404 | int16 DiskControl(uint32 pb, uint32 dce)
404  
405   int16 DiskStatus(uint32 pb, uint32 dce)
406   {
407 <        DriveInfo *info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
407 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
408          uint16 code = ReadMacInt16(pb + csCode);
409          D(bug("DiskStatus %d\n", code));
410  
411 <        // General codes
411 >        // General codes (we can get these even if the drive was invalid)
412          switch (code) {
413                  case 43: {      // Driver gestalt
414                          uint32 sel = ReadMacInt32(pb + csParam);
415                          D(bug(" driver gestalt %c%c%c%c\n", sel >> 24, sel >> 16,  sel >> 8, sel));
416                          switch (sel) {
417 <                                case 'vers':    // Version
417 >                                case FOURCC('v','e','r','s'):   // Version
418                                          WriteMacInt32(pb + csParam + 4, 0x01008000);
419                                          break;
420 <                                case 'devt':    // Device type
421 <                                        if (info != NULL) {
420 >                                case FOURCC('d','e','v','t'):   // Device type
421 >                                        if (info != drives.end()) {
422                                                  if (ReadMacInt8(info->status + dsDiskInPlace) == 8)
423 <                                                        WriteMacInt32(pb + csParam + 4, 'disk');
423 >                                                        WriteMacInt32(pb + csParam + 4, FOURCC('d','i','s','k'));
424                                                  else
425 <                                                        WriteMacInt32(pb + csParam + 4, 'rdsk');
425 >                                                        WriteMacInt32(pb + csParam + 4, FOURCC('r','d','s','k'));
426                                          } else
427 <                                                WriteMacInt32(pb + csParam + 4, 'disk');
427 >                                                WriteMacInt32(pb + csParam + 4, FOURCC('d','i','s','k'));
428                                          break;
429 <                                case 'intf':    // Interface type
430 <                                        WriteMacInt32(pb + csParam + 4, 'basi');
429 >                                case FOURCC('i','n','t','f'):   // Interface type
430 >                                        WriteMacInt32(pb + csParam + 4, EMULATOR_ID_4);
431                                          break;
432 <                                case 'sync':    // Only synchronous operation?
432 >                                case FOURCC('s','y','n','c'):   // Only synchronous operation?
433                                          WriteMacInt32(pb + csParam + 4, 0x01000000);
434                                          break;
435 <                                case 'boot':    // Boot ID
436 <                                        if (info != NULL)
435 >                                case FOURCC('b','o','o','t'):   // Boot ID
436 >                                        if (info != drives.end())
437                                                  WriteMacInt16(pb + csParam + 4, info->num);
438                                          else
439                                                  WriteMacInt16(pb + csParam + 4, 0);
440                                          WriteMacInt16(pb + csParam + 6, (uint16)DiskRefNum);
441                                          break;
442 <                                case 'wide':    // 64-bit access supported?
442 >                                case FOURCC('w','i','d','e'):   // 64-bit access supported?
443                                          WriteMacInt16(pb + csParam + 4, 0x0100);
444                                          break;
445 <                                case 'purg':    // Purge flags
445 >                                case FOURCC('p','u','r','g'):   // Purge flags
446                                          WriteMacInt32(pb + csParam + 4, 0);
447                                          break;
448 <                                case 'ejec':    // Eject flags
448 >                                case FOURCC('e','j','e','c'):   // Eject flags
449                                          WriteMacInt32(pb + csParam + 4, 0x00030003);    // Don't eject on shutdown/restart
450                                          break;
451 <                                case 'flus':    // Flush flags
451 >                                case FOURCC('f','l','u','s'):   // Flush flags
452                                          WriteMacInt16(pb + csParam + 4, 0);
453                                          break;
454 <                                case 'vmop':    // Virtual memory attributes
454 >                                case FOURCC('v','m','o','p'):   // Virtual memory attributes
455                                          WriteMacInt32(pb + csParam + 4, 0);     // Drive not available for VM
456                                          break;
457                                  default:
# Line 458 | Line 462 | int16 DiskStatus(uint32 pb, uint32 dce)
462          }
463  
464          // Drive valid?
465 <        if (info == NULL)
465 >        if (info == drives.end())
466                  return nsDrvErr;
467  
468          // Drive-specific codes
469          switch (code) {
470                  case 8:         // Get drive status
471 <                        memcpy(Mac2HostAddr(pb + csParam), Mac2HostAddr(info->status), 22);
471 >                        Mac2Mac_memcpy(pb + csParam, info->status, 22);
472                          return noErr;
473  
474                  default:
# Line 472 | Line 476 | int16 DiskStatus(uint32 pb, uint32 dce)
476                          return statusErr;
477          }
478   }
479 +
480 +
481 + /*
482 + *  Driver interrupt routine (1Hz) - check for volumes to be mounted
483 + */
484 +
485 + void DiskInterrupt(void)
486 + {
487 +        if (!acc_run_called)
488 +                return;
489 +
490 +        mount_mountable_volumes();
491 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines