home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Utilities / BasiliskII / src / sony.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-10  |  14.7 KB  |  548 lines

  1. /*
  2.  *  sony.cpp - Replacement .Sony driver (floppy drives)
  3.  *
  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
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. /*
  22.  *  SEE ALSO
  23.  *    Inside Macintosh: Devices, chapter 1 "Device Manager"
  24.  *    Technote DV 05: "Drive Queue Elements"
  25.  *    Technote DV 07: "Forcing Floppy Disk Size to be Either 400K or 800K"
  26.  *    Technote DV 17: "Sony Driver: What Your Sony Drives For You"
  27.  *    Technote DV 23: "Driver Education"
  28.  *    Technote FL 24: "Don't Look at ioPosOffset for Devices"
  29.  */
  30.  
  31. #include <string.h>
  32.  
  33. #include "sysdeps.h"
  34. #include "cpu_emulation.h"
  35. #include "main.h"
  36. #include "macos_util.h"
  37. #include "rom_patches.h"
  38. #include "sys.h"
  39. #include "prefs.h"
  40. #include "sony.h"
  41.  
  42. #define DEBUG 0
  43. #include "debug.h"
  44.  
  45.  
  46. // Check for inserted disks by polling?
  47. #ifdef AMIGA
  48. #define DISK_INSERT_CHECK 1
  49. #else
  50. #define DISK_INSERT_CHECK 0
  51. #endif
  52.  
  53.  
  54. // Floppy disk icon
  55. const uint8 SonyDiskIcon[258] = {
  56.     0x7f, 0xff, 0xff, 0xf8, 0x81, 0x00, 0x01, 0x04, 0x81, 0x00, 0x71, 0x02, 0x81, 0x00, 0x89, 0x01,
  57.     0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01,
  58.     0x81, 0x00, 0x71, 0x01, 0x81, 0x00, 0x01, 0x01, 0x80, 0xff, 0xfe, 0x01, 0x80, 0x00, 0x00, 0x01,
  59.     0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01,
  60.     0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x87, 0xff, 0xff, 0xe1, 0x88, 0x00, 0x00, 0x11,
  61.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
  62.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
  63.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x7f, 0xff, 0xff, 0xfe,
  64.  
  65.     0x7f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  66.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  67.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  68.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  69.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  70.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  71.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  72.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfe,
  73.  
  74.     0, 0
  75. };
  76.  
  77. // Floppy drive icon
  78. const uint8 SonyDriveIcon[258] = {
  79.     0x7f, 0xff, 0xff, 0xf8, 0x81, 0x00, 0x01, 0x04, 0x81, 0x00, 0x71, 0x02, 0x81, 0x00, 0x89, 0x01,
  80.     0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01,
  81.     0x81, 0x00, 0x71, 0x01, 0x81, 0x00, 0x01, 0x01, 0x80, 0xff, 0xfe, 0x01, 0x80, 0x00, 0x00, 0x01,
  82.     0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01,
  83.     0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x87, 0xff, 0xff, 0xe1, 0x88, 0x00, 0x00, 0x11,
  84.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
  85.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
  86.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x7f, 0xff, 0xff, 0xfe,
  87.  
  88.     0x7f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  89.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  90.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  91.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  92.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  93.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  94.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  95.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfe,
  96.  
  97.     0, 0
  98. };
  99.  
  100.  
  101. // Struct for each drive
  102. struct DriveInfo {
  103.     DriveInfo()
  104.     {
  105.         next = NULL;
  106.         num = 0;
  107.         fh = NULL;
  108.         read_only = false;
  109.         status = 0;
  110.     }
  111.  
  112.     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
  116.     bool read_only;        // Flag: force write protection
  117.     uint32 tag_buffer;    // Mac address of tag buffer
  118.     uint32 status;        // Mac address of drive status record
  119. };
  120.  
  121. // Linked list of DriveInfos
  122. static DriveInfo *first_drive_info;
  123.  
  124. // Icon addresses (Mac address space, set by PatchROM())
  125. uint32 SonyDiskIconAddr;
  126. uint32 SonyDriveIconAddr;
  127.  
  128. // Flag: Control(accRun) has been called, interrupt routine is now active
  129. static bool acc_run_called = false;
  130.  
  131.  
  132. /*
  133.  *  Get pointer to drive info, NULL = invalid drive number
  134.  */
  135.  
  136. static DriveInfo *get_drive_info(int num)
  137. {
  138.     DriveInfo *info = first_drive_info;
  139.     while (info != NULL) {
  140.         if (info->num == num)
  141.             return info;
  142.         info = info->next;
  143.     }
  144.     return NULL;
  145. }
  146.  
  147.  
  148. /*
  149.  *  Initialization
  150.  */
  151.  
  152. void SonyInit(void)
  153. {
  154.     first_drive_info = NULL;
  155.  
  156.     // No drives specified in prefs? Then add defaults
  157.     if (PrefsFindString("floppy", 0) == NULL)
  158.         SysAddFloppyPrefs();
  159.  
  160.     // Add drives specified in preferences
  161.     int32 index = 0;
  162.     const char *str;
  163.     while ((str = PrefsFindString("floppy", index++)) != NULL) {
  164.         bool read_only = false;
  165.         if (str[0] == '*') {
  166.             read_only = true;
  167.             str++;
  168.         }
  169.         void *fh = Sys_open(str, read_only);
  170.         if (fh) {
  171.             DriveInfo *info = new DriveInfo;
  172.             info->fh = fh;
  173.             info->read_only = SysIsReadOnly(fh);
  174.             DriveInfo *p = (DriveInfo *)&first_drive_info;
  175.             while (p->next != NULL)
  176.                 p = p->next;
  177.             p->next = info;
  178.         }
  179.     }
  180. }
  181.  
  182.  
  183. /*
  184.  *  Deinitialization
  185.  */
  186.  
  187. void SonyExit(void)
  188. {
  189.     DriveInfo *info = first_drive_info, *next;
  190.     while (info != NULL) {
  191.         Sys_close(info->fh);
  192.         next = info->next;
  193.         delete info;
  194.         info = next;
  195.     }
  196. }
  197.  
  198.  
  199. /*
  200.  *  Disk was inserted, flag for mounting
  201.  */
  202.  
  203. bool SonyMountVolume(void *fh)
  204. {
  205.     DriveInfo *info;
  206.     for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
  207.     if (info) {
  208.         if (SysIsDiskInserted(info->fh)) {
  209.             info->read_only = SysIsReadOnly(info->fh);
  210.             WriteMacInt8(info->status + dsDiskInPlace, 1);    // Inserted removable disk
  211.             WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
  212.             info->to_be_mounted = true;
  213.         }
  214.         return true;
  215.     } else
  216.         return false;
  217. }
  218.  
  219.  
  220. /*
  221.  *  Mount volumes for which the to_be_mounted flag is set
  222.  *  (called during interrupt time)
  223.  */
  224.  
  225. static void mount_mountable_volumes(void)
  226. {
  227.     DriveInfo *info = first_drive_info;
  228.     while (info != NULL) {
  229.  
  230. #if DISK_INSERT_CHECK
  231.         // Disk in drive?
  232.         if (!ReadMacInt8(info->status + dsDiskInPlace)) {
  233.  
  234.             // No, check if disk was inserted
  235.             if (SysIsDiskInserted(info->fh))
  236.                 SonyMountVolume(info->fh);
  237.         }
  238. #endif
  239.  
  240.         // Mount disk if flagged
  241.         if (info->to_be_mounted) {
  242.             D(bug(" mounting drive %d\n", info->num));
  243.             M68kRegisters r;
  244.             r.d[0] = info->num;
  245.             r.a[0] = 7;    // diskEvent
  246.             Execute68kTrap(0xa02f, &r);        // PostEvent()
  247.             info->to_be_mounted = false;
  248.         }
  249.  
  250.         info = info->next;
  251.     }
  252. }
  253.  
  254.  
  255. /*
  256.  *  Set error code in DskErr
  257.  */
  258.  
  259. static int16 set_dsk_err(int16 err)
  260. {
  261.     WriteMacInt16(0x142, err);
  262.     return err;
  263. }
  264.  
  265.  
  266. /*
  267.  *  Driver Open() routine
  268.  */
  269.  
  270. int16 SonyOpen(uint32 pb, uint32 dce)
  271. {
  272.     D(bug("SonyOpen\n"));
  273.  
  274.     // Set up DCE
  275.     WriteMacInt32(dce + dCtlPosition, 0);
  276.     WriteMacInt16(dce + dCtlQHdr + qFlags, ReadMacInt16(dce + dCtlQHdr + qFlags) & 0xff00 | 3);    // Version number, must be >=3 or System 8 will replace us
  277.     acc_run_called = false;
  278.  
  279.     // Install driver again with refnum -2 (HD20)
  280.     uint32 utab = ReadMacInt32(0x11c);
  281.     WriteMacInt32(utab + 4, ReadMacInt32(utab + 16));
  282.  
  283.     // Set up fake SonyVars
  284.     WriteMacInt32(0x134, 0xdeadbeef);
  285.  
  286.     // Clear DskErr
  287.     set_dsk_err(0);
  288.  
  289.     // Install drives
  290.     for (DriveInfo *info = first_drive_info; info; info = info->next) {
  291.  
  292.         info->num = FindFreeDriveNumber(1);
  293.         info->to_be_mounted = false;
  294.         info->tag_buffer = 0;
  295.  
  296.         if (info->fh) {
  297.  
  298.             // Allocate drive status record
  299.             M68kRegisters r;
  300.             r.d[0] = SIZEOF_DrvSts;
  301.             Execute68kTrap(0xa71e, &r);        // NewPtrSysClear()
  302.             if (r.a[0] == 0)
  303.                 continue;
  304.             info->status = r.a[0];
  305.             D(bug(" DrvSts at %08lx\n", info->status));
  306.  
  307.             // Set up drive status
  308.             WriteMacInt16(info->status + dsQType, sony);
  309.             WriteMacInt8(info->status + dsInstalled, 1);
  310.             WriteMacInt8(info->status + dsSides, 0xff);
  311.             WriteMacInt8(info->status + dsTwoSideFmt, 0xff);
  312.             WriteMacInt8(info->status + dsNewIntf, 0xff);
  313.             WriteMacInt8(info->status + dsMFMDrive, 0xff);
  314.             WriteMacInt8(info->status + dsMFMDisk, 0xff);
  315.             WriteMacInt8(info->status + dsTwoMegFmt, 0xff);
  316.  
  317.             // Disk in drive?
  318.             if (SysIsDiskInserted(info->fh)) {
  319.                 WriteMacInt8(info->status + dsDiskInPlace, 1);    // Inserted removable disk
  320.                 WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
  321.                 info->to_be_mounted = true;
  322.             }
  323.  
  324.             // Add drive to drive queue
  325.             D(bug(" adding drive %d\n", info->num));
  326.             r.d[0] = (info->num << 16) | (SonyRefNum & 0xffff);
  327.             r.a[0] = info->status + dsQLink;
  328.             Execute68kTrap(0xa04e, &r);    // AddDrive()
  329.         }
  330.     }
  331.     return noErr;
  332. }
  333.  
  334.  
  335. /*
  336.  *  Driver Prime() routine
  337.  */
  338.  
  339. int16 SonyPrime(uint32 pb, uint32 dce)
  340. {
  341.     WriteMacInt32(pb + ioActCount, 0);
  342.  
  343.     // Drive valid and disk inserted?
  344.     DriveInfo *info;
  345.     if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
  346.         return set_dsk_err(nsDrvErr);
  347.     if (!ReadMacInt8(info->status + dsDiskInPlace))
  348.         return set_dsk_err(offLinErr);
  349.     WriteMacInt8(info->status + dsDiskInPlace, 2);    // Disk accessed
  350.  
  351.     // Get parameters
  352.     void *buffer = Mac2HostAddr(ReadMacInt32(pb + ioBuffer));
  353.     size_t length = ReadMacInt32(pb + ioReqCount);
  354.     loff_t position = ReadMacInt32(dce + dCtlPosition);
  355.     if ((length & 0x1ff) || (position & 0x1ff))
  356.         return set_dsk_err(paramErr);
  357.  
  358.     size_t actual = 0;
  359.     if ((ReadMacInt16(pb + ioTrap) & 0xff) == aRdCmd) {
  360.  
  361.         // Read
  362.         actual = Sys_read(info->fh, buffer, position, length);
  363.         if (actual != length)
  364.             return set_dsk_err(readErr);
  365.  
  366.         // Clear TagBuf
  367.         WriteMacInt32(0x2fc, 0);
  368.         WriteMacInt32(0x300, 0);
  369.         WriteMacInt32(0x304, 0);
  370.  
  371.     } else {
  372.  
  373.         // Write
  374.         if (info->read_only)
  375.             return set_dsk_err(wPrErr);
  376.         actual = Sys_write(info->fh, buffer, position, length);
  377.         if (actual != length)
  378.             return set_dsk_err(writErr);
  379.     }
  380.  
  381.     // Update ParamBlock and DCE
  382.     WriteMacInt32(pb + ioActCount, actual);
  383.     WriteMacInt32(dce + dCtlPosition, ReadMacInt32(dce + dCtlPosition) + actual);
  384.     return set_dsk_err(noErr);
  385. }
  386.  
  387.  
  388. /*
  389.  *  Driver Control() routine
  390.  */
  391.  
  392. int16 SonyControl(uint32 pb, uint32 dce)
  393. {
  394.     uint16 code = ReadMacInt16(pb + csCode);
  395.     D(bug("SonyControl %d\n", code));
  396.  
  397.     // General codes
  398.     switch (code) {
  399.         case 1:        // KillIO
  400.             return set_dsk_err(-1);
  401.  
  402.         case 9:        // Track cache
  403.             return set_dsk_err(noErr);
  404.  
  405.         case 65:    // Periodic action (accRun, "insert" disks on startup)
  406.             mount_mountable_volumes();
  407.             PatchAfterStartup();        // Install patches after system startup
  408.             WriteMacInt16(dce + dCtlFlags, ReadMacInt16(dce + dCtlFlags) & ~0x2000);    // Disable periodic action
  409.             acc_run_called = true;
  410.             return noErr;
  411.     }
  412.  
  413.     // Drive valid?
  414.     DriveInfo *info;
  415.     if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
  416.         return set_dsk_err(nsDrvErr);
  417.  
  418.     // Drive-specific codes
  419.     int16 err = noErr;
  420.     switch (code) {
  421.         case 5:        // Verify disk
  422.             if (ReadMacInt8(info->status + dsDiskInPlace) <= 0)
  423.                 err = verErr;
  424.             break;
  425.  
  426.         case 6:        // Format disk
  427.             if (info->read_only)
  428.                 err = wPrErr;
  429.             else if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
  430.                 if (!SysFormat(info->fh))
  431.                     err = writErr;
  432.             } else
  433.                 err = offLinErr;
  434.             break;
  435.  
  436.         case 7:        // Eject
  437.             if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
  438.                 SysEject(info->fh);
  439.                 WriteMacInt8(info->status + dsDiskInPlace, 0);
  440.             }
  441.             break;
  442.  
  443.         case 8:        // Set tag buffer
  444.             info->tag_buffer = ReadMacInt32(pb + csParam);
  445.             break;
  446.  
  447.         case 21:        // Get drive icon
  448.             WriteMacInt32(pb + csParam, SonyDriveIconAddr);
  449.             break;
  450.  
  451.         case 22:        // Get disk icon
  452.             WriteMacInt32(pb + csParam, SonyDiskIconAddr);
  453.             break;
  454.  
  455.         case 23:        // Get drive info
  456.             if (info->num == 1)
  457.                 WriteMacInt32(pb + csParam, 0x0004);    // Internal drive
  458.             else
  459.                 WriteMacInt32(pb + csParam, 0x0104);    // External drive
  460.             break;
  461.  
  462.         case 0x5343:    // Format and write to disk ('SC'), used by DiskCopy
  463.             if (!ReadMacInt8(info->status + dsDiskInPlace))
  464.                 err = offLinErr;
  465.             else if (info->read_only)
  466.                 err = wPrErr;
  467.             else {
  468.                 void *data = Mac2HostAddr(ReadMacInt32(pb + csParam + 2));
  469.                 size_t actual = Sys_write(info->fh, data, 0, 2880*512);
  470.                 if (actual != 2880*512)
  471.                     err = writErr;
  472.             }
  473.             break;
  474.  
  475.         default:
  476.             printf("WARNING: Unknown SonyControl(%d)\n", code);
  477.             err = controlErr;
  478.             break;
  479.     }
  480.  
  481.     return set_dsk_err(err);
  482. }
  483.  
  484.  
  485. /*
  486.  *  Driver Status() routine
  487.  */
  488.  
  489. int16 SonyStatus(uint32 pb, uint32 dce)
  490. {
  491.     uint16 code = ReadMacInt16(pb + csCode);
  492.     D(bug("SonyStatus %d\n", code));
  493.  
  494.     // Drive valid?
  495.     DriveInfo *info;
  496.     if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
  497.         return set_dsk_err(nsDrvErr);
  498.  
  499.     int16 err = noErr;
  500.     switch (code) {
  501.         case 6:        // Return format list
  502.             if (ReadMacInt16(pb + csParam) > 0) {
  503.                 uint32 adr = ReadMacInt32(pb + csParam + 2);
  504.                 WriteMacInt16(pb + csParam, 1);        // 1 format
  505.                 WriteMacInt32(adr, 2880);            // 2880 sectors
  506.                 WriteMacInt32(adr + 4, 0xd2120050);    // 2 heads, 18 secs/track, 80 tracks
  507.             } else
  508.                 err = paramErr;
  509.             break;
  510.  
  511.         case 8:        // Get drive status
  512.             Mac2Mac_memcpy(pb + csParam, info->status, 22);
  513.             break;
  514.  
  515.         case 10:    // Get disk type
  516.             WriteMacInt32(pb + csParam, ReadMacInt32(info->status + dsMFMDrive) & 0xffffff00 | 0xfe);
  517.             break;
  518.  
  519.         case 0x4456: // Duplicator version supported ('DV')
  520.             WriteMacInt16(pb + csParam, 0x0410);
  521.             break;
  522.  
  523.         case 0x5343: // Get address header format byte ('SC')
  524.             WriteMacInt8(pb + csParam, 0x22);    // 512 bytes/sector
  525.             break;
  526.  
  527.         default:
  528.             printf("WARNING: Unknown SonyStatus(%d)\n", code);
  529.             err = statusErr;
  530.             break;
  531.     }
  532.  
  533.     return set_dsk_err(err);
  534. }
  535.  
  536.  
  537. /*
  538.  *  Driver interrupt routine (1Hz) - check for volumes to be mounted
  539.  */
  540.  
  541. void SonyInterrupt(void)
  542. {
  543.     if (!acc_run_called)
  544.         return;
  545.  
  546.     mount_mountable_volumes();
  547. }
  548.