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.5 by cebix, 1999-11-03T10:56:16Z vs.
Revision 1.15 by cebix, 2004-01-12T15:29:22Z

# 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-2004 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 28 | Line 28
28   *    Technote FL 24: "Don't Look at ioPosOffset for Devices"
29   */
30  
31 + #include "sysdeps.h"
32 +
33   #include <string.h>
34 + #include <vector>
35 +
36 + #ifndef NO_STD_NAMESPACE
37 + using std::vector;
38 + #endif
39  
33 #include "sysdeps.h"
40   #include "cpu_emulation.h"
41   #include "main.h"
42   #include "macos_util.h"
# Line 42 | Line 48
48   #define DEBUG 0
49   #include "debug.h"
50  
51 +
52 + // Check for inserted disks by polling?
53   #ifdef AMIGA
54 < #define DISK_INSERT_CHECK 1             // Check for inserted disks (problem: on most hardware, disks are not ejected and automatically remounted)
54 > #define DISK_INSERT_CHECK 1
55   #else
56   #define DISK_INSERT_CHECK 0
57   #endif
# Line 97 | Line 105 | const uint8 SonyDriveIcon[258] = {
105  
106  
107   // Struct for each drive
108 < struct DriveInfo {
109 <        DriveInfo()
110 <        {
111 <                next = NULL;
112 <                num = 0;
105 <                fh = NULL;
106 <                read_only = false;
107 <                status = 0;
108 <        }
108 > struct sony_drive_info {
109 >        sony_drive_info() : num(0), fh(NULL), read_only(false), status(0) {}
110 >        sony_drive_info(void *fh_, bool ro) : num(0), fh(fh_), read_only(ro), status(0) {}
111 >
112 >        void close_fh(void) { Sys_close(fh); }
113  
110        DriveInfo *next;        // Pointer to next DriveInfo (must be first in struct!)
114          int num;                        // Drive number
115          void *fh;                       // Floppy driver file handle
116          bool to_be_mounted;     // Flag: drive must be mounted in accRun
# Line 116 | Line 119 | struct DriveInfo {
119          uint32 status;          // Mac address of drive status record
120   };
121  
122 < // Linked list of DriveInfos
123 < static DriveInfo *first_drive_info;
122 > // List of drives handled by this driver
123 > typedef vector<sony_drive_info> drive_vec;
124 > static drive_vec drives;
125  
126   // Icon addresses (Mac address space, set by PatchROM())
127   uint32 SonyDiskIconAddr;
128   uint32 SonyDriveIconAddr;
129  
126 // Number of ticks between checks for disk insertion
127 const int driver_delay = 120;
128
130   // Flag: Control(accRun) has been called, interrupt routine is now active
131   static bool acc_run_called = false;
132  
133  
134   /*
135 < *  Get pointer to drive info, NULL = invalid drive number
135 > *  Get reference to drive info or drives.end() if not found
136   */
137  
138 < static DriveInfo *get_drive_info(int num)
138 > static drive_vec::iterator get_drive_info(int num)
139   {
140 <        DriveInfo *info = first_drive_info;
141 <        while (info != NULL) {
140 >        drive_vec::iterator info, end = drives.end();
141 >        for (info = drives.begin(); info != end; ++info) {
142                  if (info->num == num)
143                          return info;
143                info = info->next;
144          }
145 <        return NULL;
145 >        return info;
146   }
147  
148  
# Line 152 | Line 152 | static DriveInfo *get_drive_info(int num
152  
153   void SonyInit(void)
154   {
155        first_drive_info = NULL;
156
155          // No drives specified in prefs? Then add defaults
156          if (PrefsFindString("floppy", 0) == NULL)
157                  SysAddFloppyPrefs();
158  
159          // Add drives specified in preferences
160 <        int32 index = 0;
160 >        int index = 0;
161          const char *str;
162          while ((str = PrefsFindString("floppy", index++)) != NULL) {
163                  bool read_only = false;
# Line 168 | Line 166 | void SonyInit(void)
166                          str++;
167                  }
168                  void *fh = Sys_open(str, read_only);
169 <                if (fh) {
170 <                        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 <                }
169 >                if (fh)
170 >                        drives.push_back(sony_drive_info(fh, SysIsReadOnly(fh)));
171          }
172   }
173  
# Line 187 | Line 178 | void SonyInit(void)
178  
179   void SonyExit(void)
180   {
181 <        DriveInfo *info = first_drive_info, *next;
182 <        while (info != NULL) {
183 <                Sys_close(info->fh);
184 <                next = info->next;
194 <                delete info;
195 <                info = next;
196 <        }
181 >        drive_vec::iterator info, end = drives.end();
182 >        for (info = drives.begin(); info != end; ++info)
183 >                info->close_fh();
184 >        drives.clear();
185   }
186  
187  
# Line 203 | Line 191 | void SonyExit(void)
191  
192   bool SonyMountVolume(void *fh)
193   {
194 <        DriveInfo *info;
195 <        for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
196 <        if (info) {
194 >        drive_vec::iterator info = drives.begin(), end = drives.end();
195 >        while (info != end && info->fh != fh)
196 >                ++info;
197 >        if (info != end) {
198 >                D(bug("Looking for disk in drive %d\n", info->num));
199                  if (SysIsDiskInserted(info->fh)) {
200                          info->read_only = SysIsReadOnly(info->fh);
201                          WriteMacInt8(info->status + dsDiskInPlace, 1);  // Inserted removable disk
202                          WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
203 +                        D(bug(" disk inserted, mounting\n"));
204                          info->to_be_mounted = true;
205                  }
206                  return true;
# Line 225 | Line 216 | bool SonyMountVolume(void *fh)
216  
217   static void mount_mountable_volumes(void)
218   {
219 <        DriveInfo *info = first_drive_info;
220 <        while (info != NULL) {
219 >        drive_vec::iterator info, end = drives.end();
220 >        for (info = drives.begin(); info != end; ++info) {
221  
222   #if DISK_INSERT_CHECK
223                  // Disk in drive?
224 <                if (!ReadMacInt8(info->status + dsDiskInPlace)) {
224 >                if (ReadMacInt8(info->status + dsDiskInPlace) == 0) {
225  
226                          // No, check if disk was inserted
227                          if (SysIsDiskInserted(info->fh))
# Line 247 | Line 238 | static void mount_mountable_volumes(void
238                          Execute68kTrap(0xa02f, &r);             // PostEvent()
239                          info->to_be_mounted = false;
240                  }
250
251                info = info->next;
241          }
242   }
243  
244  
245   /*
246 + *  Set error code in DskErr
247 + */
248 +
249 + static int16 set_dsk_err(int16 err)
250 + {
251 +        D(bug("set_dsk_err(%d)\n", err));
252 +        WriteMacInt16(0x142, err);
253 +        return err;
254 + }
255 +
256 +
257 + /*
258   *  Driver Open() routine
259   */
260  
# Line 274 | Line 275 | int16 SonyOpen(uint32 pb, uint32 dce)
275          WriteMacInt32(0x134, 0xdeadbeef);
276  
277          // Clear DskErr
278 <        WriteMacInt16(0x142, 0);
278 >        set_dsk_err(0);
279  
280          // Install drives
281 <        for (DriveInfo *info = first_drive_info; info; info = info->next) {
281 >        drive_vec::iterator info, end = drives.end();
282 >        for (info = drives.begin(); info != end; ++info) {
283  
284                  info->num = FindFreeDriveNumber(1);
285                  info->to_be_mounted = false;
# Line 308 | Line 310 | int16 SonyOpen(uint32 pb, uint32 dce)
310                          if (SysIsDiskInserted(info->fh)) {
311                                  WriteMacInt8(info->status + dsDiskInPlace, 1);  // Inserted removable disk
312                                  WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
313 +                                D(bug(" disk inserted, flagging for mount\n"));
314                                  info->to_be_mounted = true;
315                          }
316  
# Line 331 | Line 334 | int16 SonyPrime(uint32 pb, uint32 dce)
334          WriteMacInt32(pb + ioActCount, 0);
335  
336          // Drive valid and disk inserted?
337 <        DriveInfo *info;
338 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
339 <                return nsDrvErr;
337 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
338 >        if (info == drives.end())
339 >                return set_dsk_err(nsDrvErr);
340          if (!ReadMacInt8(info->status + dsDiskInPlace))
341 <                return offLinErr;
341 >                return set_dsk_err(offLinErr);
342          WriteMacInt8(info->status + dsDiskInPlace, 2);  // Disk accessed
343  
344          // Get parameters
# Line 343 | Line 346 | int16 SonyPrime(uint32 pb, uint32 dce)
346          size_t length = ReadMacInt32(pb + ioReqCount);
347          loff_t position = ReadMacInt32(dce + dCtlPosition);
348          if ((length & 0x1ff) || (position & 0x1ff))
349 <                return paramErr;
349 >                return set_dsk_err(paramErr);
350  
351          size_t actual = 0;
352          if ((ReadMacInt16(pb + ioTrap) & 0xff) == aRdCmd) {
# Line 351 | Line 354 | int16 SonyPrime(uint32 pb, uint32 dce)
354                  // Read
355                  actual = Sys_read(info->fh, buffer, position, length);
356                  if (actual != length)
357 <                        return readErr;
357 >                        return set_dsk_err(readErr);
358  
359                  // Clear TagBuf
360                  WriteMacInt32(0x2fc, 0);
# Line 362 | Line 365 | int16 SonyPrime(uint32 pb, uint32 dce)
365  
366                  // Write
367                  if (info->read_only)
368 <                        return wPrErr;
368 >                        return set_dsk_err(wPrErr);
369                  actual = Sys_write(info->fh, buffer, position, length);
370                  if (actual != length)
371 <                        return writErr;
371 >                        return set_dsk_err(writErr);
372          }
373  
374          // Update ParamBlock and DCE
375          WriteMacInt32(pb + ioActCount, actual);
376          WriteMacInt32(dce + dCtlPosition, ReadMacInt32(dce + dCtlPosition) + actual);
377 <        return noErr;
377 >        return set_dsk_err(noErr);
378   }
379  
380  
# Line 387 | Line 390 | int16 SonyControl(uint32 pb, uint32 dce)
390          // General codes
391          switch (code) {
392                  case 1:         // KillIO
393 <                        return -1;
393 >                        return set_dsk_err(-1);
394  
395                  case 9:         // Track cache
396 <                        return noErr;
396 >                        return set_dsk_err(noErr);
397  
398                  case 65:        // Periodic action (accRun, "insert" disks on startup)
399                          mount_mountable_volumes();
# Line 401 | Line 404 | int16 SonyControl(uint32 pb, uint32 dce)
404          }
405  
406          // Drive valid?
407 <        DriveInfo *info;
408 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
409 <                return nsDrvErr;
407 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
408 >        if (info == drives.end())
409 >                return set_dsk_err(nsDrvErr);
410  
411          // Drive-specific codes
412 +        int16 err = noErr;
413          switch (code) {
414                  case 5:         // Verify disk
415 <                        if (ReadMacInt8(info->status + dsDiskInPlace) > 0)
416 <                                return noErr;
417 <                        else
414 <                                return verErr;
415 >                        if (ReadMacInt8(info->status + dsDiskInPlace) <= 0)
416 >                                err = verErr;
417 >                        break;
418  
419                  case 6:         // Format disk
420                          if (info->read_only)
421 <                                return wPrErr;
421 >                                err = wPrErr;
422                          else if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
423 <                                if (SysFormat(info->fh))
424 <                                        return noErr;
422 <                                else
423 <                                        return writErr;
423 >                                if (!SysFormat(info->fh))
424 >                                        err = writErr;
425                          } else
426 <                                return offLinErr;
426 >                                err = offLinErr;
427 >                        break;
428  
429                  case 7:         // Eject
430                          if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
431                                  SysEject(info->fh);
432                                  WriteMacInt8(info->status + dsDiskInPlace, 0);
433                          }
434 <                        return noErr;
434 >                        break;
435  
436                  case 8:         // Set tag buffer
437                          info->tag_buffer = ReadMacInt32(pb + csParam);
438 <                        return noErr;
438 >                        break;
439  
440                  case 21:                // Get drive icon
441                          WriteMacInt32(pb + csParam, SonyDriveIconAddr);
442 <                        return noErr;
442 >                        break;
443  
444                  case 22:                // Get disk icon
445                          WriteMacInt32(pb + csParam, SonyDiskIconAddr);
446 <                        return noErr;
446 >                        break;
447  
448                  case 23:                // Get drive info
449                          if (info->num == 1)
450                                  WriteMacInt32(pb + csParam, 0x0004);    // Internal drive
451                          else
452                                  WriteMacInt32(pb + csParam, 0x0104);    // External drive
453 <                        return noErr;
453 >                        break;
454  
455 <                case 'SC': {    // Format and write to disk
455 >                case 0x5343:    // Format and write to disk ('SC'), used by DiskCopy
456                          if (!ReadMacInt8(info->status + dsDiskInPlace))
457 <                                return offLinErr;
458 <                        if (info->read_only)
459 <                                return wPrErr;
460 <
461 <                        void *data = Mac2HostAddr(ReadMacInt32(pb + csParam + 2));
462 <                        size_t actual = Sys_write(info->fh, data, 0, 2880*512);
463 <                        if (actual != 2880*512)
464 <                                return writErr;
465 <                        else
466 <                                return noErr;
465 <                }
457 >                                err = offLinErr;
458 >                        else if (info->read_only)
459 >                                err = wPrErr;
460 >                        else {
461 >                                void *data = Mac2HostAddr(ReadMacInt32(pb + csParam + 2));
462 >                                size_t actual = Sys_write(info->fh, data, 0, 2880*512);
463 >                                if (actual != 2880*512)
464 >                                        err = writErr;
465 >                        }
466 >                        break;
467  
468                  default:
469                          printf("WARNING: Unknown SonyControl(%d)\n", code);
470 <                        return controlErr;
470 >                        err = controlErr;
471 >                        break;
472          }
473 +
474 +        return set_dsk_err(err);
475   }
476  
477  
# Line 481 | Line 485 | int16 SonyStatus(uint32 pb, uint32 dce)
485          D(bug("SonyStatus %d\n", code));
486  
487          // Drive valid?
488 <        DriveInfo *info;
489 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
490 <                return nsDrvErr;
488 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
489 >        if (info == drives.end())
490 >                return set_dsk_err(nsDrvErr);
491  
492 +        int16 err = noErr;
493          switch (code) {
494                  case 6:         // Return format list
495                          if (ReadMacInt16(pb + csParam) > 0) {
# Line 492 | Line 497 | int16 SonyStatus(uint32 pb, uint32 dce)
497                                  WriteMacInt16(pb + csParam, 1);         // 1 format
498                                  WriteMacInt32(adr, 2880);                       // 2880 sectors
499                                  WriteMacInt32(adr + 4, 0xd2120050);     // 2 heads, 18 secs/track, 80 tracks
495                                return noErr;
500                          } else
501 <                                return paramErr;
501 >                                err = paramErr;
502 >                        break;
503  
504                  case 8:         // Get drive status
505                          Mac2Mac_memcpy(pb + csParam, info->status, 22);
506 <                        return noErr;
506 >                        break;
507  
508                  case 10:        // Get disk type
509                          WriteMacInt32(pb + csParam, ReadMacInt32(info->status + dsMFMDrive) & 0xffffff00 | 0xfe);
510 <                        return noErr;
510 >                        break;
511  
512 <                case 'DV':      // Duplicator version supported
512 >                case 0x4456: // Duplicator version supported ('DV')
513                          WriteMacInt16(pb + csParam, 0x0410);
514 <                        return noErr;
514 >                        break;
515  
516 <                case 'SC':      // Get address header format byte
516 >                case 0x5343: // Get address header format byte ('SC')
517                          WriteMacInt8(pb + csParam, 0x22);       // 512 bytes/sector
518 <                        return noErr;
518 >                        break;
519  
520                  default:
521                          printf("WARNING: Unknown SonyStatus(%d)\n", code);
522 <                        return statusErr;
522 >                        err = statusErr;
523 >                        break;
524          }
525 +
526 +        return set_dsk_err(err);
527   }
528  
529  
530   /*
531 < *  Driver interrupt routine - check for volumes to be mounted
531 > *  Driver interrupt routine (1Hz) - check for volumes to be mounted
532   */
533  
534   void SonyInterrupt(void)
535   {
528        static int tick_count = 0;
536          if (!acc_run_called)
537                  return;
538  
539 <        tick_count++;
533 <        if (tick_count > driver_delay) {
534 <                tick_count = 0;
535 <                mount_mountable_volumes();
536 <        }
539 >        mount_mountable_volumes();
540   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines