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.3 by cebix, 1999-10-25T08:07:48Z 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 39 | Line 44
44   #include "prefs.h"
45   #include "sony.h"
46  
47 < #define DEBUG 1
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  
126 // Number of ticks between checks for disk insertion
127 const int driver_delay = 120;
128
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;
143                info = info->next;
143          }
144 <        return NULL;
144 >        return info;
145   }
146  
147  
# Line 152 | Line 151 | static DriveInfo *get_drive_info(int num
151  
152   void SonyInit(void)
153   {
155        first_drive_info = NULL;
156
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 168 | Line 165 | void SonyInit(void)
165                          str++;
166                  }
167                  void *fh = Sys_open(str, read_only);
168 <                if (fh) {
169 <                        DriveInfo *info = new DriveInfo;
173 <                        info->fh = fh;
174 <                        info->read_only = SysIsReadOnly(fh);
175 <                        DriveInfo *p = (DriveInfo *)&first_drive_info;
176 <                        while (p->next != NULL)
177 <                                p = p->next;
178 <                        p->next = info;
179 <                }
168 >                if (fh)
169 >                        drives.push_back(sony_drive_info(fh, SysIsReadOnly(fh)));
170          }
171   }
172  
# Line 187 | 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;
194 <                delete info;
195 <                info = next;
196 <        }
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 203 | 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 225 | Line 213 | bool SonyMountVolume(void *fh)
213  
214   static void mount_mountable_volumes(void)
215   {
216 <        DriveInfo *info = first_drive_info;
217 <        while (info != NULL) {
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?
# Line 247 | Line 235 | static void mount_mountable_volumes(void
235                          Execute68kTrap(0xa02f, &r);             // PostEvent()
236                          info->to_be_mounted = false;
237                  }
250
251                info = info->next;
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 274 | 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 331 | 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 343 | 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 351 | 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 362 | 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 387 | 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;
391 >                        return set_dsk_err(noErr);
392  
393                  case 65:        // Periodic action (accRun, "insert" disks on startup)
394                          mount_mountable_volumes();
# Line 401 | Line 399 | int16 SonyControl(uint32 pb, uint32 dce)
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
414 <                                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;
422 <                                else
423 <                                        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;
465 <                }
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 481 | 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 492 | 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
495                                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 - check for volumes to be mounted
526 > *  Driver interrupt routine (1Hz) - check for volumes to be mounted
527   */
528  
529   void SonyInterrupt(void)
530   {
528        static int tick_count = 0;
531          if (!acc_run_called)
532                  return;
533  
534 <        tick_count++;
533 <        if (tick_count > driver_delay) {
534 <                tick_count = 0;
535 <                mount_mountable_volumes();
536 <        }
534 >        mount_mountable_volumes();
535   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines