home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / Modules / dsr_realdisk.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  18.5 KB  |  871 lines

  1. #include <fcntl.h>
  2. #include <stdio.h>
  3. #include <errno.h>
  4.  
  5. #include "v9t9_common.h"
  6. #include "v9t9.h"
  7. #include "roms.h"
  8. #include "cru.h"
  9. #include "command.h"
  10.  
  11. #include "memory.h"
  12. #include "dsr.h"
  13.  
  14. char        realdiskfilename[OS_NAMESIZE] = "disk.bin";
  15. u8          realdiskdsr[8192];
  16. char        diskname[3][OS_NAMESIZE] =
  17.     { "disk0001.dsk", "disk0002.dsk", "disk0003.dsk" };
  18. char       *diskimagepath = NULL;
  19.  
  20. #define _L    LOG_REALDISK | LOG_INFO
  21. #define _LS    LOG_REALDISK | LOG_INFO | LOG_USER
  22.  
  23. #define DSKbuffersize (256*18)    /* maximum track size */
  24.  
  25. #if BEWORKS_FS
  26.      OSFileType  osDiskImageType = { 0666, "x/v9t9-disk-image" };
  27. #elif POSIX_FS
  28.      OSFileType  osDiskImageType = { 0666 };
  29. #elif WIN32_FS
  30.      OSFileType  osDiskImageType = 0;
  31. #elif MAC_FS
  32.      OSFileType  osDiskImageType = 'DI99';
  33. #endif
  34.  
  35. typedef struct DSKInfo
  36. {
  37.     u8   num;        /* current drive #1-3 */
  38.     u8   hold;        /* holding for data? */
  39.     u8   lastbyte;    /* last byte written to WDDATA */
  40.     u8   buffer[DSKbuffersize];    /* buffered I/O */
  41.     u32  buflen;        /* internal use only, max len */
  42.     u32  bufpos;        /* buffer is only a window */
  43.     u32  written;    /* how much written? */
  44.  
  45.     OSRef handle;    /* file descriptor for disk */
  46.     u8   density;    /* density, 9 or 18 */
  47.     u8   tracksside;    /* # tracks per side */
  48.  
  49. //       u8  trackoffset;     /* last seeked track */
  50.     u32  tracksize;    /* max # bytes in a size, set by opendisk */
  51.     u32  trackbyteoffset;    /* offset into track, bytes */
  52.  
  53.     u8   command;    /* command being executed */
  54.     u8   track;        /* current track */
  55.     u8   sector;        /* current sector */
  56.     u8   side;        /* current side */
  57.     u8   status;        /* current status */
  58.  
  59.     u8   formatsaving;    /* are we saving data in a format? */
  60.     u8   postponed;    /* waiting for input */
  61. }    DSKInfo;
  62.  
  63. DSKInfo    DSK;
  64.  
  65. #define FDC_seekhome    ((~0xf5)&0xff)
  66. #define FDC_seek        ((~0xe1)&0xff)
  67. #define FDC_stepin        ((~0xa5)&0xff)
  68. #define FDC_readsector    ((~0x77)&0xff)
  69. #define FDC_writesector    ((~0x57)&0xff)
  70. #define FDC_readIDmarker ((~0x3f)&0xff)
  71. #define FDC_interrupt    ((~0x2f)&0xff)
  72. #define FDC_formattrack ((~0x0b)&0xff)
  73.  
  74. #define fdc_READY        0x80
  75. #define fdc_WRITEPORT    0x40
  76. #define fdc_BADRECORD    0x10
  77. #define fdc_CRCERR        0x08
  78. #define    fdc_LOSTDATA    0x04
  79. #define    fdc_TRACK0        0x04
  80. #define    fdc_BUSY        0x01
  81.  
  82. #define    fdc_WTDATA        0x5FFE
  83. #define    fdc_RDDATA        0x5FF6
  84.  
  85. struct fdc_secrec {
  86.     u8          idmark;
  87.     u8          track, side, sector;
  88.     u8          seclen;    /*  128<<seclen */
  89.     u8          datamark;
  90. };
  91.  
  92. #define disk_SD    0
  93. #define    disk_DD    1
  94.  
  95. static void
  96. FDCflushbuffer(void)
  97. {
  98.     DSK.written += DSK.bufpos;
  99.     if (DSK.written >= DSK.buflen)
  100.         DSK.formatsaving = 0;
  101.  
  102.     if (DSK.handle) {
  103.         OSError     err;
  104.         OSSize      ret = DSK.bufpos;
  105.  
  106.         err = OS_Write(DSK.handle, (void *) DSK.buffer, &ret);
  107.         if (err != OS_NOERR)
  108.             DSK.status |= fdc_BADRECORD;
  109.         else if (ret != DSK.bufpos)
  110.             DSK.status |= fdc_LOSTDATA;
  111.     }
  112.     DSK.bufpos = 0;
  113. }
  114.  
  115. static      u32
  116. FDCgetfilesize(void)
  117. {
  118.     OSSize      sz;
  119.  
  120.     if (DSK.handle) {
  121.         OS_GetSize(DSK.handle, &sz);
  122.         return sz;
  123.     } else
  124.         return 0;
  125. }
  126.  
  127. static void
  128. FDCcheckdisk(void)
  129. {
  130.     if (DSK.handle)
  131.         DSK.status |= fdc_READY;
  132. }
  133.  
  134. /*
  135.     Returns 0 for error.
  136. */
  137. static int
  138. FDCseektotrack(void)
  139. {
  140.     if (DSK.handle) {
  141.         u32         offs;
  142.  
  143.         if (DSK.side)
  144.             offs = DSK.tracksside + (~(DSK.track - DSK.tracksside));
  145.         else
  146.             offs = DSK.track;
  147.         offs *= DSK.tracksize;
  148.         if (offs >= FDCgetfilesize())
  149.             return 0;
  150.         logger(_L|L_1, "seeking to Tr%d Sd%d = byte %d of file\n", 
  151.                DSK.track, DSK.side, offs);
  152.         if (!OS_Seek(DSK.handle, OSSeekAbs, offs) == OS_NOERR) {
  153.             logger(_LS | LOG_ERROR, "failed to seek!\n");
  154.             return 0;
  155.         }
  156.  
  157.         return 1;
  158.     } else
  159.         DSK.trackbyteoffset = 0;
  160.     return 0;
  161. }
  162.  
  163.  
  164. static void
  165. FDCclosedisk(void)
  166. {
  167. //  if (!(features&FE_realdisk))
  168. //      return;
  169.  
  170.     logger(_L|0, "FDCclosedisk\n");
  171.     if (DSK.postponed)
  172.         FDCflushbuffer();
  173.     if (DSK.handle) {
  174.         OS_Close(DSK.handle);
  175.         DSK.handle = 0;
  176.     }
  177. }
  178.  
  179. static void
  180. FDCopendisk(void)
  181. {
  182.     OSSpec      spec;
  183.     OSError     err;
  184.  
  185. //  struct  stat st;
  186.  
  187. //  if (!(features&FE_realdisk))
  188. //      return;
  189.  
  190.     logger(_L|0, "FDCopendisk\n");
  191.     if (DSK.handle)
  192.         FDCclosedisk();
  193.  
  194.     err = OS_FindFileInPath(diskname[DSK.num - 1], diskimagepath, &spec);
  195.     logger(_L|0, "disk image = %s\n", OS_SpecToString1(&spec));
  196.  
  197.     if (err != OS_NOERR ||
  198.         (err = OS_Open(&spec, OSReadWrite, &DSK.handle)) != OS_NOERR) {
  199.         logger(_L|LOG_ERROR,
  200.              "DOAD server:  could not open disk at DSK%d, creating a new one (%s)\n",
  201.              DSK.num, OS_SpecToString1(&spec));
  202.         FDCclosedisk();
  203.         if ((err = OS_Create(&spec, &osDiskImageType)) != OS_NOERR ||
  204.             (err = OS_Open(&spec, OSReadWrite, &DSK.handle)) != OS_NOERR) {
  205.             logger(_LS|LOG_ERROR,
  206.                  "DOAD server:  could not create disk (%s)\n",
  207.                  OS_GetErrText(err));
  208.             DSK.handle = 0;
  209.             return;
  210.         }
  211.         DSK.density = 9;
  212.     } else {
  213.         OSSize      len = 20;
  214.  
  215.         OS_Read(DSK.handle, (void *) DSK.buffer, &len);
  216.         if (len != 20) {
  217.             OS_Close(DSK.handle);
  218.             logger(_LS|LOG_ERROR,
  219.                  "DOAD server:  disk image '%s' is short (%d bytes)\n",
  220.                  OS_SpecToString1(&spec), len);
  221.             DSK.handle = 0;
  222.             return;
  223.         }
  224.         DSK.tracksside = DSK.buffer[17];
  225.         DSK.density = DSK.buffer[12];
  226.     }
  227.  
  228.     DSK.tracksize = DSK.density * 256l;
  229.     logger(_L|0, "Opened disk %d, #tracks=%d  tracksize=%d  sectors=%d\n",
  230.          DSK.num, DSK.tracksside, DSK.tracksize, DSK.density);
  231.     logger(_L|L_1, "DSK.handle=%d\n", DSK.handle);
  232. }
  233.  
  234.  
  235. static void
  236. FDCseekhome(void)
  237. {
  238.     logger(_L|0, "FDC seek home\n");
  239.     DSK.track = 0;
  240.     DSK.status |= fdc_TRACK0;
  241.     FDCcheckdisk();
  242.     FDCseektotrack();
  243. }
  244.  
  245. static void
  246. FDCseek(void)
  247. {
  248.     logger(_L|0, "FDC seek, T%d s%d\n", DSK.track, DSK.side);
  249.     DSK.track = DSK.lastbyte;
  250.     if (!DSK.track)
  251.         DSK.status |= fdc_TRACK0;
  252.     if (DSK.track >= 80)
  253.         DSK.status |= fdc_BADRECORD;
  254.     FDCcheckdisk();
  255.     FDCseektotrack();
  256. }
  257.  
  258. static void
  259. FDCstepin(void)
  260. {
  261.     logger(_L|0, "FDC step in, T%d s%d\n", DSK.track, DSK.side);
  262.     DSK.track++;
  263.     if (DSK.track >= 80)
  264.         DSK.status |= fdc_BADRECORD;
  265.     FDCcheckdisk();
  266.     FDCseektotrack();
  267. }
  268.  
  269. static void
  270. FDCskipseek(int skip)
  271. {
  272.     DSK.trackbyteoffset += skip;
  273.     OS_Seek(DSK.handle, OSSeekRel, skip);
  274. }
  275.  
  276. static int
  277. FDCfindIDmarker(void)
  278. {
  279.     if (FDCseektotrack() == 0) {
  280.         logger(_L|L_1, "FDCfindIDmarker failed\n");
  281.         DSK.status |= fdc_BADRECORD;
  282.         return 0;
  283.     } else {
  284.         logger(_L|L_1, "FDCfindIDmarker succeeded, skipping to sector %d\n",
  285.              DSK.sector);
  286.         FDCskipseek(DSK.sector * 256);
  287.         return 1;
  288.     }
  289. }
  290.  
  291. static void
  292. FDCreadIDmarker(void)
  293. {
  294.     struct fdc_secrec *fsr = (struct fdc_secrec *) DSK.buffer;
  295.  
  296.     fsr->idmark = 0xfe;
  297.     fsr->track = DSK.track;
  298.     fsr->sector = DSK.sector;
  299.     fsr->seclen = 2;
  300.     fsr->side = DSK.side;
  301.     fsr->datamark = 0xfb;
  302.     DSK.buflen = sizeof(*fsr);
  303.     DSK.bufpos = 1;
  304.     logger(_L|L_1, "ID marker:  track=%d  sector=%d  side=%d\n", fsr->track,
  305.          fsr->sector, fsr->side);
  306.     FDCcheckdisk();
  307. }
  308.  
  309. static void
  310. FDCreadsector(void)
  311. {
  312.     logger(_L|0, "FDC read sector, T%d S%d s%d\n", DSK.track, DSK.sector, DSK.side);
  313.     if (DSK.handle) {
  314.         if (FDCfindIDmarker()) {
  315.             OSSize      ret = 256;
  316.             OSError     err;
  317.  
  318.             err = OS_Read(DSK.handle, (void *) DSK.buffer, &ret);
  319.             if (err != OS_NOERR || ret < 256) {
  320.                 DSK.status |= fdc_CRCERR;
  321.                 DSK.status |= fdc_BADRECORD;
  322.                 DSK.buflen = 0;
  323.             } else {
  324.                 int         x;
  325.  
  326.                 DSK.buflen = ret;
  327.  
  328.                 if (log_level(LOG_REALDISK) >= 2) {
  329.                     logger(_L|L_2, "Apparent filename = %8.8s\n",
  330.                          FLAT_MEMORY_PTR(md_video, memory_read_word(0x8356) -
  331.                          memory_read_word(0x8354) + 1));
  332.                     logger(_L|L_2, "Sector contents:\n");
  333.                     for (x = 0; x < ret; x++) {
  334.                         int         y;
  335.  
  336.                         logger(_L|L_2, "%04X=", x);
  337.                         for (y = 0; y < 16; y++)
  338.                             logger(_L|L_2, "%02X ", DSK.buffer[x + y]);
  339.                         logger(_L|L_2, " ");
  340.                         for (y = 0; y < 16; y++)
  341.                             logger(_L|L_2, "%c",
  342.                                  isprint(DSK.buffer[x + y]) ? DSK.buffer[x +
  343.                                                                        y] :
  344.                                  '.');
  345.                         logger(_L|L_2, "\n");
  346.  
  347.                         x += 16;
  348.                     }
  349.                 }
  350.             }
  351.             DSK.bufpos = 0;
  352.             return;
  353.         }
  354.     } else {
  355.         logger(_L|0, "FDCreadsector failed, DSK.handle is 0\n");
  356.     }
  357.     DSK.status |= fdc_BADRECORD;
  358.     DSK.bufpos = 0;
  359.     DSK.buflen = 0;
  360.  
  361. }
  362.  
  363.  
  364. static void
  365. FDCwritesector(void)
  366. {
  367.     logger(_L|0, "FDC write sector, T%d S%d s%d\n", DSK.track, DSK.sector, DSK.side);
  368.     if (FDCfindIDmarker() == 0) {
  369.         DSK.status |= fdc_BADRECORD;
  370.         DSK.buflen = 0;
  371.     } else {
  372.         DSK.buflen = 256;
  373.         DSK.postponed = 1;
  374.     }
  375.     DSK.written = DSK.bufpos = 0;
  376.     FDCcheckdisk();
  377. }
  378.  
  379. static void
  380. FDCformattrack(void)
  381. {
  382.     logger(_L|0, "FDC format track, #%d\n", DSK.track);
  383.     DSK.formatsaving = 0;
  384.     DSK.buflen = DSK.tracksize;
  385. }
  386.  
  387. static void
  388. FDCguaranteetrackspace(void)
  389. {
  390.     u32         size = (DSK.track + 1) * DSK.tracksize;
  391.  
  392.     if (size > FDCgetfilesize()) {
  393.         if (OS_SetSize(DSK.handle, size) != OS_NOERR) {
  394.             DSK.status |= fdc_CRCERR | fdc_BADRECORD;
  395.         }
  396.     }
  397. }
  398.  
  399. static void
  400. FDCinterrupt(void)
  401. {
  402.     logger(_L|0, "FDC interrupt\n");
  403.     if (DSK.postponed) {
  404.         FDCflushbuffer();
  405.         DSK.postponed = 0;
  406.     }
  407.     DSK.status |= fdc_READY;
  408. }
  409.  
  410. static void
  411. FDCholdoff(void)
  412. {
  413.     logger(_L|0, "FDC hold off\n");
  414.     if (DSK.postponed) {
  415.         FDCflushbuffer();
  416.         DSK.postponed = 0;
  417.     }
  418.     DSK.status |= fdc_READY;
  419. }
  420.  
  421. //////////////////
  422.  
  423. static      s8
  424. FDCreadbyte(u32 addr)
  425. {
  426.     u8          ret;
  427.  
  428.     switch ((addr - 0x5ff0) >> 1) {
  429.     case 0:                    /* R_RDSTAT */
  430.         ret = DSK.status ^ 0x80;
  431.         logger(_L|L_1, "FDC read status >%04X = >%02X\n", addr, (u8) ret);
  432.         break;
  433.  
  434.     case 1:                    /* R_RTADDR */
  435.         ret = DSK.track;
  436.         logger(_L|L_1, "FDC read track addr >%04X = >%02X\n", addr, (u8) ret);
  437.         break;
  438.  
  439.     case 2:                    /* R_RSADDR */
  440.         ret = DSK.sector;
  441.         logger(_L|L_1, "FDC read sector addr >%04X = >%02X\n", addr, (u8) ret);
  442.         break;
  443.  
  444.     case 3:                    /* R_RDDATA */
  445.         if (DSK.hold &&
  446.             (DSK.command == FDC_readsector || DSK.command == FDC_readIDmarker))
  447.         {
  448.             ret = DSK.buffer[DSK.bufpos];
  449.             DSK.bufpos++;
  450.             if (DSK.bufpos >= DSK.buflen) {
  451.                 DSK.bufpos = 0;
  452.             }
  453.         }
  454.         logger(_L|L_2, "FDC read data >%02X\n", addr, (u8) ret);
  455.         break;
  456.  
  457.     case 4:                    /* R_WTCMD */
  458.     case 5:                    /* R_WTADDR */
  459.     case 6:                    /* R_WSADDR */
  460.     case 7:                    /* R_WTDATA */
  461.         ret = 0x00;
  462.         logger(_L|L_1, "FDC read write xxx >%04X = >%02X\n", addr, (u8) ret);
  463.         break;
  464.     }
  465.     return ret;
  466.  
  467. }
  468.  
  469. static void
  470. FDCwritebyte(u32 addr, u8 val)
  471. {
  472.     switch ((addr - 0x5ff0) >> 1) {
  473.     case 0:                    /* W_RDSTAT */
  474.     case 1:                    /* W_RTADDR */
  475.     case 2:                    /* W_RSADDR */
  476.     case 3:                    /* W_RDDATA */
  477.         logger(_L|L_1, "FDC write read xxx >%04X, >%02X\n", addr, val);
  478.         break;
  479.  
  480.     case 4:                    /* W_WTCMD */
  481.         DSK.bufpos = DSK.status = DSK.postponed = 0;
  482.         DSK.command = val;
  483.         switch (DSK.command) {
  484.         case FDC_seekhome:
  485.             FDCseekhome();
  486.             break;
  487.         case FDC_seek:
  488.             FDCseek();
  489.             break;
  490.         case FDC_stepin:
  491.             FDCstepin();
  492.             break;
  493.         case FDC_readsector:
  494.             FDCreadsector();
  495.             break;
  496.         case FDC_writesector:
  497.             FDCwritesector();
  498.             break;
  499.         case FDC_readIDmarker:
  500.             FDCreadIDmarker();
  501.             break;
  502.         case FDC_interrupt:
  503.             FDCinterrupt();
  504.             break;
  505.         case FDC_formattrack:
  506.             FDCformattrack();
  507.             break;
  508.         default:
  509.             logger(_L|0, "unknown FDC command >%02X\n", val);
  510.         }
  511.         break;
  512.  
  513.     case 5:                    /* W_WTADDR */
  514.         DSK.track = val;
  515.         logger(_L|0, "FDC write track addr >%04X, >%02X\n", addr, val);
  516.         break;
  517.  
  518.     case 6:                    /* W_WSADDR */
  519.         DSK.sector = val;
  520.         logger(_L|0, "FDC write sector addr >%04X, >%02X\n", addr, val);
  521.         break;
  522.  
  523.     case 7:                    /* W_WTDATA */
  524.         if (DSK.hold == 0)
  525.             DSK.lastbyte = val;
  526.         else {
  527.             if (DSK.command == FDC_writesector) {
  528.                 DSK.buffer[DSK.bufpos++] = val;
  529.                 if (DSK.bufpos >= DSK.buflen)
  530.                     FDCflushbuffer();
  531.             } else if (DSK.command == FDC_formattrack) {
  532.                 FDCguaranteetrackspace();
  533.             }
  534.         }
  535.     }
  536. }
  537.  
  538.  
  539. static void
  540. bwdrom_realdisk(const mrstruct *mr, u32 addr, s8 val)
  541. {
  542.     if (addr >= 0x5ff0)
  543.         FDCwritebyte(addr, ~val);
  544. }
  545.  
  546. static      s8
  547. brdrom_realdisk(const mrstruct *mr, u32 addr)
  548. {
  549.     if (addr >= 0x5ff0)
  550.         return ~FDCreadbyte(addr);
  551.     else
  552.         return BYTE(mr->areamemory, addr - 0x5C00);
  553. }
  554.  
  555. extern vmModule realDiskDSR;
  556.  
  557. mrstruct    dsr_rom_realdisk_handler = {
  558.     realdiskdsr, realdiskdsr, NULL,            /* ROM */
  559.     NULL,
  560.     NULL,
  561.     NULL,
  562.     NULL
  563. };
  564.  
  565. //  this is only used on the last area of the DSR ROM block */
  566. mrstruct    dsr_rom_realdisk_io_handler = {
  567.     realdiskdsr + 0x1C00, NULL, NULL,
  568.     NULL,
  569.     brdrom_realdisk,
  570.     NULL,
  571.     bwdrom_realdisk
  572. };
  573.  
  574. static      u32
  575. cruwRealDiskROM(u32 addr, u32 data, u32 num)
  576. {
  577.     if (data) {
  578.         logger(_L|0, "real disk DSR on\n");
  579.         report_status(STATUS_DISK_ACCESS, 1, true);
  580. //        stateflag|=ST_DEBUG;
  581.         dsr_set_active(&realDiskDSR);
  582.  
  583.         SET_AREA_HANDLER(0x4000, 0x1c00, &dsr_rom_realdisk_handler);
  584.         SET_AREA_HANDLER(0x5c00, 0x400, &dsr_rom_realdisk_io_handler);
  585.  
  586.         logger(_L|L_1, "DSR Read >4000 = >%2X\n", memory_read_byte(0x4000));
  587.     } else {
  588.         logger(_L|0, "real disk DSR off\n");
  589.         report_status(STATUS_DISK_ACCESS, 1, false);
  590. //        stateflag&=~ST_DEBUG;
  591.         dsr_set_active(NULL);
  592.         SET_AREA_HANDLER(0x4000, 0x2000, &zero_memory_handler);
  593.     }
  594.     return 0;
  595. }
  596.  
  597. static      u32
  598. cruwRealDiskHold(u32 addr, u32 data, u32 num)
  599. {
  600.     logger(_L|0, "CRU hold off\n");
  601.     DSK.hold = data;
  602.     if (DSK.hold == 0) {
  603.         FDCholdoff();
  604.     }
  605.     return 0;
  606. }
  607.  
  608. static      u32
  609. cruwRealDiskHeads(u32 addr, u32 data, u32 num)
  610. {
  611.     logger(_L|0, "CRU heads\n");
  612.     return 0;
  613. }
  614.  
  615. static      u32
  616. cruwRealDiskSel(u32 addr, u32 data, u32 num)
  617. {
  618.     u8          newnum = (addr - 0x1106) >> 1;
  619.  
  620.     logger(_L|0, "CRU disk select, #%d\n", newnum);
  621.  
  622.     if (data) {
  623.         logger(_L|0, "opening (DSK.num=%d)\n", DSK.num);
  624.         if (newnum != DSK.num) {
  625.             FDCclosedisk();
  626.             DSK.num = newnum;
  627.         }
  628.  
  629.         if (!DSK.handle) {
  630.             FDCopendisk();
  631.         }
  632.     } else if (newnum == DSK.num) {
  633.         logger(_L|0, "closing\n");
  634.         FDCclosedisk();
  635.         DSK.num = 0;
  636.     }
  637.     return 0;
  638. }
  639.  
  640. static      u32
  641. cruwRealDiskSide(u32 addr, u32 data, u32 num)
  642. {
  643.     DSK.side = data;
  644.     FDCseektotrack();
  645.     return 0;
  646. }
  647.  
  648. static      u32
  649. crurRealDiskPoll(u32 addr, u32 data, u32 num)
  650. {
  651.     return 0;
  652. }
  653.  
  654. /*************************************/
  655.  
  656. static
  657. DECL_SYMBOL_ACTION(realdisk_disk_change)
  658. {
  659.     int         dsknum = sym->name[9] - '0';
  660.  
  661.     if (task == caa_READ)
  662.         return 0;
  663.  
  664.     if (!dsr_is_real_disk(dsknum))
  665.         logger(_L|L_0,
  666.               "DOAD server:  DSK%d (%s) is inaccessible\n"
  667.                "when emulated (FIAD) disk DSR is loaded\n",
  668.               dsknum, diskname[dsknum - 1]);
  669.  
  670.     if (DSK.num == dsknum) {
  671.         logger(_L|LOG_WARN, "Changing disk %d while it's being accessed!\n", DSK.num);
  672.         FDCclosedisk();
  673.     }
  674.     return 1;
  675. }
  676.  
  677. /************************************/
  678.  
  679.  
  680. static      vmResult
  681. realdisk_getcrubase(u32 * base)
  682. {
  683.     *base = 0x1100;
  684.     return vmOk;
  685. }
  686.  
  687. static      vmResult
  688. realdisk_filehandler(u32 code)
  689. {
  690.     /* shouldn't ever get here */
  691.     return vmOk;
  692. }
  693.  
  694. static      vmResult
  695. realdisk_detect(void)
  696. {
  697.     return vmOk;
  698. }
  699.  
  700. static      vmResult
  701. realdisk_init(void)
  702. {
  703.     command_symbol_table *realdiskcommands =
  704.         command_symbol_table_new("TI Disk DSR Options",
  705.                                  "These commands control the TI 'real' disk-on-a-disk (DOAD) emulation",
  706.  
  707.          command_symbol_new("DiskImagePath",
  708.                             "Set directory list to search for DOAD disk images",
  709.                             c_STATIC,
  710.                             NULL /* action */ ,
  711.                             RET_FIRST_ARG,
  712.                             command_arg_new_string
  713.                             ("path",
  714.                              "list of directories "
  715.                              "separated by one of these characters: '"
  716.                              OS_ENVSEPLIST "'",
  717.                              NULL /* action */ ,
  718.                              -1, &diskimagepath,
  719.                              NULL /* next */ )
  720.                             ,
  721.           command_symbol_new("DiskImage1|DSK1Image",
  722.                              "DOAD image in drive 1",
  723.                              c_STATIC,
  724.                              realdisk_disk_change,
  725.                              RET_FIRST_ARG,
  726.                              command_arg_new_string
  727.                              ("file",
  728.                               "name of DOAD image",
  729.                               NULL /* action */ ,
  730.                               ARG_STR(diskname[0]),
  731.                               NULL /* next */ )
  732.                              ,
  733.            command_symbol_new("DiskImage2|DSK2Image",
  734.                               "DOAD image in drive 2",
  735.                               c_STATIC,
  736.                               realdisk_disk_change,
  737.                               RET_FIRST_ARG,
  738.                               command_arg_new_string
  739.                               ("file",
  740.                                "name of DOAD image",
  741.                                NULL /* action */ ,
  742.                                ARG_STR(diskname[1]),
  743.                                NULL /* next */ )
  744.                               ,
  745.             command_symbol_new("DiskImage3|DSK3Image",
  746.                                "DOAD image in drive 3",
  747.                                c_STATIC,
  748.                                realdisk_disk_change,
  749.                                RET_FIRST_ARG,
  750.                                command_arg_new_string
  751.                                ("file",
  752.                                 "name of DOAD image",
  753.                                 NULL /* action */ ,
  754.                                 ARG_STR(diskname[2]),
  755.                                 NULL /* next */ )
  756.                                ,
  757.  
  758.              command_symbol_new("DiskDSRFileName",
  759.                                 "Name of DSR ROM image which fits in the CPU address space >4000...>5FFF",
  760.                                 c_STATIC,
  761.                                 NULL /* action */ ,
  762.                                 RET_FIRST_ARG,
  763.                                 command_arg_new_string
  764.                                 ("file",
  765.                                  "name of binary image",
  766.                                  NULL /* action */ ,
  767.                                  ARG_STR(realdiskfilename),
  768.                                  NULL /* next */ )
  769.                                 ,
  770.  
  771.             NULL /* next */ ))))),
  772.  
  773.          NULL /* sub */ ,
  774.  
  775.          NULL    /* next */
  776.         );
  777.  
  778.     command_symbol_table_add_subtable(universe, realdiskcommands);
  779.  
  780. //  features |= FE_realdisk;
  781.     return vmOk;
  782. }
  783.  
  784. static      vmResult
  785. realdisk_enable(void)
  786. {
  787. //  if (!(features & FE_realdisk))
  788. //      return vmOk;
  789.  
  790.     logger(_L|0, "setting up TI real-disk DSR ROM\n");
  791.     if (0 == loaddsr(romspath, systemromspath, realdiskfilename,
  792.                      "TI disk DSR ROM", realdiskdsr)) return vmNotAvailable;
  793.  
  794.     if (cruadddevice(CRU_WRITE, 0x1100, 1, cruwRealDiskROM) &&
  795.         cruadddevice(CRU_WRITE, 0x1104, 1, cruwRealDiskHold) &&
  796.         cruadddevice(CRU_WRITE, 0x1106, 1, cruwRealDiskHeads) &&
  797.         cruadddevice(CRU_WRITE, 0x1108, 1, cruwRealDiskSel) &&
  798.         cruadddevice(CRU_WRITE, 0x110A, 1, cruwRealDiskSel) &&
  799.         cruadddevice(CRU_WRITE, 0x110C, 1, cruwRealDiskSel) &&
  800.         cruadddevice(CRU_WRITE, 0x110E, 1, cruwRealDiskSide) &&
  801.         cruadddevice(CRU_READ, 0x1102, 1, crurRealDiskPoll) &&
  802.         cruadddevice(CRU_READ, 0x1104, 1, crurRealDiskPoll) &&
  803.         cruadddevice(CRU_READ, 0x1106, 1, crurRealDiskPoll)) {
  804. //      features |= FE_realdisk;
  805.         return vmOk;
  806.     } else
  807.         return vmNotAvailable;
  808. }
  809.  
  810. static      vmResult
  811. realdisk_disable(void)
  812. {
  813. //  if (!(features & FE_realdisk))
  814. //      return vmOk;
  815.  
  816.     crudeldevice(CRU_WRITE, 0x1100, 1, cruwRealDiskROM);
  817.     crudeldevice(CRU_WRITE, 0x1104, 1, cruwRealDiskHold);
  818.     crudeldevice(CRU_WRITE, 0x1106, 1, cruwRealDiskHeads);
  819.     crudeldevice(CRU_WRITE, 0x1108, 1, cruwRealDiskSel);
  820.     crudeldevice(CRU_WRITE, 0x110A, 1, cruwRealDiskSel);
  821.     crudeldevice(CRU_WRITE, 0x110C, 1, cruwRealDiskSel);
  822.     crudeldevice(CRU_WRITE, 0x110E, 1, cruwRealDiskSide);
  823.  
  824.     crudeldevice(CRU_READ, 0x1102, 1, crurRealDiskPoll);
  825.     crudeldevice(CRU_READ, 0x1104, 1, crurRealDiskPoll);
  826.     crudeldevice(CRU_READ, 0x1106, 1, crurRealDiskPoll);
  827.     return vmOk;
  828. }
  829.  
  830. static      vmResult
  831. realdisk_restart(void)
  832. {
  833.     return vmOk;
  834. }
  835.  
  836. static      vmResult
  837. realdisk_restop(void)
  838. {
  839.     return vmOk;
  840. }
  841.  
  842. static      vmResult
  843. realdisk_term(void)
  844. {
  845.     return vmOk;
  846. }
  847.  
  848. static vmDSRModule realDiskModule = {
  849.     1,
  850.     realdisk_getcrubase,
  851.     realdisk_filehandler
  852. };
  853.  
  854. vmModule    realDiskDSR = {
  855.     3,
  856.     "TI real-disk DSR",
  857.     "dsrRealDisk",
  858.  
  859.     vmTypeDSR,
  860.     vmFlagsNone,
  861.  
  862.     realdisk_detect,
  863.     realdisk_init,
  864.     realdisk_term,
  865.     realdisk_enable,
  866.     realdisk_disable,
  867.     realdisk_restart,
  868.     realdisk_restop,
  869.     {(vmGenericModule *) & realDiskModule}
  870. };
  871.