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.12 by cebix, 2001-07-15T14:19:06Z

# 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 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  
130 < // Flag: accRun called for the first time, run PatchAfterStartup()
131 < static bool periodic_first_time = false;
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;
140                info = info->next;
144          }
145 <        return NULL;
145 >        return info;
146   }
147  
148  
# Line 149 | Line 152 | static DriveInfo *get_drive_info(int num
152  
153   void SonyInit(void)
154   {
152        first_drive_info = NULL;
153
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 165 | Line 166 | void SonyInit(void)
166                          str++;
167                  }
168                  void *fh = Sys_open(str, read_only);
169 <                if (fh) {
170 <                        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 <                }
169 >                if (fh)
170 >                        drives.push_back(sony_drive_info(fh, SysIsReadOnly(fh)));
171          }
172   }
173  
# Line 184 | 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;
191 <                delete info;
192 <                info = next;
193 <        }
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 200 | 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                  if (SysIsDiskInserted(info->fh)) {
199                          info->read_only = SysIsReadOnly(info->fh);
200                          WriteMacInt8(info->status + dsDiskInPlace, 1);  // Inserted removable disk
# Line 216 | Line 208 | bool SonyMountVolume(void *fh)
208  
209  
210   /*
211 + *  Mount volumes for which the to_be_mounted flag is set
212 + *  (called during interrupt time)
213 + */
214 +
215 + static void mount_mountable_volumes(void)
216 + {
217 +        drive_vec::iterator info, end = drives.end();
218 +        for (info = drives.begin(); info != end; ++info) {
219 +
220 + #if DISK_INSERT_CHECK
221 +                // Disk in drive?
222 +                if (!ReadMacInt8(info->status + dsDiskInPlace)) {
223 +
224 +                        // No, check if disk was inserted
225 +                        if (SysIsDiskInserted(info->fh))
226 +                                SonyMountVolume(info->fh);
227 +                }
228 + #endif
229 +
230 +                // Mount disk if flagged
231 +                if (info->to_be_mounted) {
232 +                        D(bug(" mounting drive %d\n", info->num));
233 +                        M68kRegisters r;
234 +                        r.d[0] = info->num;
235 +                        r.a[0] = 7;     // diskEvent
236 +                        Execute68kTrap(0xa02f, &r);             // PostEvent()
237 +                        info->to_be_mounted = false;
238 +                }
239 +        }
240 + }
241 +
242 +
243 + /*
244 + *  Set error code in DskErr
245 + */
246 +
247 + static int16 set_dsk_err(int16 err)
248 + {
249 +        WriteMacInt16(0x142, err);
250 +        return err;
251 + }
252 +
253 +
254 + /*
255   *  Driver Open() routine
256   */
257  
# Line 226 | Line 262 | int16 SonyOpen(uint32 pb, uint32 dce)
262          // Set up DCE
263          WriteMacInt32(dce + dCtlPosition, 0);
264          WriteMacInt16(dce + dCtlQHdr + qFlags, ReadMacInt16(dce + dCtlQHdr + qFlags) & 0xff00 | 3);     // Version number, must be >=3 or System 8 will replace us
265 <        periodic_first_time = true;
265 >        acc_run_called = false;
266  
267          // Install driver again with refnum -2 (HD20)
268          uint32 utab = ReadMacInt32(0x11c);
# Line 236 | Line 272 | int16 SonyOpen(uint32 pb, uint32 dce)
272          WriteMacInt32(0x134, 0xdeadbeef);
273  
274          // Clear DskErr
275 <        WriteMacInt16(0x142, 0);
275 >        set_dsk_err(0);
276  
277          // Install drives
278 <        for (DriveInfo *info = first_drive_info; info; info = info->next) {
278 >        drive_vec::iterator info, end = drives.end();
279 >        for (info = drives.begin(); info != end; ++info) {
280  
281                  info->num = FindFreeDriveNumber(1);
282                  info->to_be_mounted = false;
# Line 293 | Line 330 | int16 SonyPrime(uint32 pb, uint32 dce)
330          WriteMacInt32(pb + ioActCount, 0);
331  
332          // Drive valid and disk inserted?
333 <        DriveInfo *info;
334 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
335 <                return nsDrvErr;
333 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
334 >        if (info == drives.end())
335 >                return set_dsk_err(nsDrvErr);
336          if (!ReadMacInt8(info->status + dsDiskInPlace))
337 <                return offLinErr;
337 >                return set_dsk_err(offLinErr);
338          WriteMacInt8(info->status + dsDiskInPlace, 2);  // Disk accessed
339  
340          // Get parameters
# Line 305 | Line 342 | int16 SonyPrime(uint32 pb, uint32 dce)
342          size_t length = ReadMacInt32(pb + ioReqCount);
343          loff_t position = ReadMacInt32(dce + dCtlPosition);
344          if ((length & 0x1ff) || (position & 0x1ff))
345 <                return paramErr;
345 >                return set_dsk_err(paramErr);
346  
347          size_t actual = 0;
348          if ((ReadMacInt16(pb + ioTrap) & 0xff) == aRdCmd) {
# Line 313 | Line 350 | int16 SonyPrime(uint32 pb, uint32 dce)
350                  // Read
351                  actual = Sys_read(info->fh, buffer, position, length);
352                  if (actual != length)
353 <                        return readErr;
353 >                        return set_dsk_err(readErr);
354  
355                  // Clear TagBuf
356                  WriteMacInt32(0x2fc, 0);
# Line 324 | Line 361 | int16 SonyPrime(uint32 pb, uint32 dce)
361  
362                  // Write
363                  if (info->read_only)
364 <                        return wPrErr;
364 >                        return set_dsk_err(wPrErr);
365                  actual = Sys_write(info->fh, buffer, position, length);
366                  if (actual != length)
367 <                        return writErr;
367 >                        return set_dsk_err(writErr);
368          }
369  
370          // Update ParamBlock and DCE
371          WriteMacInt32(pb + ioActCount, actual);
372          WriteMacInt32(dce + dCtlPosition, ReadMacInt32(dce + dCtlPosition) + actual);
373 <        return noErr;
373 >        return set_dsk_err(noErr);
374   }
375  
376  
# Line 349 | Line 386 | int16 SonyControl(uint32 pb, uint32 dce)
386          // General codes
387          switch (code) {
388                  case 1:         // KillIO
389 <                        return -1;
389 >                        return set_dsk_err(-1);
390  
391                  case 9:         // Track cache
392 <                        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) {
360 <
361 <                                // Disk in drive?
362 <                                if (!ReadMacInt8(info->status + dsDiskInPlace)) {
392 >                        return set_dsk_err(noErr);
393  
394 < #if DISK_INSERT_CHECK
395 <                                        // No, check if disk was inserted
396 <                                        if (SysIsDiskInserted(info->fh))
397 <                                                SonyMountVolume(info->fh);
398 < #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 <                        }
394 >                case 65:        // Periodic action (accRun, "insert" disks on startup)
395 >                        mount_mountable_volumes();
396 >                        PatchAfterStartup();            // Install patches after system startup
397 >                        WriteMacInt16(dce + dCtlFlags, ReadMacInt16(dce + dCtlFlags) & ~0x2000);        // Disable periodic action
398 >                        acc_run_called = true;
399                          return noErr;
388                }
400          }
401  
402          // Drive valid?
403 <        DriveInfo *info;
404 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
405 <                return nsDrvErr;
403 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
404 >        if (info == drives.end())
405 >                return set_dsk_err(nsDrvErr);
406  
407          // Drive-specific codes
408 +        int16 err = noErr;
409          switch (code) {
410                  case 5:         // Verify disk
411 <                        if (ReadMacInt8(info->status + dsDiskInPlace) > 0)
412 <                                return noErr;
413 <                        else
402 <                                return verErr;
411 >                        if (ReadMacInt8(info->status + dsDiskInPlace) <= 0)
412 >                                err = verErr;
413 >                        break;
414  
415                  case 6:         // Format disk
416                          if (info->read_only)
417 <                                return wPrErr;
417 >                                err = wPrErr;
418                          else if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
419 <                                if (SysFormat(info->fh))
420 <                                        return noErr;
410 <                                else
411 <                                        return writErr;
419 >                                if (!SysFormat(info->fh))
420 >                                        err = writErr;
421                          } else
422 <                                return offLinErr;
422 >                                err = offLinErr;
423 >                        break;
424  
425                  case 7:         // Eject
426                          if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
427                                  SysEject(info->fh);
428                                  WriteMacInt8(info->status + dsDiskInPlace, 0);
429                          }
430 <                        return noErr;
430 >                        break;
431  
432                  case 8:         // Set tag buffer
433                          info->tag_buffer = ReadMacInt32(pb + csParam);
434 <                        return noErr;
434 >                        break;
435  
436                  case 21:                // Get drive icon
437                          WriteMacInt32(pb + csParam, SonyDriveIconAddr);
438 <                        return noErr;
438 >                        break;
439  
440                  case 22:                // Get disk icon
441                          WriteMacInt32(pb + csParam, SonyDiskIconAddr);
442 <                        return noErr;
442 >                        break;
443  
444                  case 23:                // Get drive info
445                          if (info->num == 1)
446                                  WriteMacInt32(pb + csParam, 0x0004);    // Internal drive
447                          else
448                                  WriteMacInt32(pb + csParam, 0x0104);    // External drive
449 <                        return noErr;
449 >                        break;
450  
451 <                case 'SC': {    // Format and write to disk
451 >                case 0x5343:    // Format and write to disk ('SC'), used by DiskCopy
452                          if (!ReadMacInt8(info->status + dsDiskInPlace))
453 <                                return offLinErr;
454 <                        if (info->read_only)
455 <                                return wPrErr;
456 <
457 <                        void *data = Mac2HostAddr(ReadMacInt32(pb + csParam + 2));
458 <                        size_t actual = Sys_write(info->fh, data, 0, 2880*512);
459 <                        if (actual != 2880*512)
460 <                                return writErr;
461 <                        else
462 <                                return noErr;
453 <                }
453 >                                err = offLinErr;
454 >                        else if (info->read_only)
455 >                                err = wPrErr;
456 >                        else {
457 >                                void *data = Mac2HostAddr(ReadMacInt32(pb + csParam + 2));
458 >                                size_t actual = Sys_write(info->fh, data, 0, 2880*512);
459 >                                if (actual != 2880*512)
460 >                                        err = writErr;
461 >                        }
462 >                        break;
463  
464                  default:
465                          printf("WARNING: Unknown SonyControl(%d)\n", code);
466 <                        return controlErr;
466 >                        err = controlErr;
467 >                        break;
468          }
469 +
470 +        return set_dsk_err(err);
471   }
472  
473  
# Line 469 | Line 481 | int16 SonyStatus(uint32 pb, uint32 dce)
481          D(bug("SonyStatus %d\n", code));
482  
483          // Drive valid?
484 <        DriveInfo *info;
485 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
486 <                return nsDrvErr;
484 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
485 >        if (info == drives.end())
486 >                return set_dsk_err(nsDrvErr);
487  
488 +        int16 err = noErr;
489          switch (code) {
490                  case 6:         // Return format list
491                          if (ReadMacInt16(pb + csParam) > 0) {
# Line 480 | Line 493 | int16 SonyStatus(uint32 pb, uint32 dce)
493                                  WriteMacInt16(pb + csParam, 1);         // 1 format
494                                  WriteMacInt32(adr, 2880);                       // 2880 sectors
495                                  WriteMacInt32(adr + 4, 0xd2120050);     // 2 heads, 18 secs/track, 80 tracks
483                                return noErr;
496                          } else
497 <                                return paramErr;
497 >                                err = paramErr;
498 >                        break;
499  
500                  case 8:         // Get drive status
501 <                        memcpy(Mac2HostAddr(pb + csParam), Mac2HostAddr(info->status), 22);
502 <                        return noErr;
501 >                        Mac2Mac_memcpy(pb + csParam, info->status, 22);
502 >                        break;
503  
504                  case 10:        // Get disk type
505                          WriteMacInt32(pb + csParam, ReadMacInt32(info->status + dsMFMDrive) & 0xffffff00 | 0xfe);
506 <                        return noErr;
506 >                        break;
507  
508 <                case 'DV':      // Duplicator version supported
508 >                case 0x4456: // Duplicator version supported ('DV')
509                          WriteMacInt16(pb + csParam, 0x0410);
510 <                        return noErr;
510 >                        break;
511  
512 <                case 'SC':      // Get address header format byte
512 >                case 0x5343: // Get address header format byte ('SC')
513                          WriteMacInt8(pb + csParam, 0x22);       // 512 bytes/sector
514 <                        return noErr;
514 >                        break;
515  
516                  default:
517                          printf("WARNING: Unknown SonyStatus(%d)\n", code);
518 <                        return statusErr;
518 >                        err = statusErr;
519 >                        break;
520          }
521 +
522 +        return set_dsk_err(err);
523 + }
524 +
525 +
526 + /*
527 + *  Driver interrupt routine (1Hz) - check for volumes to be mounted
528 + */
529 +
530 + void SonyInterrupt(void)
531 + {
532 +        if (!acc_run_called)
533 +                return;
534 +
535 +        mount_mountable_volumes();
536   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines