home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / sony.cpp < prev    next >
C/C++ Source or Header  |  1999-11-03  |  15KB  |  538 lines

  1. /*
  2.  *  sony.cpp - Replacement .Sony driver (floppy drives)
  3.  *
  4.  *  Basilisk II (C) 1997-1999 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. #ifdef AMIGA
  46. #define DISK_INSERT_CHECK 1        // Check for inserted disks (problem: on most hardware, disks are not ejected and automatically remounted)
  47. #else
  48. #define DISK_INSERT_CHECK 0
  49. #endif
  50.  
  51.  
  52. // Floppy disk icon
  53. const uint8 SonyDiskIcon[258] = {
  54.     0x7f, 0xff, 0xff, 0xf8, 0x81, 0x00, 0x01, 0x04, 0x81, 0x00, 0x71, 0x02, 0x81, 0x00, 0x89, 0x01,
  55.     0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01,
  56.     0x81, 0x00, 0x71, 0x01, 0x81, 0x00, 0x01, 0x01, 0x80, 0xff, 0xfe, 0x01, 0x80, 0x00, 0x00, 0x01,
  57.     0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01,
  58.     0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x87, 0xff, 0xff, 0xe1, 0x88, 0x00, 0x00, 0x11,
  59.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
  60.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
  61.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x7f, 0xff, 0xff, 0xfe,
  62.  
  63.     0x7f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  64.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  65.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 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, 0x7f, 0xff, 0xff, 0xfe,
  71.  
  72.     0, 0
  73. };
  74.  
  75. // Floppy drive icon
  76. const uint8 SonyDriveIcon[258] = {
  77.     0x7f, 0xff, 0xff, 0xf8, 0x81, 0x00, 0x01, 0x04, 0x81, 0x00, 0x71, 0x02, 0x81, 0x00, 0x89, 0x01,
  78.     0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01, 0x81, 0x00, 0x89, 0x01,
  79.     0x81, 0x00, 0x71, 0x01, 0x81, 0x00, 0x01, 0x01, 0x80, 0xff, 0xfe, 0x01, 0x80, 0x00, 0x00, 0x01,
  80.     0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01,
  81.     0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x87, 0xff, 0xff, 0xe1, 0x88, 0x00, 0x00, 0x11,
  82.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
  83.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11,
  84.     0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x88, 0x00, 0x00, 0x11, 0x7f, 0xff, 0xff, 0xfe,
  85.  
  86.     0x7f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
  87.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  88.     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 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, 0x7f, 0xff, 0xff, 0xfe,
  94.  
  95.     0, 0
  96. };
  97.  
  98.  
  99. // Struct for each drive
  100. struct DriveInfo {
  101.     DriveInfo()
  102.     {
  103.         next = NULL;
  104.         num = 0;
  105.         fh = NULL;
  106.         read_only = false;
  107.         status = 0;
  108.     }
  109.  
  110.     DriveInfo *next;    // Pointer to next DriveInfo (must be first in struct!)
  111.     int num;            // Drive number
  112.     void *fh;            // Floppy driver file handle
  113.     bool to_be_mounted;    // Flag: drive must be mounted in accRun
  114.     bool read_only;        // Flag: force write protection
  115.     uint32 tag_buffer;    // Mac address of tag buffer
  116.     uint32 status;        // Mac address of drive status record
  117. };
  118.  
  119. // Linked list of DriveInfos
  120. static DriveInfo *first_drive_info;
  121.  
  122. // Icon addresses (Mac address space, set by PatchROM())
  123. uint32 SonyDiskIconAddr;
  124. uint32 SonyDriveIconAddr;
  125.  
  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
  135.  */
  136.  
  137. static DriveInfo *get_drive_info(int num)
  138. {
  139.     DriveInfo *info = first_drive_info;
  140.     while (info != NULL) {
  141.         if (info->num == num)
  142.             return info;
  143.         info = info->next;
  144.     }
  145.     return NULL;
  146. }
  147.  
  148.  
  149. /*
  150.  *  Initialization
  151.  */
  152.  
  153. void SonyInit(void)
  154. {
  155.     first_drive_info = NULL;
  156.  
  157.     // No drives specified in prefs? Then add defaults
  158.     if (PrefsFindString("floppy", 0) == NULL)
  159.         SysAddFloppyPrefs();
  160.  
  161.     // Add drives specified in preferences
  162.     int32 index = 0;
  163.     const char *str;
  164.     while ((str = PrefsFindString("floppy", index++)) != NULL) {
  165.         bool read_only = false;
  166.         if (str[0] == '*') {
  167.             read_only = true;
  168.             str++;
  169.         }
  170.         void *fh = Sys_open(str, read_only);
  171.         if (fh) {
  172.             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.         }
  180.     }
  181. }
  182.  
  183.  
  184. /*
  185.  *  Deinitialization
  186.  */
  187.  
  188. void SonyExit(void)
  189. {
  190.     DriveInfo *info = first_drive_info, *next;
  191.     while (info != NULL) {
  192.         Sys_close(info->fh);
  193.         next = info->next;
  194.         delete info;
  195.         info = next;
  196.     }
  197. }
  198.  
  199.  
  200. /*
  201.  *  Disk was inserted, flag for mounting
  202.  */
  203.  
  204. bool SonyMountVolume(void *fh)
  205. {
  206.     DriveInfo *info;
  207.     for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
  208.     if (info) {
  209.         if (SysIsDiskInserted(info->fh)) {
  210.             info->read_only = SysIsReadOnly(info->fh);
  211.             WriteMacInt8(info->status + dsDiskInPlace, 1);    // Inserted removable disk
  212.             WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
  213.             info->to_be_mounted = true;
  214.         }
  215.         return true;
  216.     } else
  217.         return false;
  218. }
  219.  
  220.  
  221. /*
  222.  *  Mount volumes for which the to_be_mounted flag is set
  223.  *  (called during interrupt time)
  224.  */
  225.  
  226. static void mount_mountable_volumes(void)
  227. {
  228.     DriveInfo *info = first_drive_info;
  229.     while (info != NULL) {
  230.  
  231. #if DISK_INSERT_CHECK
  232.         // Disk in drive?
  233.         if (!ReadMacInt8(info->status + dsDiskInPlace)) {
  234.  
  235.             // No, check if disk was inserted
  236.             if (SysIsDiskInserted(info->fh))
  237.                 SonyMountVolume(info->fh);
  238.         }
  239. #endif
  240.  
  241.         // Mount disk if flagged
  242.         if (info->to_be_mounted) {
  243.             D(bug(" mounting drive %d\n", info->num));
  244.             M68kRegisters r;
  245.             r.d[0] = info->num;
  246.             r.a[0] = 7;    // diskEvent
  247.             Execute68kTrap(0xa02f, &r);        // PostEvent()
  248.             info->to_be_mounted = false;
  249.         }
  250.  
  251.         info = info->next;
  252.     }
  253. }
  254.  
  255.  
  256. /*
  257.  *  Driver Open() routine
  258.  */
  259.  
  260. int16 SonyOpen(uint32 pb, uint32 dce)
  261. {
  262.     D(bug("SonyOpen\n"));
  263.  
  264.     // Set up DCE
  265.     WriteMacInt32(dce + dCtlPosition, 0);
  266.     WriteMacInt16(dce + dCtlQHdr + qFlags, ReadMacInt16(dce + dCtlQHdr + qFlags) & 0xff00 | 3);    // Version number, must be >=3 or System 8 will replace us
  267.     acc_run_called = false;
  268.  
  269.     // Install driver again with refnum -2 (HD20)
  270.     uint32 utab = ReadMacInt32(0x11c);
  271.     WriteMacInt32(utab + 4, ReadMacInt32(utab + 16));
  272.  
  273.     // Set up fake SonyVars
  274.     WriteMacInt32(0x134, 0xdeadbeef);
  275.  
  276.     // Clear DskErr
  277.     WriteMacInt16(0x142, 0);
  278.  
  279.     // Install drives
  280.     for (DriveInfo *info = first_drive_info; info; info = info->next) {
  281.  
  282.         info->num = FindFreeDriveNumber(1);
  283.         info->to_be_mounted = false;
  284.         info->tag_buffer = 0;
  285.  
  286.         if (info->fh) {
  287.  
  288.             // Allocate drive status record
  289.             M68kRegisters r;
  290.             r.d[0] = SIZEOF_DrvSts;
  291.             Execute68kTrap(0xa71e, &r);        // NewPtrSysClear()
  292.             if (r.a[0] == 0)
  293.                 continue;
  294.             info->status = r.a[0];
  295.             D(bug(" DrvSts at %08lx\n", info->status));
  296.  
  297.             // Set up drive status
  298.             WriteMacInt16(info->status + dsQType, sony);
  299.             WriteMacInt8(info->status + dsInstalled, 1);
  300.             WriteMacInt8(info->status + dsSides, 0xff);
  301.             WriteMacInt8(info->status + dsTwoSideFmt, 0xff);
  302.             WriteMacInt8(info->status + dsNewIntf, 0xff);
  303.             WriteMacInt8(info->status + dsMFMDrive, 0xff);
  304.             WriteMacInt8(info->status + dsMFMDisk, 0xff);
  305.             WriteMacInt8(info->status + dsTwoMegFmt, 0xff);
  306.  
  307.             // Disk in drive?
  308.             if (SysIsDiskInserted(info->fh)) {
  309.                 WriteMacInt8(info->status + dsDiskInPlace, 1);    // Inserted removable disk
  310.                 WriteMacInt8(info->status + dsWriteProt, info->read_only ? 0xff : 0);
  311.                 info->to_be_mounted = true;
  312.             }
  313.  
  314.             // Add drive to drive queue
  315.             D(bug(" adding drive %d\n", info->num));
  316.             r.d[0] = (info->num << 16) | (SonyRefNum & 0xffff);
  317.             r.a[0] = info->status + dsQLink;
  318.             Execute68kTrap(0xa04e, &r);    // AddDrive()
  319.         }
  320.     }
  321.     return noErr;
  322. }
  323.  
  324.  
  325. /*
  326.  *  Driver Prime() routine
  327.  */
  328.  
  329. int16 SonyPrime(uint32 pb, uint32 dce)
  330. {
  331.     WriteMacInt32(pb + ioActCount, 0);
  332.  
  333.     // Drive valid and disk inserted?
  334.     DriveInfo *info;
  335.     if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
  336.         return nsDrvErr;
  337.     if (!ReadMacInt8(info->status + dsDiskInPlace))
  338.         return offLinErr;
  339.     WriteMacInt8(info->status + dsDiskInPlace, 2);    // Disk accessed
  340.  
  341.     // Get parameters
  342.     void *buffer = Mac2HostAddr(ReadMacInt32(pb + ioBuffer));
  343.     size_t length = ReadMacInt32(pb + ioReqCount);
  344.     loff_t position = ReadMacInt32(dce + dCtlPosition);
  345.     if ((length & 0x1ff) || (position & 0x1ff))
  346.         return paramErr;
  347.  
  348.     size_t actual = 0;
  349.     if ((ReadMacInt16(pb + ioTrap) & 0xff) == aRdCmd) {
  350.  
  351.         // Read
  352.         actual = Sys_read(info->fh, buffer, position, length);
  353.         if (actual != length)
  354.             return readErr;
  355.  
  356.         // Clear TagBuf
  357.         WriteMacInt32(0x2fc, 0);
  358.         WriteMacInt32(0x300, 0);
  359.         WriteMacInt32(0x304, 0);
  360.  
  361.     } else {
  362.  
  363.         // Write
  364.         if (info->read_only)
  365.             return wPrErr;
  366.         actual = Sys_write(info->fh, buffer, position, length);
  367.         if (actual != length)
  368.             return writErr;
  369.     }
  370.  
  371.     // Update ParamBlock and DCE
  372.     WriteMacInt32(pb + ioActCount, actual);
  373.     WriteMacInt32(dce + dCtlPosition, ReadMacInt32(dce + dCtlPosition) + actual);
  374.     return noErr;
  375. }
  376.  
  377.  
  378. /*
  379.  *  Driver Control() routine
  380.  */
  381.  
  382. int16 SonyControl(uint32 pb, uint32 dce)
  383. {
  384.     uint16 code = ReadMacInt16(pb + csCode);
  385.     D(bug("SonyControl %d\n", code));
  386.  
  387.     // General codes
  388.     switch (code) {
  389.         case 1:        // KillIO
  390.             return -1;
  391.  
  392.         case 9:        // Track cache
  393.             return noErr;
  394.  
  395.         case 65:    // Periodic action (accRun, "insert" disks on startup)
  396.             mount_mountable_volumes();
  397.             PatchAfterStartup();        // Install patches after system startup
  398.             WriteMacInt16(dce + dCtlFlags, ReadMacInt16(dce + dCtlFlags) & ~0x2000);    // Disable periodic action
  399.             acc_run_called = true;
  400.             return noErr;
  401.     }
  402.  
  403.     // Drive valid?
  404.     DriveInfo *info;
  405.     if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
  406.         return nsDrvErr;
  407.  
  408.     // Drive-specific codes
  409.     switch (code) {
  410.         case 5:        // Verify disk
  411.             if (ReadMacInt8(info->status + dsDiskInPlace) > 0)
  412.                 return noErr;
  413.             else
  414.                 return verErr;
  415.  
  416.         case 6:        // Format disk
  417.             if (info->read_only)
  418.                 return wPrErr;
  419.             else if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
  420.                 if (SysFormat(info->fh))
  421.                     return noErr;
  422.                 else
  423.                     return writErr;
  424.             } else
  425.                 return offLinErr;
  426.  
  427.         case 7:        // Eject
  428.             if (ReadMacInt8(info->status + dsDiskInPlace) > 0) {
  429.                 SysEject(info->fh);
  430.                 WriteMacInt8(info->status + dsDiskInPlace, 0);
  431.             }
  432.             return noErr;
  433.  
  434.         case 8:        // Set tag buffer
  435.             info->tag_buffer = ReadMacInt32(pb + csParam);
  436.             return noErr;
  437.  
  438.         case 21:        // Get drive icon
  439.             WriteMacInt32(pb + csParam, SonyDriveIconAddr);
  440.             return noErr;
  441.  
  442.         case 22:        // Get disk icon
  443.             WriteMacInt32(pb + csParam, SonyDiskIconAddr);
  444.             return noErr;
  445.  
  446.         case 23:        // Get drive info
  447.             if (info->num == 1)
  448.                 WriteMacInt32(pb + csParam, 0x0004);    // Internal drive
  449.             else
  450.                 WriteMacInt32(pb + csParam, 0x0104);    // External drive
  451.             return noErr;
  452.  
  453.         case 'SC': {    // Format and write to disk
  454.             if (!ReadMacInt8(info->status + dsDiskInPlace))
  455.                 return offLinErr;
  456.             if (info->read_only)
  457.                 return wPrErr;
  458.  
  459.             void *data = Mac2HostAddr(ReadMacInt32(pb + csParam + 2));
  460.             size_t actual = Sys_write(info->fh, data, 0, 2880*512);
  461.             if (actual != 2880*512)
  462.                 return writErr;
  463.             else
  464.                 return noErr;
  465.         }
  466.  
  467.         default:
  468.             printf("WARNING: Unknown SonyControl(%d)\n", code);
  469.             return controlErr;
  470.     }
  471. }
  472.  
  473.  
  474. /*
  475.  *  Driver Status() routine
  476.  */
  477.  
  478. int16 SonyStatus(uint32 pb, uint32 dce)
  479. {
  480.     uint16 code = ReadMacInt16(pb + csCode);
  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;
  487.  
  488.     switch (code) {
  489.         case 6:        // Return format list
  490.             if (ReadMacInt16(pb + csParam) > 0) {
  491.                 uint32 adr = ReadMacInt32(pb + csParam + 2);
  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;
  496.             } else
  497.                 return paramErr;
  498.  
  499.         case 8:        // Get drive status
  500.             Mac2Mac_memcpy(pb + csParam, info->status, 22);
  501.             return noErr;
  502.  
  503.         case 10:    // Get disk type
  504.             WriteMacInt32(pb + csParam, ReadMacInt32(info->status + dsMFMDrive) & 0xffffff00 | 0xfe);
  505.             return noErr;
  506.  
  507.         case 'DV':    // Duplicator version supported
  508.             WriteMacInt16(pb + csParam, 0x0410);
  509.             return noErr;
  510.  
  511.         case 'SC':    // Get address header format byte
  512.             WriteMacInt8(pb + csParam, 0x22);    // 512 bytes/sector
  513.             return noErr;
  514.  
  515.         default:
  516.             printf("WARNING: Unknown SonyStatus(%d)\n", code);
  517.             return statusErr;
  518.     }
  519. }
  520.  
  521.  
  522. /*
  523.  *  Driver interrupt routine - check for volumes to be mounted
  524.  */
  525.  
  526. void SonyInterrupt(void)
  527. {
  528.     static int tick_count = 0;
  529.     if (!acc_run_called)
  530.         return;
  531.  
  532.     tick_count++;
  533.     if (tick_count > driver_delay) {
  534.         tick_count = 0;
  535.         mount_mountable_volumes();
  536.     }
  537. }
  538.