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

Comparing BasiliskII/src/sony.cpp (file contents):
Revision 1.1 by cebix, 1999-10-03T14:16:25Z vs.
Revision 1.11 by cebix, 2001-07-01T14:38:02Z

# Line 1 | Line 1
1   /*
2   *  sony.cpp - Replacement .Sony driver (floppy drives)
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 29 | Line 29
29   */
30  
31   #include <string.h>
32 + #include <vector>
33 +
34 + #ifndef NO_STD_NAMESPACE
35 + using std::vector;
36 + #endif
37  
38   #include "sysdeps.h"
39   #include "cpu_emulation.h"
# Line 42 | Line 47
47   #define DEBUG 0
48   #include "debug.h"
49  
50 +
51 + // Check for inserted disks by polling?
52   #ifdef AMIGA
53 < #define DISK_INSERT_CHECK 1             // Check for inserted disks (problem: on most hardware, disks are not ejected and automatically remounted)
53 > #define DISK_INSERT_CHECK 1
54   #else
55   #define DISK_INSERT_CHECK 0
56   #endif
# Line 97 | Line 104 | const uint8 SonyDriveIcon[258] = {
104  
105  
106   // Struct for each drive
107 < struct DriveInfo {
108 <        DriveInfo()
109 <        {
110 <                next = NULL;
111 <                num = 0;
105 <                fh = NULL;
106 <                read_only = false;
107 <                status = 0;
108 <        }
107 > struct sony_drive_info {
108 >        sony_drive_info() : num(0), fh(NULL), read_only(false), status(0) {}
109 >        sony_drive_info(void *fh_, bool ro) : num(0), fh(fh_), read_only(ro), status(0) {}
110 >
111 >        void close_fh(void) { Sys_close(fh); }
112  
110        DriveInfo *next;        // Pointer to next DriveInfo (must be first in struct!)
113          int num;                        // Drive number
114          void *fh;                       // Floppy driver file handle
115          bool to_be_mounted;     // Flag: drive must be mounted in accRun
# Line 116 | Line 118 | struct DriveInfo {
118          uint32 status;          // Mac address of drive status record
119   };
120  
121 < // Linked list of DriveInfos
122 < static DriveInfo *first_drive_info;
121 > // List of drives handled by this driver
122 > typedef vector<sony_drive_info> drive_vec;
123 > static drive_vec drives;
124  
125   // Icon addresses (Mac address space, set by PatchROM())
126   uint32 SonyDiskIconAddr;
127   uint32 SonyDriveIconAddr;
128  
129 < // Flag: accRun called for the first time, run PatchAfterStartup()
130 < static bool periodic_first_time = false;
129 > // Flag: Control(accRun) has been called, interrupt routine is now active
130 > static bool acc_run_called = false;
131  
132  
133   /*
134 < *  Get pointer to drive info, NULL = invalid drive number
134 > *  Get reference to drive info or drives.end() if not found
135   */
136  
137 < static DriveInfo *get_drive_info(int num)
137 > static drive_vec::iterator get_drive_info(int num)
138   {
139 <        DriveInfo *info = first_drive_info;
140 <        while (info != NULL) {
139 >        drive_vec::iterator info, end = drives.end();
140 >        for (info = drives.begin(); info != end; ++info) {
141                  if (info->num == num)
142                          return info;
140                info = info->next;
143          }
144 <        return NULL;
144 >        return info;
145   }
146  
147  
# Line 149 | Line 151 | static DriveInfo *get_drive_info(int num
151  
152   void SonyInit(void)
153   {
152        first_drive_info = NULL;
153
154          // No drives specified in prefs? Then add defaults
155          if (PrefsFindString("floppy", 0) == NULL)
156                  SysAddFloppyPrefs();
157  
158          // Add drives specified in preferences
159 <        int32 index = 0;
159 >        int index = 0;
160          const char *str;
161          while ((str = PrefsFindString("floppy", index++)) != NULL) {
162                  bool read_only = false;
# Line 165 | Line 165 | void SonyInit(void)
165                          str++;
166                  }
167                  void *fh = Sys_open(str, read_only);
168 <                if (fh) {
169 <                        DriveInfo *info = new DriveInfo;
170 <                        info->fh = fh;
171 <                        info->read_only = SysIsReadOnly(fh);
172 <                        DriveInfo *p = (DriveInfo *)&first_drive_info;
173 <                        while (p->next != NULL)
174 <                                p = p->next;
175 <                        p->next = info;
176 <                }
168 >                if (fh)
169 >                        drives.push_back(sony_drive_info(fh, SysIsReadOnly(fh)));
170          }
171   }
172  
# Line 184 | Line 177 | void SonyInit(void)
177  
178   void SonyExit(void)
179   {
180 <        DriveInfo *info = first_drive_info, *next;
181 <        while (info != NULL) {
182 <                Sys_close(info->fh);
183 <                next = info->next;
191 <                delete info;
192 <                info = next;
193 <        }
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 200 | Line 190 | void SonyExit(void)
190  
191   bool SonyMountVolume(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
# Line 216 | Line 207 | bool SonyMountVolume(void *fh)
207  
208  
209   /*
210 + *  Mount volumes for which the to_be_mounted flag is set
211 + *  (called during interrupt time)
212 + */
213 +
214 + static void mount_mountable_volumes(void)
215 + {
216 +        drive_vec::iterator info, end = drives.end();
217 +        for (info = drives.begin(); info != end; ++info) {
218 +
219 + #if DISK_INSERT_CHECK
220 +                // Disk in drive?
221 +                if (!ReadMacInt8(info->status + dsDiskInPlace)) {
222 +
223 +                        // No, check if disk was inserted
224 +                        if (SysIsDiskInserted(info->fh))
225 +                                SonyMountVolume(info->fh);
226 +                }
227 + #endif
228 +
229 +                // Mount disk if flagged
230 +                if (info->to_be_mounted) {
231 +                        D(bug(" mounting drive %d\n", info->num));
232 +                        M68kRegisters r;
233 +                        r.d[0] = info->num;
234 +                        r.a[0] = 7;     // diskEvent
235 +                        Execute68kTrap(0xa02f, &r);             // PostEvent()
236 +                        info->to_be_mounted = false;
237 +                }
238 +        }
239 + }
240 +
241 +
242 + /*
243 + *  Set error code in DskErr
244 + */
245 +
246 + static int16 set_dsk_err(int16 err)
247 + {
248 +        WriteMacInt16(0x142, err);
249 +        return err;
250 + }
251 +
252 +
253 + /*
254   *  Driver Open() routine
255   */
256  
# Line 226 | Line 261 | int16 SonyOpen(uint32 pb, uint32 dce)
261          // Set up DCE
262          WriteMacInt32(dce + dCtlPosition, 0);
263          WriteMacInt16(dce + dCtlQHdr + qFlags, ReadMacInt16(dce + dCtlQHdr + qFlags) & 0xff00 | 3);     // Version number, must be >=3 or System 8 will replace us
264 <        periodic_first_time = true;
264 >        acc_run_called = false;
265  
266          // Install driver again with refnum -2 (HD20)
267          uint32 utab = ReadMacInt32(0x11c);
# Line 236 | Line 271 | int16 SonyOpen(uint32 pb, uint32 dce)
271          WriteMacInt32(0x134, 0xdeadbeef);
272  
273          // Clear DskErr
274 <        WriteMacInt16(0x142, 0);
274 >        set_dsk_err(0);
275  
276          // Install drives
277 <        for (DriveInfo *info = first_drive_info; info; info = info->next) {
277 >        drive_vec::iterator info, end = drives.end();
278 >        for (info = drives.begin(); info != end; ++info) {
279  
280                  info->num = FindFreeDriveNumber(1);
281                  info->to_be_mounted = false;
# Line 293 | Line 329 | int16 SonyPrime(uint32 pb, uint32 dce)
329          WriteMacInt32(pb + ioActCount, 0);
330  
331          // Drive valid and disk inserted?
332 <        DriveInfo *info;
333 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
334 <                return nsDrvErr;
332 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
333 >        if (info == drives.end())
334 >                return set_dsk_err(nsDrvErr);
335          if (!ReadMacInt8(info->status + dsDiskInPlace))
336 <                return offLinErr;
336 >                return set_dsk_err(offLinErr);
337          WriteMacInt8(info->status + dsDiskInPlace, 2);  // Disk accessed
338  
339          // Get parameters
# Line 305 | Line 341 | int16 SonyPrime(uint32 pb, uint32 dce)
341          size_t length = ReadMacInt32(pb + ioReqCount);
342          loff_t position = ReadMacInt32(dce + dCtlPosition);
343          if ((length & 0x1ff) || (position & 0x1ff))
344 <                return paramErr;
344 >                return set_dsk_err(paramErr);
345  
346          size_t actual = 0;
347          if ((ReadMacInt16(pb + ioTrap) & 0xff) == aRdCmd) {
# Line 313 | Line 349 | int16 SonyPrime(uint32 pb, uint32 dce)
349                  // Read
350                  actual = Sys_read(info->fh, buffer, position, length);
351                  if (actual != length)
352 <                        return readErr;
352 >                        return set_dsk_err(readErr);
353  
354                  // Clear TagBuf
355                  WriteMacInt32(0x2fc, 0);
# Line 324 | Line 360 | int16 SonyPrime(uint32 pb, uint32 dce)
360  
361                  // Write
362                  if (info->read_only)
363 <                        return wPrErr;
363 >                        return set_dsk_err(wPrErr);
364                  actual = Sys_write(info->fh, buffer, position, length);
365                  if (actual != length)
366 <                        return writErr;
366 >                        return set_dsk_err(writErr);
367          }
368  
369          // Update ParamBlock and DCE
370          WriteMacInt32(pb + ioActCount, actual);
371          WriteMacInt32(dce + dCtlPosition, ReadMacInt32(dce + dCtlPosition) + actual);
372 <        return noErr;
372 >        return set_dsk_err(noErr);
373   }
374  
375  
# Line 349 | Line 385 | int16 SonyControl(uint32 pb, uint32 dce)
385          // General codes
386          switch (code) {
387                  case 1:         // KillIO
388 <                        return -1;
388 >                        return set_dsk_err(-1);
389  
390                  case 9:         // Track cache
391 <                        return noErr;
356 <
357 <                case 65: {      // Periodic action ("insert" disks on startup and check for disk changes)
358 <                        DriveInfo *info = first_drive_info;
359 <                        while (info != NULL) {
391 >                        return set_dsk_err(noErr);
392  
393 <                                // Disk in drive?
394 <                                if (!ReadMacInt8(info->status + dsDiskInPlace)) {
395 <
396 < #if DISK_INSERT_CHECK
397 <                                        // No, check if disk was inserted
366 <                                        if (SysIsDiskInserted(info->fh))
367 <                                                SonyMountVolume(info->fh);
368 < #endif
369 <                                }
370 <
371 <                                // Mount disk if flagged
372 <                                if (info->to_be_mounted) {
373 <                                        D(bug(" mounting drive %d\n", info->num));
374 <                                        M68kRegisters r;
375 <                                        r.d[0] = info->num;
376 <                                        r.a[0] = 7;     // diskEvent
377 <                                        Execute68kTrap(0xa02f, &r);             // PostEvent()
378 <                                        info->to_be_mounted = false;
379 <                                }
380 <
381 <                                info = info->next;
382 <                        }
383 <                        if (periodic_first_time) {
384 <                                periodic_first_time = false;
385 <                                PatchAfterStartup();            // Install patches after system startup
386 <                        }
393 >                case 65:        // Periodic action (accRun, "insert" disks on startup)
394 >                        mount_mountable_volumes();
395 >                        PatchAfterStartup();            // Install patches after system startup
396 >                        WriteMacInt16(dce + dCtlFlags, ReadMacInt16(dce + dCtlFlags) & ~0x2000);        // Disable periodic action
397 >                        acc_run_called = true;
398                          return noErr;
388                }
399          }
400  
401          // Drive valid?
402 <        DriveInfo *info;
403 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
404 <                return nsDrvErr;
402 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
403 >        if (info == drives.end())
404 >                return set_dsk_err(nsDrvErr);
405  
406          // Drive-specific codes
407 +        int16 err = noErr;
408          switch (code) {
409                  case 5:         // Verify disk
410 <                        if (ReadMacInt8(info->status + dsDiskInPlace) > 0)
411 <                                return noErr;
412 <                        else
402 <                                return verErr;
410 >                        if (ReadMacInt8(info->status + dsDiskInPlace) <= 0)
411 >                                err = verErr;
412 >                        break;
413  
414                  case 6:         // Format disk
415                          if (info->read_only)
416 <                                return wPrErr;
416 >                                err = wPrErr;
417                          else if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
418 <                                if (SysFormat(info->fh))
419 <                                        return noErr;
410 <                                else
411 <                                        return writErr;
418 >                                if (!SysFormat(info->fh))
419 >                                        err = writErr;
420                          } else
421 <                                return offLinErr;
421 >                                err = offLinErr;
422 >                        break;
423  
424                  case 7:         // Eject
425                          if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
426                                  SysEject(info->fh);
427                                  WriteMacInt8(info->status + dsDiskInPlace, 0);
428                          }
429 <                        return noErr;
429 >                        break;
430  
431                  case 8:         // Set tag buffer
432                          info->tag_buffer = ReadMacInt32(pb + csParam);
433 <                        return noErr;
433 >                        break;
434  
435                  case 21:                // Get drive icon
436                          WriteMacInt32(pb + csParam, SonyDriveIconAddr);
437 <                        return noErr;
437 >                        break;
438  
439                  case 22:                // Get disk icon
440                          WriteMacInt32(pb + csParam, SonyDiskIconAddr);
441 <                        return noErr;
441 >                        break;
442  
443                  case 23:                // Get drive info
444                          if (info->num == 1)
445                                  WriteMacInt32(pb + csParam, 0x0004);    // Internal drive
446                          else
447                                  WriteMacInt32(pb + csParam, 0x0104);    // External drive
448 <                        return noErr;
448 >                        break;
449  
450 <                case 'SC': {    // Format and write to disk
450 >                case 0x5343:    // Format and write to disk ('SC'), used by DiskCopy
451                          if (!ReadMacInt8(info->status + dsDiskInPlace))
452 <                                return offLinErr;
453 <                        if (info->read_only)
454 <                                return wPrErr;
455 <
456 <                        void *data = Mac2HostAddr(ReadMacInt32(pb + csParam + 2));
457 <                        size_t actual = Sys_write(info->fh, data, 0, 2880*512);
458 <                        if (actual != 2880*512)
459 <                                return writErr;
460 <                        else
461 <                                return noErr;
453 <                }
452 >                                err = offLinErr;
453 >                        else if (info->read_only)
454 >                                err = wPrErr;
455 >                        else {
456 >                                void *data = Mac2HostAddr(ReadMacInt32(pb + csParam + 2));
457 >                                size_t actual = Sys_write(info->fh, data, 0, 2880*512);
458 >                                if (actual != 2880*512)
459 >                                        err = writErr;
460 >                        }
461 >                        break;
462  
463                  default:
464                          printf("WARNING: Unknown SonyControl(%d)\n", code);
465 <                        return controlErr;
465 >                        err = controlErr;
466 >                        break;
467          }
468 +
469 +        return set_dsk_err(err);
470   }
471  
472  
# Line 469 | Line 480 | int16 SonyStatus(uint32 pb, uint32 dce)
480          D(bug("SonyStatus %d\n", code));
481  
482          // Drive valid?
483 <        DriveInfo *info;
484 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
485 <                return nsDrvErr;
483 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
484 >        if (info == drives.end())
485 >                return set_dsk_err(nsDrvErr);
486  
487 +        int16 err = noErr;
488          switch (code) {
489                  case 6:         // Return format list
490                          if (ReadMacInt16(pb + csParam) > 0) {
# Line 480 | Line 492 | int16 SonyStatus(uint32 pb, uint32 dce)
492                                  WriteMacInt16(pb + csParam, 1);         // 1 format
493                                  WriteMacInt32(adr, 2880);                       // 2880 sectors
494                                  WriteMacInt32(adr + 4, 0xd2120050);     // 2 heads, 18 secs/track, 80 tracks
483                                return noErr;
495                          } else
496 <                                return paramErr;
496 >                                err = paramErr;
497 >                        break;
498  
499                  case 8:         // Get drive status
500 <                        memcpy(Mac2HostAddr(pb + csParam), Mac2HostAddr(info->status), 22);
501 <                        return noErr;
500 >                        Mac2Mac_memcpy(pb + csParam, info->status, 22);
501 >                        break;
502  
503                  case 10:        // Get disk type
504                          WriteMacInt32(pb + csParam, ReadMacInt32(info->status + dsMFMDrive) & 0xffffff00 | 0xfe);
505 <                        return noErr;
505 >                        break;
506  
507 <                case 'DV':      // Duplicator version supported
507 >                case 0x4456: // Duplicator version supported ('DV')
508                          WriteMacInt16(pb + csParam, 0x0410);
509 <                        return noErr;
509 >                        break;
510  
511 <                case 'SC':      // Get address header format byte
511 >                case 0x5343: // Get address header format byte ('SC')
512                          WriteMacInt8(pb + csParam, 0x22);       // 512 bytes/sector
513 <                        return noErr;
513 >                        break;
514  
515                  default:
516                          printf("WARNING: Unknown SonyStatus(%d)\n", code);
517 <                        return statusErr;
517 >                        err = statusErr;
518 >                        break;
519          }
520 +
521 +        return set_dsk_err(err);
522 + }
523 +
524 +
525 + /*
526 + *  Driver interrupt routine (1Hz) - check for volumes to be mounted
527 + */
528 +
529 + void SonyInterrupt(void)
530 + {
531 +        if (!acc_run_called)
532 +                return;
533 +
534 +        mount_mountable_volumes();
535   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines