Advertisement
Guest User

Untitled

a guest
Jun 24th, 2017
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 48.28 KB | None | 0 0
  1. /* rxm.c */
  2.  
  3. static char *rcsid = "$Id: rxm.c,v 1.29 2007/07/02 01:39:01 chd Exp $";
  4.  
  5. //#define __linux__
  6. //#define __NetBSD__
  7.  
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <signal.h>
  11. #include <errno.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <fcntl.h>
  16. #include <unistd.h>
  17. #include <time.h>
  18.  
  19. #if defined __linux__
  20. #include <sys/io.h>
  21. #include <sched.h>
  22. #elif defined __NetBSD__
  23. #include <machine/pio.h>
  24. #include <machine/sysarch.h>
  25. #else
  26. #error No system defined!
  27. #endif
  28.  
  29.  
  30. #include "rx_version.h"
  31.  
  32. /* fundamental definitions */
  33.  
  34. /* parallel port definitions */
  35. /*   this is a retrofit of the address from being compile time to runtime */
  36. #define IO_BASE       (io_base)
  37. #define IO_DATA        IO_BASE
  38. #define IO_STATUS     (IO_BASE + 1)
  39. #define IO_CNTRL      (IO_BASE + 2)
  40. #define FAST_IO                          /* use 32bit port access instructions instead of 8bit */
  41.  
  42. /* LINUX port I/O permissions are enabled as number of ports starting at a base address */
  43. #ifdef  FAST_IO
  44. #define IO_LEN       ((IO_CNTRL - IO_BASE + 4) & 0xFFFFFFFC)   /* round up to 32bit */
  45. #else
  46. #define IO_LEN        (IO_CNTRL - IO_BASE + 1)
  47. #endif
  48.  
  49. /* NetBSD port I/O permissions are handled by a bitmap */
  50. #define IOMAP_OFFSET  (IO_BASE/32)
  51. #ifndef FAST_IO
  52. #define IOMAP_BITMASK ((1 << (IO_DATA%32)) | (1 << (IO_STATUS%32)) | (1 << (IO_CNTRL%32)))
  53. #else
  54. #define IOMAP_BITMASK (0x0F << (IO_DATA%32))
  55. #endif
  56.  
  57.  
  58. #ifdef __NetBSD__
  59. u_long iomap[32];
  60. #endif
  61.  
  62. #define BIT_D0 0001
  63. #define BIT_D1 0002
  64. #define BIT_D2 0004
  65. #define BIT_D3 0010
  66. #define BIT_D4 0020
  67. #define BIT_D5 0040
  68. #define BIT_D6 0100
  69. #define BIT_D7 0200
  70.  
  71. #define BIT_C0 0001
  72. #define BIT_C5 0040
  73.  
  74. #define BIT_S3 0010
  75. #define BIT_S4 0020
  76. #define BIT_S5 0040
  77. #define BIT_S6 0100
  78. #define BIT_S7 0200
  79.  
  80. /* RX hardware interface definitions */
  81.  
  82. #define HW_RX_REG_1      DATA      /* bits in register 1 */
  83. #define HW_RX_ERROR      BIT_D0
  84. #define HW_RX_TR         BIT_D1
  85. #define HW_RX_DONE       BIT_D2
  86. #define HW_RX_SHIFT      BIT_D3
  87. #define HW_RX_OUT        BIT_D4
  88. #define HW_RX_AC_LO      BIT_D5
  89. #define HW_RX_LED1       BIT_D5
  90. #define HW_RX_LED2       BIT_D6
  91. #define HW_RX_INITFF     BIT_D7
  92. #define HW_RX_REG_1_INV  (BIT_D7)
  93. #define DATA_INV         HW_RX_REG_1_INV
  94.  
  95. #define HW_RX_REG_2      CNTRL     /* bits in register 2 */
  96. #define HW_RX_DATA_O     BIT_C0
  97. #define HW_RX_REG_2_INV  (BIT_C0)
  98. #define CNTRL_INV        HW_RX_REG_2_INV
  99.  
  100. #define HW_RX_REG_3      STATUS    /* bits in register 3 */
  101. #define HW_RX_RUN        BIT_S7  
  102. #define HW_RX_DMA        BIT_S6
  103. #define HW_RX_INIT       BIT_S5
  104. #define HW_RX_DATA_I     BIT_S4
  105. #define HW_RX_12BIT      BIT_S3
  106. #define HW_RX_REG_3_INV  (BIT_S3 | BIT_S4 | BIT_S6)
  107. #define STATUS_INV       HW_RX_REG_3_INV
  108.  
  109. /* RX interface definitions */
  110.  
  111. #define RX_ERROR      (HW_RX_ERROR)
  112. #define RX_TR         (HW_RX_TR)
  113. #define RX_DONE       (HW_RX_DONE)
  114. #define RX_SHIFT      (HW_RX_SHIFT)
  115. #define RX_OUT        (HW_RX_OUT)
  116. #define RX_AC_LO      (HW_RX_AC_LO)
  117. #define RX_INITFF     (HW_RX_INITFF)
  118.  
  119. #define RX_LED1       (HW_RX_LED1)
  120. #define RX_LED2       (HW_RX_LED2)
  121.  
  122. #define RX_DATA_O     (HW_RX_DATA_O << 8)
  123.  
  124. #define RX_DATA_I     (HW_RX_DATA_I << 16)
  125. #define RX_RUN        (HW_RX_RUN << 16)
  126. #define RX_INIT       (HW_RX_INIT << 16)
  127. #define RX_12BIT      (HW_RX_12BIT << 16)
  128. #define RX_DMA        (HW_RX_DMA << 16)
  129.  
  130. // #define rx_wait()  while(!(rx_if_get(RX_RUN | RX_INIT))) sleep(0);
  131. #define RX_WAIT       1
  132. #define RX_NOWAIT     0
  133.  
  134. /* function codes */
  135.  
  136. #define RX_FUNC         0000016         /* mask for function code */
  137. #define RX_FILL         0000000         /* fill buffer */
  138. #define RX_EMPTY        0000002         /* empty */
  139. #define RX_WSECT        0000004         /* write sector */
  140. #define RX_RSECT        0000006         /* read sector */
  141. #define RX_SMD          0000010         /* set media density */
  142. #define RX_RDSTAT       0000012         /* read status */
  143. #define RX_WDDSECT      0000014         /* write deleted data sector */
  144. #define RX_RDEC         0000016         /* read error code */
  145.  
  146. #define RX_UNIT         0000020         /* unit select */
  147. #define RX_DEN          0000400         /* function density */
  148. #define RX_GO           0000001         /* GO bit */
  149. #define RX_IE           0000100         /* IE bit */
  150. #define RX_EXADDR       0030000         /* upper 2 bits of 18bit address */
  151. #define RX_CS_INIT      0040000         /* initialize RX02 */
  152.  
  153. /* status codes */
  154.  
  155. #define RX_CRC          0000001         /* CRC error */
  156. #define RX_DS       0000002     /* double sided - RX03 */
  157. #define RX_ID           0000004         /* controller initialization done */
  158. #define RX_RX02_ID      0000010         /* set if an RX02 drive */
  159. #define RX_DEN_ERR      0000020         /* density error */
  160. #define RX_DENSITY_B    0000040         /* diskette is double density */
  161. #define RX_DD           0000100         /* deleted data detected */
  162. #define RX_DRDY_B       0000200         /* drive ready */
  163. #define RX_USEL_B       0000400         /* unit selected */
  164. #define RX_WC_OVFL      0001000         /* word count overflow */
  165.  
  166. /* emulation types */
  167. #define RX_RX01         1               /* RX02 in RX01 emulation mode */
  168. #define RX_RX02         2               /* RX02 in RX02 mode */
  169. #define rx_mode(x)      (rx2.type == (x))
  170. #define RX_XFER_PIO     0               /* RX02 with a PIO interface or an RX01 */
  171. #define RX_XFER_DMA     1               /* RX02 with a DMA interface */
  172. #define rx_xfer_mode(x) (rx2.xfer_mode == (x))
  173.  
  174. /* disk definitions */
  175.  
  176. #define RX0_IMAGE       "rx0.dsk"
  177. #define RX1_IMAGE       "rx1.dsk"
  178.  
  179. #define NTRKS           77              /* number of tracks / disk */
  180. #define NSECTS          26              /* number of sectors / track */
  181. #define NBPS            128             /* bytes per sector - SD */
  182. #define DENSITY_SD      1
  183. #define DENSITY_DD      2
  184. #define NUNITS          2               /* Unit Number: 0 = left, 1 = right */
  185. #define NORMAL_DATA     0
  186. #define DELETED_DATA    1
  187.  
  188. #define sec_size(d)     (NBPS*(d))
  189. #define dsk_size(d)     (NTRKS*NSECTS*sec_size(d))
  190.  
  191. /* timing */
  192. #define RX02_ACTUAL_SPEED 0
  193.  
  194. /* a test configuration */
  195. #if (RX02_ACTUAL_SPEED == 3)
  196. #define MS              1000            /* sleep millisecond */
  197. #define RX_RDSTAT_TIME  (25*MS)         /* read status function time */
  198. #define RX_INIT_TIME    (50*MS)         /* initialize floppy drive system time */
  199. #define RX_STEP_TIME    0               /* track step time */
  200. #define RX_SETTLE_TIME  0               /* seek settling time */
  201. #define RX_SEC_TIME     0
  202. #endif
  203.  
  204. /* a faster, but still simulating delays */
  205. #if (RX02_ACTUAL_SPEED == 2)
  206. #define MS              1000            /* sleep millisecond */
  207. #define RX_RDSTAT_TIME  (200*MS)        /* read status function time */
  208. #define RX_INIT_TIME    (400*MS)        /* initialize floppy drive system time */
  209. #define RX_STEP_TIME    (8*MS)          /* track step time */
  210. #define RX_SETTLE_TIME  (15*MS)         /* seek settling time */
  211. #define RX_SEC_TIME     (3*60*1000*MS/360/NSECTS)
  212. #endif
  213.  
  214. /* actual speed of real hardware */
  215. #if (RX02_ACTUAL_SPEED == 1)
  216. #define MS              1000            /* sleep millisecond */
  217. #define RX_RDSTAT_TIME  (250*MS)        /* read status function time */
  218. #define RX_INIT_TIME    (500*MS)        /* initialize floppy drive system time */
  219. #define RX_STEP_TIME    (10*MS)         /* track step time */
  220. #define RX_SETTLE_TIME  (20*MS)         /* seek settling time */
  221. #define RX_SEC_TIME     (3*60*1000*MS/360/NSECTS)
  222. #endif
  223.  
  224. /* as fast as it can go */
  225. #if (RX02_ACTUAL_SPEED == 0)            /* this is too fast for the diagnostics */
  226. #define MS              1000            /* sleep millisecond */
  227. #define RX_RDSTAT_TIME  (25*MS)         /* read status function time */
  228. #define RX_INIT_TIME    (50*MS)         /* initialize floppy drive system time */
  229. #define RX_STEP_TIME    0               /* track step time */
  230. #define RX_SETTLE_TIME  0               /* seek settling time */
  231. #define RX_SEC_TIME     0
  232. #endif
  233.  
  234. #ifndef MS
  235. #error RX02_ACTUAL_SPEED must be set properly.
  236. #endif
  237.  
  238. #define seek_time(d) (RX_SEC_TIME + ((abs(d) == 0) ? 0 : abs(d)*RX_STEP_TIME + RX_SETTLE_TIME))
  239.  
  240. struct drv_t {
  241.     int ta;
  242.     char fn[50];
  243.     int fd;
  244.     int density;
  245.     unsigned char image[dsk_size(DENSITY_DD)];
  246. };
  247.  
  248. struct rx2_t {
  249.     int type;                   /* emulation type */
  250.     int xfer_mode;              /* transfer mode: RX_PIO or RX_DMA */
  251.     int cs;                     /* image of CSR */
  252.     int db;                     /* image of DB */
  253.     int ta;                     /* track address */
  254.     int sa;                     /* sector address */
  255.     int wc;                     /* word count */
  256.     int ba;                     /* buffer address */
  257.     int es;                     /* extended status */
  258.     int err_code;               /* error code */
  259.     struct drv_t *unit;         /* active drive */
  260.     struct drv_t drv[NUNITS];   /* drive specific parameters */
  261. } rx2;
  262.  
  263. unsigned char buffer[sec_size(DENSITY_DD)];
  264. unsigned char dd_sec_map[NUNITS][NTRKS][NSECTS]; /* 0 == normal data, 1 == deleted data */
  265. int func_count[8];              /* count the number of times a function has been executed */
  266.  
  267. int verbose;
  268. int expand_image;
  269. int intr_signal;
  270. int interruptable;
  271. int rx_if_image;
  272. int io_base;            /* parallel port base address */
  273.  
  274. void prompt(void);
  275.  
  276. void spinner(int);
  277. #define NO_DOT '\000'           /* flag indicating to turn the spinner, but not advance it */
  278. #define DOT    '.'              /* advance spinner: leaving a dot behind, usual means a pause */
  279. #define BANG   '!'              /*   leaving a bang behind, means a pause but not interruptable */
  280. #define LATE   'L'              /*   leaving an L behind, means the run bit was set immediately and we are late */
  281.  
  282. #define RX_DRDY(u)      ((rx2.drv[(u)].fd > 0) ? RX_DRDY_B : 0)
  283. #define RX_USEL(u)      ((unit == 0) ? 0 : RX_USEL_B)
  284. #define RX_DENSITY(u)   (((rx2.drv[(u)].density) == DENSITY_SD) ? 0 : RX_DENSITY_B)
  285. #define RX_NBITS()      (rx_if_get(RX_12BIT) ? 12 : 8)
  286. #define RX_DELDAT(u)    (dd_sec_map[(u)][rx2.ta][rx2.sa - 1] == DELETED_DATA)
  287. #define rx_nbits(x)     (RX_NBITS() == (x))
  288. #define verbosity(x)    ((x) <= verbose)
  289.  
  290.  
  291. /* read the processor clock cycle counter */
  292.  
  293. extern __inline__ unsigned long long int rdtsc()
  294. {
  295.     unsigned long long int x;
  296.     __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
  297.     return x;
  298. }
  299.  
  300. // RX interface bit I/O
  301.  
  302. // return the bits from the RX interface bit vector
  303. // only those bits in mask are accurate, the rest are zeroed
  304.  
  305. int rx_if_getx(int mask)
  306. {
  307.     int val = 0;
  308. #ifdef FAST_IO
  309.     int port_val;
  310.    
  311.     port_val = inl(IO_DATA) ^ (DATA_INV | (STATUS_INV << 8) | (CNTRL_INV << 16));
  312.     val = (port_val & 0x0000ff) | ((port_val & 0x00ff00) << 8) | ((port_val & 0xff0000) >> 8);  
  313. #else
  314.  
  315.     if (mask & 0x0000ff) {
  316.         val |= inb(IO_DATA) ^ DATA_INV;
  317.     }
  318.     if (mask & 0x00ff00) {
  319.         val |= (inb(IO_CNTRL) ^ CNTRL_INV) << 8;
  320.     }
  321.     if (mask & 0xff0000) {
  322.         val |= (inb(IO_STATUS) ^ STATUS_INV) << 16;
  323.     }
  324. #endif
  325.     return val & mask;
  326. }
  327.  
  328. int rx_if_get(int mask)
  329. {
  330. #if 1
  331.     return rx_if_getx(mask);
  332. #else
  333.     int val1, val2, loops;
  334.  
  335.     loops = 0;
  336.     do {
  337.         val1 = rx_if_getx(mask);
  338.         val2 = rx_if_getx(mask);
  339.         loops += 1;
  340.         if ((loops % 10) == 9)
  341.             printf("rx_if_get: took 9 tries\n");
  342.     }
  343.     while (val1 != val2);
  344.     if (loops > 2)
  345.         printf("rx_if_get: took %d tries\n", loops);  
  346.     return val1;
  347. #endif
  348. }
  349.  
  350. // change the state of mask bits to val
  351.  
  352. void rx_if_put(int mask, int val)
  353. {
  354.     static int dat;
  355. #if defined __linux__
  356. #ifdef FAST_IO
  357.     int port_dat;
  358.  
  359.     dat &= ~mask;
  360.     dat |= (mask & val);
  361.     port_dat = (dat & 0x0000ff) | ((dat & 0x00ff00) << 8);
  362.     port_dat ^= DATA_INV | (CNTRL_INV << 16);
  363.     outl(port_dat, IO_DATA);
  364. #else
  365.     dat &= ~mask;
  366.     dat |= (mask & val);
  367.     if (mask & 0x000000ff)
  368.         outb(dat ^ DATA_INV, IO_DATA);
  369.     if (mask & 0x0000ff00)
  370.         outb((dat >> 8) ^ CNTRL_INV, IO_CNTRL);
  371. #endif
  372. #elif defined __NetBSD__
  373. #ifdef FAST_IO
  374.     int port_dat;
  375.  
  376.     dat &= ~mask;
  377.     dat |= (mask & val);
  378.     port_dat = (dat & 0x0000ff) | ((dat & 0x00ff00) << 8);
  379.     port_dat ^= DATA_INV | (CNTRL_INV << 16);
  380.     outl(IO_DATA, port_dat);
  381. #else
  382.     dat &= ~mask;
  383.     dat |= (mask & val);
  384.     if (mask & 0x000000ff)
  385.         outb(IO_DATA, dat ^ DATA_INV);
  386.     if (mask & 0x0000ff00)
  387.         outb(IO_CNTRL, (dat >> 8) ^ CNTRL_INV);
  388. #endif
  389. #endif
  390.     rx_if_image = dat;
  391. }
  392.  
  393. void rx_if_set(int mask)
  394. {
  395.      rx_if_put(mask, 0x00FFFFFF);
  396. }
  397.  
  398. void rx_if_clr(int mask)
  399. {
  400.      rx_if_put(mask, 0x00000000);
  401. }
  402.  
  403. /* ---------------------------------------------------------- */
  404.  
  405. /* delay for x microseconds */
  406.  
  407. void rxdelay(ulong x) {
  408.     struct timespec interval;
  409.  
  410. #if 0
  411.     usleep(x);
  412. #else
  413.     interval.tv_sec = x / 1000000L;
  414.     interval.tv_nsec = 1000*(x % 1000000L);
  415.     nanosleep(&interval, NULL);
  416. #endif
  417. }
  418.  
  419. #define NICE_VALUE 10
  420.  
  421. /* wait until the RX_RUN signal is asserted                                */
  422.  
  423. /*   This function waits until the RX_RUN signal is asserted indicating    */
  424. /*   that a new value has been loaded into the CS or DB registers.         */
  425. /*   It also returns when RX_INIT is asserted.                             */
  426. /*   RX_TR is cleared.                                                     */
  427.  
  428. #define WAIT_LOOPS 1000
  429.  
  430. void rx_wait(void)
  431. {
  432.     int sleeping, loops;
  433.  
  434.     loops = 0;
  435.     sleeping = 0;
  436.  
  437.     while (!(rx_if_get(RX_RUN | RX_INIT))) {
  438.         if (loops > WAIT_LOOPS) {
  439.             if (!sleeping) {
  440.                 sleeping = 1;
  441.                 if (verbosity(3))
  442.                     printf("rx_wait: yielding processor\n");
  443.                 else {
  444.                     if (interruptable)
  445.                         spinner(DOT);
  446.                     else
  447.                         spinner(BANG);
  448.                 }
  449.             }
  450.             if ((interruptable && intr_signal > 0) || intr_signal > 4)
  451.                 prompt();
  452. #ifdef __linux__
  453.             nice(NICE_VALUE);  /* lower priority */
  454.             sched_yield();
  455. #else
  456.             sleep(0);
  457. #endif
  458.         } else
  459.              loops += 1;
  460.     }
  461.     nice(0);                   /* restore to base priority */
  462.     rx_if_clr(RX_TR);
  463. }
  464.  
  465. /* receive a word of n bits*/
  466. /*     transfer is msb first */
  467.  
  468. int rx_recv(int n) {
  469.     int i, x;
  470.  
  471.     x = 0;
  472.     rx_if_clr(RX_DATA_O | RX_OUT | RX_SHIFT | RX_ERROR | RX_DONE);
  473.     for (i = 0; i < n; i++) {
  474.         x <<= 1;                               /* make room       */
  475.         x |= (rx_if_get(RX_DATA_I)) ? 1 : 0;   /* insert new bit  */
  476.         rx_if_set(RX_SHIFT);                   /* pulse for shift */
  477.         rx_if_clr(RX_SHIFT);
  478.     }
  479.  
  480.     /* The extra pulse on RX_SHIFT is included in the RX02 TM flowchart,   */
  481.     /* but it seems to get the RX211 state machine out of sync.            */
  482.     /* It is commented out here for that reason.                           */
  483. #if 0
  484.     rx_if_set(RX_SHIFT);                       /* pulse for shift          */
  485.     rx_if_clr(RX_SHIFT);                       /*   to get parity, I think */
  486. #endif
  487.     return x;
  488. }
  489.  
  490. /* receive a word of n bits with handshakes */
  491.  
  492. /*   RX_TR is asserted indicating that a transfer is requested.            */
  493. /*   We now wait until RX_RUN is asserted by the PDP interface, indicating */
  494. /*   that a value has been loaded into a register.                         */
  495. /*   RX_TR is deasserted.                                                  */
  496. /*   The value loaded by the PDP is then tranfered bit by bit.             */
  497.  
  498. int rx_get(int n) {
  499.     rx_if_set(RX_TR);
  500. if (verbosity(3))
  501.     printf("setting TR\n");
  502.     rx_wait();
  503.     rx_if_clr(RX_TR);
  504.     return(rx_recv(n));
  505. }
  506.  
  507. /* transmit a word of n bits */
  508. /*     transfer is msb first */
  509.  
  510. /*   Data is clocked into the RX interface on the rising edge of RX_SHIFT.     */
  511. /*   RX_SHIFT is cleared and the data bit is set on the same output cycle      */
  512. /*   so that only 2 i/o port writes are necessary.                             */
  513. /*   (Unfortunately the data bit and shift bit are in different output ports,  */
  514. /*   so there is no advantage.)                                                */
  515.  
  516. void rx_xmit(int val, int n) {
  517.     int i, mask;
  518. #if 0
  519.     int bit;
  520. #endif
  521.  
  522.     rx_if_clr(RX_SHIFT);
  523.     rx_if_set(RX_OUT);
  524.     mask = 1 << (n - 1);
  525. #if 0
  526.     for (i = 0; i < n; i++) {
  527.         if (val & mask)
  528.             bit = RX_DATA_O;
  529.         else
  530.             bit = 0;
  531.         rx_if_put(RX_DATA_O | RX_SHIFT, bit);     /* set the output state   */
  532.         rx_if_set(RX_SHIFT);                      /* clock in the bit       */
  533.         mask >>= 1;
  534.     }
  535. #else
  536.     for (i = 0; i < n; i++) {
  537.         if (val & mask)
  538.             rx_if_set(RX_DATA_O);
  539.         else
  540.             rx_if_clr(RX_DATA_O);
  541.         rx_if_clr(RX_SHIFT);
  542.         rx_if_set(RX_SHIFT);         /* pulse for shift */
  543.         mask >>= 1;
  544.     }
  545. #endif
  546.     rx_if_clr(RX_SHIFT);
  547.     rx_if_set(RX_DATA_O);
  548. }
  549.  
  550. /* transmit a word of n bits with handshakes */
  551. /*     if wait, then wait for RX_RUN from interface */
  552.  
  553. void rx_put(int val, int n, int wait) {
  554.     rx_if_set(RX_OUT);
  555.     rx_if_clr(RX_DONE | RX_TR);
  556.     rx_xmit(val, n);
  557.     rx_if_set(RX_TR);
  558. if (verbosity(3))
  559.     printf("setting TR\n");
  560.     if (wait) {
  561.         rx_wait();
  562.         rx_if_clr(RX_TR);
  563.     }
  564. }
  565.  
  566. /* transmit an extended status word of 12 bits */
  567.  
  568. void rx_put_es(int val) {
  569.     if (verbose)
  570.         printf("rx_put_es: ex stat = %05o, ", val);
  571.     if (rx_xfer_mode(RX_XFER_DMA)) {
  572.         if (verbose)
  573.             printf("DMA mode\n");
  574.         rx_if_clr(RX_TR);
  575.         rx_if_set(RX_OUT);
  576.         rx_if_set(RX_DONE);        
  577.         rx_xmit(val, 12);
  578.         rx_if_set(RX_TR);
  579.     }
  580.     else {
  581.         if (verbose)
  582.             printf("PIO mode\n");
  583.         rx_if_clr(RX_TR);
  584.         rx_if_set(RX_OUT);
  585.         if (!rx_mode(RX_RX01) && !rx_nbits(12)) /* RX8E */
  586.             rx_if_set(RX_DONE);
  587.         rx_xmit(val, 12);
  588.         if (!rx_mode(RX_RX01) && !rx_nbits(12)) {/* RX8E */
  589.             rx_if_set(RX_TR);
  590.             if (verbosity(3))
  591.                 printf("setting TR\n");
  592.         }
  593.     }
  594. }
  595.  
  596. /* display an activity indicator on the controlling terminal */
  597.  
  598. /*   if dot is true then a dot is deposited and the cursor moves on */
  599.  
  600. void spinner(int dot) {
  601.     char phases[] = "|/-\\";
  602.     static int cur_phase;
  603.  
  604.     if (dot)
  605.         printf("\010%c.", dot);             /* BS a char and a dot */
  606. #if 0
  607.     if (dot == DOT)
  608.         printf("\010..");                   /* BS and two dots */
  609.     if (dot == BANG)
  610.         printf("\010!.");                   /* BS a bang and a dot */
  611. #endif
  612.     if (cur_phase < 0 || cur_phase > 3)
  613.         cur_phase = 0;
  614.     printf("\010%c", phases[cur_phase++]);  /* BS and the next turn */
  615.     fflush(NULL);
  616. }
  617.  
  618. /* show the current state of the interface signals */
  619.  
  620. void show_rx_if(void) {
  621.     if (rx_if_image & (RX_ERROR | RX_TR | RX_DONE | RX_SHIFT | RX_OUT | RX_AC_LO | RX_INITFF))
  622.         printf("rx_if_signals asserted: ");
  623.     else {
  624.         printf("rx_if_signals asserted: none\n");
  625.         return;
  626.     }
  627.     if (rx_if_image & RX_ERROR)
  628.         printf("RX_ERROR ");
  629.     if (rx_if_image & RX_TR)
  630.         printf("RX_TR ");
  631.     if (rx_if_image & RX_DONE)
  632.         printf("RX_DONE ");
  633.     if (rx_if_image & RX_SHIFT)
  634.         printf("RX_SHIFT ");
  635.     if (rx_if_image & RX_OUT)
  636.         printf("RX_OUT ");
  637. //  if (rx_if_image & RX_AC_LO)
  638. //      printf("RX_AC_LO ");
  639.     if (rx_if_image & RX_LED1)
  640.         printf("RX_LED1 ");
  641.     if (rx_if_image & RX_INITFF)
  642.         printf("RX_INITFF ");
  643.     printf("\n");
  644. }
  645.  
  646.  
  647. /* do a function request */
  648.  
  649. void do_func(void) {
  650.     int i, j, val, offset;
  651.     int unit;
  652.     int distance;
  653.  
  654.     rx_if_clr(RX_TR);
  655.     rx_if_clr(RX_OUT);
  656.     rx_if_set(RX_DATA_O);
  657.     rx_if_set(RX_DONE);
  658.     interruptable = 1;
  659.     rx_if_set(RX_LED1);
  660.     rx_wait();
  661.     interruptable = 0;
  662.     rx_if_clr(RX_LED1);
  663.     if (rx_if_get(RX_INIT)) {
  664.         if (verbose)
  665.             printf("RX_INIT request.\n");
  666.         return;
  667.     }
  668.     if (rx_xfer_mode(RX_XFER_DMA) || (rx_mode(RX_RX01) && rx_nbits(12)) || (rx_mode(RX_RX02) && rx_nbits(12))) {
  669.         rx2.cs = rx_recv(12);
  670.         if (verbosity(3))
  671.             printf("receiving 12 bit command\n");
  672.     }
  673.     else { /* two 8-bit transfers with an RX11 or an RX28 in 8bit mode */
  674.         rx2.cs = rx_recv(8);
  675. //      rx2.cs |= rx_get(8) << 8;
  676.         if (verbosity(3))
  677.             printf("receiving 8 bit command\n");
  678.     }
  679.  
  680.     if (verbose)
  681.         printf("RX_RUN request: function = %06o\n", rx2.cs);
  682. //    else
  683. //        spinner(NO_DOT);
  684.     unit = (rx2.cs & RX_UNIT) ? 1 : 0;
  685.     rx2.unit = &rx2.drv[unit];
  686.  
  687. //    if (!(rx2.cs & RX_GO)) {
  688. //        printf("ERROR: Received command without a GO bit.\nMajor protocol violation.\n");
  689. //        goto error;
  690. //    }
  691.  
  692.     func_count[(rx2.cs & RX_FUNC) >> 1] += 1;
  693.  
  694.     switch(rx2.cs & RX_FUNC) {
  695.  
  696.     /* fill buffer  - 000             */
  697.     /* empty buffer - 001             */
  698.     /*  RX02 DMA                      */
  699.     /*    func                        */
  700.     /*    word count (8)              */
  701.     /*    xfer of N bytes (8)         */
  702.     /*  RX02 PIO                      */
  703.     /*    func                        */
  704.     /*    xfer of N bytes (8) or (12) */
  705.     /*  RX01                          */
  706.     /*    func                        */
  707.     /*    xfer of N bytes (8) or (12) */
  708.     case RX_FILL:
  709.     case RX_EMPTY:
  710.         if (verbose)
  711.             printf("%s buffer request\n", ((rx2.cs & RX_FUNC) == RX_FILL) ? "fill" : "empty");
  712.         if (rx_xfer_mode(RX_XFER_DMA))
  713.             rx2.wc = rx_get(8);
  714.         else {
  715.             rx2.wc = rx_nbits(8) ? 128/2 : 64/2;
  716.             if (RX_DENSITY(unit))
  717.                 rx2.wc *= 2;
  718.         }
  719.         if (verbose || rx2.wc == 0)
  720.             if (rx_nbits(8))
  721.                 printf("word count = %06o (%d bytes)\n", rx2.wc, rx2.wc*2);
  722.  
  723.         if (2*rx2.wc > sec_size(rx2.unit->density)) {
  724.             if (verbose)
  725.                 printf("word count overflow\n");
  726.             rx2.err_code = 0230;
  727.             rx2.es = RX_WC_OVFL | RX_USEL(unit) | RX_DENSITY(unit);
  728.             goto error;
  729.         }
  730.         if ((rx2.cs & RX_FUNC) == RX_EMPTY) {
  731.             for (i = 0; i < 2*rx2.wc; i++) {
  732.                 if (rx_nbits(8))
  733.                     val = buffer[i];
  734.                 else {  /* 12 bit values are packed into the first 2/3 of the sector */
  735.                     j = 3*i/2;
  736.                     val = (i & 1) ? ((buffer[j] & 017) << 8) | buffer[j + 1] : (buffer[j] << 4) | ((buffer[j + 1] >> 4) & 017);
  737.                 }
  738.                 rx_put(val, RX_NBITS(), RX_WAIT);
  739.             }
  740.         }
  741.         else {
  742.             for (i = 0; i < 2*rx2.wc; i++) {
  743.                 if (rx_nbits(8))  
  744.                     buffer[i] = rx_get(8);
  745.                 else {
  746.                     val = rx_get(12);
  747.                     j = 3*i/2;
  748.                     if (i & 1) {
  749.                         buffer[j] |= (val >> 8) & 017;
  750.                         buffer[j + 1] = val;
  751.                     } else {
  752.                         buffer[j] = val >> 4;
  753.                         buffer[j + 1] = (val & 017) << 4;
  754.                     }
  755.                 }
  756.             }
  757.             if (2*rx2.wc*RX_NBITS()/8 < sec_size(rx2.unit->density))
  758.                 memset(&buffer[2*rx2.wc*RX_NBITS()/8], 0x00, sec_size(rx2.unit->density) - 2*rx2.wc*RX_NBITS()/8);
  759.         }
  760.         if (verbose) {
  761.             if (rx_nbits(8))
  762.                 printf("transferred %d bytes\n", rx2.wc*2);
  763.             else
  764.                 printf("transferred %d words\n", rx2.wc*2);
  765.     }
  766.         rx2.wc = 0;
  767.         rx2.es = RX_USEL(unit) | RX_DENSITY(unit);
  768.         break;            
  769.  
  770.     /* write sector - 010 */
  771.     /* read sector - 011  */
  772.     /* write deleted data sector - 110  */
  773.     /*    func               */
  774.     /*    sector (8) or (12) */
  775.     /*    track  (8) or (12) */
  776.     case RX_RSECT:
  777.     case RX_WSECT:  
  778.     case RX_WDDSECT:
  779.  
  780.         if (verbose)
  781.             printf("transfer sector request: ");
  782.         if (verbose && ((rx2.cs & RX_FUNC) == RX_WSECT))
  783.             printf("write\n");
  784.         if (verbose && ((rx2.cs & RX_FUNC) == RX_RSECT))
  785.             printf("read\n");
  786.         if (verbose && ((rx2.cs & RX_FUNC) == RX_WDDSECT))
  787.             printf("write deleted data\n");
  788.  
  789.         if (verbosity(3))
  790.             printf("getting sector address\n");
  791.         rx2.sa = rx_get(RX_NBITS()) & 037;
  792.         if (verbosity(3))
  793.             printf("xfr: sector = %d\n", rx2.sa);
  794.         if (verbosity(3))
  795.             printf("getting track address\n");
  796.         rx2.ta = rx_get(RX_NBITS()) & 0177;
  797.         if (verbosity(3))
  798.             printf("xfr: track = %d\n", rx2.ta);
  799.  
  800.         rx_if_clr(RX_SHIFT | RX_DATA_O | RX_DONE | RX_OUT | RX_TR | RX_ERROR);
  801.  
  802. //        if (verbose)
  803. //            printf("transfer sector request: ");
  804. //        if (verbose && ((rx2.cs & RX_FUNC) == RX_WSECT))
  805. //            printf("write\n");
  806. //        if (verbose && ((rx2.cs & RX_FUNC) == RX_RSECT))
  807. //            printf("read\n");
  808. //        if (verbose && ((rx2.cs & RX_FUNC) == RX_WDDSECT))
  809. //            printf("write deleted data\n");
  810.  
  811.         distance = rx2.ta - rx2.unit->ta;
  812.         rx2.unit->ta = rx2.ta;
  813.  
  814.         /* check that drive is ready */
  815.         if (!RX_DRDY(unit)) {
  816.             rx2.es = RX_USEL(unit) | RX_DENSITY(unit);
  817.             printf("drive %d not ready\n", unit);
  818.             goto error;
  819.         }
  820.         /* check that density matches */
  821.         if (!rx_mode(RX_RX01) &&  /* RX01 ignores density bit and OS/8 does too */
  822.             ((RX_DENSITY(unit) && !(rx2.cs & RX_DEN))
  823.             || (!RX_DENSITY(unit) && (rx2.cs & RX_DEN)))) {
  824.             rx2.es = RX_USEL(unit) | RX_DENSITY(unit) | RX_DEN_ERR;
  825.             rx2.err_code = 0240; /* Density Error */
  826.             if (verbose)
  827.                 printf("sector density error on unit %d\n", unit);
  828.             goto error;
  829.         }
  830.         if (rx2.ta < 0 || rx2.ta >= NTRKS || rx2.sa < 1 || rx2.sa > NSECTS) {
  831.             if (rx2.ta < 0 || rx2.ta >= NTRKS)
  832.                 printf("track value out of range: track = %06o, sector = %06o\n", rx2.ta, rx2.sa);
  833.             if (rx2.sa < 1 || rx2.sa > NSECTS)
  834.                 printf("sector value out of range: track = %06o, sector = %06o\n", rx2.ta, rx2.sa);
  835.         }
  836.         else {
  837.             offset = (rx2.ta*NSECTS + (rx2.sa - 1))*sec_size(rx2.unit->density);
  838.             if ((rx2.cs & RX_FUNC) == RX_RSECT) { /* read */
  839.                 if (verbose) printf("read: unit = %d, track = %d, sector = %d\n", unit, rx2.ta, rx2.sa);
  840.                 memcpy(buffer, &rx2.unit->image[offset], sec_size(rx2.unit->density));
  841.             }
  842.             else { /* write */
  843.                 if (verbose) printf("write: unit = %d, track = %d, sector = %d\n", unit, rx2.ta, rx2.sa);
  844.                 if ((rx2.cs & RX_FUNC) == RX_WDDSECT)
  845.                     dd_sec_map[unit][rx2.ta][rx2.sa - 1] = DELETED_DATA;
  846.                 else
  847.                     dd_sec_map[unit][rx2.ta][rx2.sa - 1] = NORMAL_DATA;
  848.                 memcpy(&rx2.unit->image[offset], buffer, sec_size(rx2.unit->density));
  849.                 lseek(rx2.unit->fd, offset, SEEK_SET);
  850.                 write(rx2.unit->fd, buffer, sec_size(rx2.unit->density));
  851.             }
  852.         }
  853.         // printf("seek distance is %d, waiting for %d uS\n", abs(distance), seek_time(distance));
  854.         rxdelay(seek_time(distance));
  855.         rx2.es = RX_USEL(unit) | RX_DRDY(unit) | RX_DENSITY(unit) | RX_DELDAT(unit);
  856.         break;
  857.  
  858.     /* set media density - 100 */
  859.     /*    func                 */
  860.     /*    "I"                  */
  861.     case RX_SMD:
  862.         if (rx_mode(RX_RX01)) { /* function 100 is a NOP for the RX01 */
  863.             if (verbose)
  864.                 printf("NOP request\n");
  865.             break;
  866.         }
  867.         if (verbose)
  868.             printf("set media density\n    waiting for password...\n");
  869.         val = rx_get(RX_NBITS());
  870.         if (val != 'I') {
  871.             rx2.err_code = 0250;
  872.             rx2.es = RX_USEL(unit) | RX_DENSITY(unit);
  873.             if (verbose)
  874.                 printf("    password error: received %04o, expected 0111\n", val);
  875.             goto error;
  876.         }
  877.         else {
  878.             rx2.drv[unit].density = (rx2.cs & RX_DEN) ? DENSITY_DD : DENSITY_SD;
  879.             if (verbose)
  880.                 printf("    correct password received.\n");
  881.         }
  882.         rx2.es = RX_USEL(unit) | RX_DENSITY(unit);
  883.         break;
  884.  
  885.     /* maintenance read status - 101  */ /***************/
  886.     /*    func                        */
  887.     case RX_RDSTAT:
  888.         rxdelay(RX_RDSTAT_TIME); /* delay */
  889.         if (verbosity(3))
  890.             printf("Density = %o, com_stat = %o\n", rx2.unit->density, rx2.cs);
  891.         if (RX_DRDY(unit) && (((rx2.unit->density == DENSITY_DD) && !(rx2.cs & RX_DEN)) /* check that density matches */
  892.             || ((rx2.unit->density == DENSITY_SD) && (rx2.cs & RX_DEN)))) {
  893.             rx2.es = RX_USEL(unit) | RX_DRDY(unit) | RX_DENSITY(unit) | RX_DEN_ERR | (rx_mode(RX_RX02) ? RX_RX02_ID : 0);
  894.             rx2.err_code = 0240; /* Density Error */
  895.             if (verbosity(3))
  896.                 printf("density error\n");
  897.             goto error;
  898.         }
  899.         rx2.es = RX_USEL(unit) | RX_DRDY(unit) | RX_DENSITY(unit) | (rx_mode(RX_RX02) ? RX_RX02_ID : 0);
  900.         if (verbosity(3))
  901.             printf("read status: status = %04o\n", rx2.es);
  902.         break;
  903.  
  904.     /* read error code - 111  */ /***************/
  905.     /*    func            */
  906.     case RX_RDEC:
  907.         if (verbose)
  908.             printf("read error code\n");
  909.         if (rx_xfer_mode(RX_XFER_DMA)) {
  910.             rx_put(rx2.err_code, RX_NBITS(), RX_WAIT);
  911.             rx_put(rx2.wc, 8, RX_WAIT);
  912.             printf("error_code = %03o, wordcnt = %03o -> word 1 = %06o\n", rx2.err_code, rx2.wc, (rx2.wc << 8) | rx2.err_code);
  913.  
  914.             rx_put(rx2.drv[0].ta, 8, RX_WAIT);
  915.             rx_put(rx2.drv[1].ta, 8, RX_WAIT);
  916.             printf("rx[0].track = %04o (%d.), rx[1].track = %04o (%d.) -> word 2 = %06o,\n",
  917.                 rx2.drv[0].ta, rx2.drv[0].ta, rx2.drv[1].ta, rx2.drv[1].ta, (rx2.drv[1].ta << 8) | rx2.drv[0].ta);
  918.  
  919.             rx_put(rx2.ta, 8, RX_WAIT);
  920.             rx_put(rx2.sa, 8, RX_WAIT);
  921.             printf("track = %04o (%d.), sector = %03o (%d.) -> word 3 = %06o\n",
  922.                 rx2.ta, rx2.ta, rx2.sa, rx2.sa, (rx2.sa << 8) + rx2.ta);
  923.  
  924.             rx_put(((unit) ? 0200 : 0) | (RX_DRDY(unit) ? 040 : 0)
  925.                 | ((rx2.drv[1].density == DENSITY_SD) ? 0 : 0100)
  926.                 | ((rx2.drv[0].density == DENSITY_SD) ? 0 : 020)
  927.                 | ((rx2.cs & RX_DEN) ? 1 : 0), 8, RX_WAIT); /* *** */
  928.             rx_put(rx2.unit->ta, 8, RX_NOWAIT);
  929.             printf("misc stat = %03o, rx[unit].track = %04o (%d.) -> word 4 = %06o\n",
  930.                 ((unit) ? 0200 : 0) | (RX_DRDY(unit) ? 040 : 0)
  931.                 | ((rx2.drv[1].density == DENSITY_SD) ? 0 : 0100)
  932.                 | ((rx2.drv[0].density == DENSITY_SD) ? 0 : 020)
  933.                 | ((rx2.cs & RX_DEN) ? 1 : 0),
  934.                 rx2.unit->ta, rx2.unit->ta,
  935.                 (rx2.unit->ta << 8) | ((unit) ? 0200 : 0) | (RX_DRDY(unit) ? 040 : 0)
  936.                 | ((rx2.drv[1].density == DENSITY_SD) ? 0 : 0100)
  937.                 | ((rx2.drv[0].density == DENSITY_SD) ? 0 : 020)
  938.                 | ((rx2.cs & RX_DEN) ? 1 : 0));
  939.  
  940.             rx2.es = RX_USEL(unit) | RX_DRDY(unit) | RX_DENSITY(unit);
  941.         } // else
  942.           //  rx_put(rx2.err_code, RX_NBITS(), RX_NOWAIT);
  943.         break;            
  944.     }
  945.  
  946. done:
  947.     rx_put_es(rx2.es);
  948.     return;
  949. error:
  950.     rx_if_set(RX_ERROR);
  951.     goto done;
  952. }
  953.  
  954. void rx_init() {
  955.     int offset;
  956.  
  957.     rx_if_clr(RX_DONE);
  958.     printf("Initializing...\n");
  959.     rxdelay(RX_INIT_TIME);
  960.     rx_if_set(RX_INITFF);
  961.     rx_if_clr(RX_INITFF);
  962.     if (rx_if_get(RX_INIT))
  963.         printf("  held by RX_INIT. Waiting... \n");
  964.     while (rx_if_get(RX_INIT)) {
  965.         sleep(1);
  966.         if (intr_signal > 0)
  967.             prompt();
  968.         rx_if_set(RX_INITFF);
  969.         rx_if_clr(RX_INITFF);
  970.     }
  971.  
  972.     rx2.cs = 0;
  973.     rx2.db = 0;
  974.     rx2.ta = 1;
  975.     rx2.sa = 1;
  976.     rx2.wc = 0;
  977.     rx2.ba = 0;
  978.     rx2.es = 0;
  979.     rx2.err_code = 0;
  980.     rx2.unit = &rx2.drv[0];
  981.     rx2.drv[0].ta = rx2.ta;
  982.     rx2.drv[1].ta = 0;
  983.  
  984.     /* copy boot sector into the buffer */
  985.     offset = (rx2.ta*NSECTS + (rx2.sa - 1))*sec_size(rx2.drv[0].density);
  986.     memcpy(buffer, &rx2.drv[0].image[offset], sec_size(rx2.drv[0].density));
  987.  
  988.     rx_if_clr(RX_ERROR);
  989.     rx2.err_code = 0;
  990.     rx2.es = RX_DRDY(0) | RX_DENSITY(0) | RX_DELDAT(0) | RX_ID | (rx_mode(RX_RX02) ? RX_RX02_ID : 0);
  991.     rx_put_es(rx2.es);
  992. }
  993.  
  994. void attach_file(int drv) {
  995.     struct drv_t *unit;
  996.     struct stat stat_buf;
  997.  
  998.     unit = &rx2.drv[drv];
  999.  
  1000.     /* if the unit is attached to file then close it */
  1001.     if (unit->fd >= 0) {
  1002.         if(close(unit->fd))
  1003.             perror("rxm: attach_file: close");
  1004.         else {
  1005.             unit->fd = -1;  /* make it a non-fd */
  1006.             if (verbose)
  1007.                 printf("file successfully closed\n");
  1008.         }
  1009.     }
  1010.  
  1011.     /* attempt to open the new image file */
  1012.     /*    a null file name or a file name of a single . is considered a message to detach and not reopen */
  1013.     /*    if no file is found, create one of the appropriate size */
  1014.     if (unit->fn[0] != '.' || unit->fn[0] != '\0' || unit->fn[1] != '\0') {
  1015.         unit->fd = open(unit->fn, O_RDWR);
  1016.         if (unit->fd < 0) {
  1017.             if (errno == ENOENT) {
  1018.                 unit->fd = open(unit->fn, O_RDWR | O_CREAT, 0664);
  1019.                 if (unit->fd < 0) {
  1020.                     printf("rxm: attach_file: could not create disk %d image file\n", drv);
  1021.                     unit->fd = -1;
  1022.                 } else {
  1023.                     memset(unit->image, 0, dsk_size(unit->density));
  1024.                     write(unit->fd, unit->image, dsk_size(unit->density));
  1025.                 }
  1026.             } else {
  1027.                 printf("rxm: attach_file: could not open disk %d image file\n", drv);
  1028.                 unit->fd = -1;
  1029.             }
  1030.         } else {
  1031.             if (verbose)
  1032.                 printf("rxm: attach_file: file %s attached OK as drive %d\n", unit->fn, drv);
  1033.         }
  1034.     } else {
  1035.         unit->fd = -1;
  1036.         if (verbose)
  1037.             printf("rxm: attach_file: file not attached to disk %d because the name was . or NULL\n", drv);
  1038.     }
  1039.  
  1040.     /* if a file was opened, check that it is the right size */
  1041.     /*   if it is the right size then all is well */
  1042.     /*   if it is not the right size and it is small and we have set the option to expand */
  1043.     /*      then expand the image to the correct size for this density */
  1044.     if (unit->fd >= 0) {
  1045.         if (fstat(unit->fd, &stat_buf) >= 0) {
  1046.              /* check for a block special file meaning this is a real floppy */
  1047.              if (stat_buf.st_mode & S_IFBLK) {
  1048.                  read(unit->fd, unit->image, dsk_size(unit->density));
  1049.              }
  1050.              /* check for a size miss-match */
  1051.              else if (stat_buf.st_size != dsk_size(unit->density)) {
  1052.                  printf("rxm: file image size does not equal disk %d image size\n", drv);
  1053.                  if (stat_buf.st_size > dsk_size(unit->density) || !expand_image) {
  1054.                      close(unit->fd);
  1055.                      unit->fd = -1;
  1056.                      printf("rxm: image not attached\n");
  1057.                  } else {
  1058.                      printf("rxm: image file expanded\n");
  1059.                      memset(unit->image, 0, dsk_size(unit->density));
  1060.                      read(unit->fd, unit->image, stat_buf.st_size);      
  1061.                      lseek(unit->fd, 0, SEEK_SET);
  1062.                      write(unit->fd, unit->image, dsk_size(unit->density));
  1063.                  }
  1064.              } else {
  1065.                  read(unit->fd, unit->image, dsk_size(unit->density));
  1066.              }
  1067.         } else
  1068.              printf("rxm: the image file was opened for disk %d, but the fstat failed\n", drv);
  1069.     }
  1070. }
  1071.  
  1072. char *func_name[2][8] = { { "Fill Buffer      ", /* RX01 */
  1073.                             "Empty Buffer     ",
  1074.                             "Write Sector     ",
  1075.                             "Read Sector      ",
  1076.                             "NOP              ",
  1077.                             "Read Status      ",
  1078.                             "Write DD Sector  ",
  1079.                             "Read Error Code  " },
  1080.                           { "Fill Buffer      ", /* RX02 */
  1081.                             "Empty Buffer     ",
  1082.                             "Write Sector     ",
  1083.                             "Read Sector      ",
  1084.                             "Set Media Density",
  1085.                             "Read Status      ",
  1086.                             "Write DD Sector  ",
  1087.                             "Read Error Code  " }
  1088. };
  1089.  
  1090. void rx2_reg_dump(void) {
  1091.     int i;
  1092.  
  1093.     printf("RX02 Emulator V%d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION);
  1094.     printf("%s ", rx_mode(2) ? "in native mode" : "in RX01 mode");
  1095.     printf("with a %s interface\n", rx_xfer_mode(RX_XFER_DMA) ? "DMA" : "PIO");
  1096.  
  1097.     printf("%s\n", rcsid);
  1098.  
  1099.     printf("RX2CS = %06o\n  ", rx2.cs);
  1100.     if (rx2.cs & RX_GO)
  1101.         printf("GO ");
  1102.     printf("func = %03o ", (rx2.cs & RX_FUNC) >> 1);
  1103.     printf("unit = %d ", (rx2.cs & RX_UNIT) ? 1 : 0);
  1104.     if (rx2.cs & RX_IE)
  1105.         printf("IE ");
  1106.     printf("%s ", (rx2.cs & RX_DEN) ? "DD" : "SD");
  1107.     printf("ex addr = %o ", (rx2.cs & RX_EXADDR) >> 12);
  1108.     if (rx2.cs & RX_CS_INIT)
  1109.         printf("INIT ");
  1110.     printf("\n");
  1111.  
  1112.     printf("RX2TA = %d. (%03o)\n", rx2.ta, rx2.ta);
  1113.     printf("RX2SA = %d. (%03o)\n", rx2.sa, rx2.sa);
  1114.     printf("RX2WC = %d. (%03o)\n", rx2.wc, rx2.wc);
  1115.     printf("RX2ES = %04o\n", rx2.es);
  1116.     printf("\nDrive 0: track = %d. (%03o)\n", rx2.drv[0].ta, rx2.drv[0].ta);
  1117.     printf("         %s\n", (rx2.drv[0].density == 1) ? "single density" : "double density");
  1118.     if (RX_DRDY(0))
  1119.         printf("         file name = %s\n", rx2.drv[0].fn);
  1120.     else
  1121.         printf("         drive is not attached to a file\n");
  1122.     printf("\nDrive 1: track = %d. (%03o)\n", rx2.drv[1].ta, rx2.drv[1].ta);
  1123.     printf("         %s\n", (rx2.drv[1].density == 1) ? "single density" : "double density");
  1124.     if (RX_DRDY(1))
  1125.         printf("         file name = %s\n", rx2.drv[1].fn);
  1126.     else
  1127.         printf("         drive is not attached to a file\n");
  1128.     printf("\nFunction counts\n");
  1129.     for (i = 0; i < 8; i++)
  1130.         printf("  %01o %s %d\n", i, func_name[rx_mode(RX_RX01) ? 0 : 1][i], func_count[i]);
  1131. }
  1132.  
  1133. void prompt(void){
  1134.     char command[255];
  1135.     char com_s[10];
  1136.     char fn_s[255];
  1137.     char density_s[10];
  1138.     int drv;
  1139.  
  1140.     if (!interruptable)
  1141.         printf("\nWARNING! Prompting when NOT INTERRUPTABLE.\n"
  1142.                "Loss of data is possible!\n");
  1143.  
  1144.     printf("\ncommand prompt\n");
  1145.     printf(" c\n");
  1146.     printf(" 0 [fn | .] [SD | DD]\n");
  1147.     printf(" 1 [fn | .] [SD | DD]\n");
  1148.     printf(" p\n");
  1149.     printf(" s\n");
  1150.     printf(" v 0 | 1 | 2 | 3\n");
  1151.     printf(" q\n\n");
  1152.  
  1153.     do {
  1154.         com_s[0] = '\0';
  1155.         fn_s[0] = '\0';
  1156.         density_s[0] = '\0';
  1157.         if (!interruptable)
  1158.             printf("NOT INTERRUPTABLE ");
  1159.         printf("> ");
  1160.         fgets(command, sizeof(command), stdin);
  1161.         sscanf(command, "%10s %255s %10s", com_s, fn_s, density_s);
  1162.         switch(com_s[0]) {
  1163.         case 'c':
  1164.         case 'C':
  1165.             break;
  1166.         case '0':
  1167.         case '1':
  1168.             drv = (com_s[0] == '0') ? 0 : 1;
  1169.             strncpy(rx2.drv[drv].fn, fn_s, sizeof(rx2.drv[0].fn));
  1170.             if (strcmp("SD", density_s) == 0)
  1171.                 rx2.drv[drv].density = DENSITY_SD;
  1172.             else if (strcmp("DD", density_s) == 0)
  1173.                 rx2.drv[drv].density = DENSITY_DD;
  1174.             else if (rx2.type == RX_RX02)
  1175.                 rx2.drv[drv].density = DENSITY_DD;
  1176.             else
  1177.                 rx2.drv[drv].density = DENSITY_SD;
  1178.             attach_file(drv);
  1179.             break;
  1180.         case 'p':
  1181.         case 'P':
  1182.             rx2_reg_dump();
  1183.             break;
  1184.         case 's':
  1185.         case 'S':
  1186.             for (drv = 0; drv < 2; drv++) {
  1187.                 printf("Drive %d: ", drv);
  1188.                 if (rx2.drv[drv].fd == -1)
  1189.                     printf("not attached\n");
  1190.                 else
  1191.                     printf("(%s) %s\n", (rx2.drv[drv].density == DENSITY_SD) ? "SD" : "DD", rx2.drv[drv].fn);
  1192.             }
  1193.             break;
  1194.         case 'v':
  1195.         case 'V':
  1196.             if (fn_s[0] == '0')
  1197.                 verbose = 0;
  1198.             else if (fn_s[0] == '1')
  1199.                 verbose = 1;
  1200.             else if (fn_s[0] == '2')
  1201.                 verbose = 2;
  1202.             else if (fn_s[0] == '3')
  1203.                 verbose = 3;
  1204.             else
  1205.                 printf("bad parameter for v command\n");
  1206.             printf("verbose flag == %d\n", verbose);
  1207.             break;
  1208.         case 'q':
  1209.         case 'Q':
  1210.             exit(0);
  1211.         default:
  1212.             printf("error\n");
  1213.         }
  1214.     } while (com_s[0] != 'c' && com_s[0] != 'C');
  1215.     printf("\n.");
  1216.     fflush(NULL);
  1217.     intr_signal = 0;
  1218. }
  1219.  
  1220. void intr_handler(int signum) {
  1221.     intr_signal += 1;
  1222.     if (verbose) {
  1223.         printf(" (intr_signal = %d)\n", intr_signal);
  1224.         fflush(NULL);
  1225.     }
  1226.     if (intr_signal >= 10)  /* should never occur */
  1227.         exit(0);
  1228.     signal(SIGINT, intr_handler);
  1229. }
  1230.  
  1231. int main(int argc, char * const argv[]) {
  1232.  
  1233.     int c;
  1234.     int drv;
  1235.     int offset;
  1236.  
  1237.     printf("Digital RX02 Disk Simulator V%d.%d.%d\n%s\n", MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION, rcsid);
  1238.  
  1239.     verbose = 0;
  1240.     expand_image = 0;
  1241.     io_base = 0x378;
  1242.  
  1243.     rx2.type = RX_RX02;
  1244. //  rx2.xfer_mode = rx_if_get(RX_DMA) ? RX_XFER_DMA : RX_XFER_PIO;
  1245.     rx2.xfer_mode = RX_XFER_DMA;
  1246.     rx2.cs = 0;
  1247.     rx2.db = 0;
  1248.     rx2.ta = 1;
  1249.     rx2.sa = 1;
  1250.     rx2.wc = 0;
  1251.     rx2.ba = 0;
  1252.     rx2.es = 0;
  1253.     rx2.err_code = 0;
  1254.     rx2.unit = &rx2.drv[0];
  1255.  
  1256.  
  1257.     rx2.drv[0].ta = rx2.ta;
  1258.     rx2.drv[0].density = DENSITY_DD;
  1259.     strncpy(rx2.drv[0].fn, RX0_IMAGE, sizeof(rx2.drv[0].fn));
  1260.     rx2.drv[0].fd = -1;
  1261.     memset(rx2.drv[0].image, 0, sizeof(rx2.drv[0].image));
  1262.  
  1263.     rx2.drv[1].ta = 0;
  1264.     rx2.drv[1].density = DENSITY_DD;
  1265.     strncpy(rx2.drv[1].fn, RX1_IMAGE, sizeof(rx2.drv[1].fn));
  1266.     rx2.drv[1].fd = -1;
  1267.     memset(rx2.drv[1].image, 0, sizeof(rx2.drv[1].image));
  1268.  
  1269.     memset(buffer, 0, sizeof(buffer));
  1270.  
  1271.     memset(dd_sec_map, NORMAL_DATA, sizeof(dd_sec_map));
  1272.  
  1273.     rx2.es = RX_DRDY(0) | RX_DENSITY(0) | RX_ID | (rx_mode(RX_RX02) ? RX_RX02_ID : 0); /* drive ready */
  1274.  
  1275.     drv = 0;  /* initial options for drive 0 */
  1276.     do {
  1277.         c = getopt(argc, argv, "t:0:1:d:p:vhx");
  1278.         switch(c) {
  1279.         case 't':    /* set drive type */
  1280.             if (verbose)
  1281.                 printf("option: t (set drive type)\n");
  1282.             if (optarg != NULL && strcmp("RX01", optarg) == 0) {
  1283.                 if (verbose)
  1284.                     printf("simulating RX01 drive\n");
  1285.                 rx2.type = RX_RX01;
  1286.                 rx2.xfer_mode = RX_XFER_PIO;
  1287.                 if (verbose)
  1288.                     printf("simulating PIO interface (RX8E, RXV11, RX11)\n");
  1289.                 rx2.drv[0].density = DENSITY_SD;
  1290.                 rx2.drv[1].density = DENSITY_SD;
  1291.             } else if (optarg != NULL && strcmp("RX02", optarg) == 0) {
  1292.                 if (verbose)
  1293.                     printf("simulating RX02 drive\n");
  1294.                 rx2.type = RX_RX02;
  1295.             /* this is really not necessary if the DMA signal line was hooked up */
  1296.             } else if (optarg != NULL && strcmp("PIO", optarg) == 0) {
  1297.                 if (verbose)
  1298.                     printf("simulating PIO interface (RX8E, RXV11, RX11)\n");
  1299.                 rx2.xfer_mode = RX_XFER_PIO;
  1300.             } else if (optarg != NULL && strcmp("DMA", optarg) == 0) {
  1301.                 if (rx2.type == RX_RX01) {
  1302.                     printf("rxm: invalid xfer mode for an RX01\n");
  1303.                     break;
  1304.                 }
  1305.                 if (verbose)
  1306.                     printf("simulating DMA interface (RXV21, RX211)\n");
  1307.                 rx2.xfer_mode = RX_XFER_DMA;
  1308.             } else
  1309.                 printf("rxm: invalid drive type or transfer mode\n");
  1310.             break;
  1311.         case '0':    /* set filename for drive 0 or 1 */
  1312.         case '1':
  1313.             drv = (c == '0') ? 0 : 1;
  1314.             if (verbose)
  1315.                 printf("option: %d (set drive %d file name)\n", drv, drv);
  1316.             if (optarg != NULL)
  1317.                 strncpy(rx2.drv[drv].fn, optarg, sizeof(rx2.drv[drv].fn));
  1318.             else
  1319.                 printf("rxm: no file name\n");
  1320.             if (verbose)
  1321.                 printf("drive %d file name = %s\n", drv, rx2.drv[drv].fn);
  1322.             break;
  1323.         case 'd':    /* set floppy density in drive */
  1324.             if (verbose)
  1325.                 printf("option: d (set floppy density in drive %d)\n", drv);
  1326.             if (optarg != NULL && strcmp("SD", optarg) == 0)
  1327.                 rx2.drv[drv].density = DENSITY_SD;
  1328.             else if (optarg != NULL && strcmp("DD", optarg) == 0)
  1329.                 rx2.drv[drv].density = DENSITY_DD;
  1330.             else
  1331.                 printf("rxm: bad density value\n");
  1332.             if (verbose)
  1333.                 printf("drive %d density set to %s\n", drv, (rx2.drv[drv].density == DENSITY_SD) ? "SD" : "DD");
  1334.             if (rx2.type == 1 && rx2.drv[drv].density == DENSITY_DD) {
  1335.                 printf("rxm: WARNING: attempt to set double density in an RX01. Ignored.\n");
  1336.                 rx2.drv[drv].density = DENSITY_SD;
  1337.             }
  1338.             break;
  1339.     case 'p':
  1340.             if (verbose)
  1341.                 printf("option: p (set the parallel port address)\n");
  1342.             if (optarg != NULL && strcmp("0x378", optarg) == 0)
  1343.                 io_base = 0x378;
  1344.             else if (optarg != NULL && strcmp("0x278", optarg) == 0)
  1345.                 io_base = 0x278;
  1346.             else
  1347.                 printf("rxm: bad parallel port address\n");
  1348.             break;
  1349.         case 'h':
  1350.             printf("Usage: rxm [OPTION]...\n");
  1351.             printf("Emulate a DEC RX02 Floppy Drive System\n");
  1352.         printf("Using parallel port at 0x%04x\n", IO_BASE);
  1353.             printf("\n");
  1354.             printf("  -0 FILENAME   use FILENAME for drive 0 image\n");
  1355.             printf("  -1 FILENAME   use FILENAME for drive 1 image\n");
  1356.             printf("  -x     expand images that are too small\n");
  1357.             printf("  -d SD | DD   act as though previous image was of density\n");
  1358.             printf("  -h    print help message and exit\n");
  1359.             printf("  -t RX01 | RX02 | DMA | PIO select emulation type and tranfer mode\n");
  1360.             printf("  -p ADDRESS set the parallel port address\n");
  1361.             printf("  -v    display extra information\n");
  1362.             printf("\n");
  1363.             exit(0);
  1364.             break;
  1365.         case 'v':
  1366.             verbose += 1;
  1367.             printf("entering verbose mode\n");
  1368.             break;
  1369.         case 'x':
  1370.             expand_image = 1;
  1371.             if (verbose)
  1372.                 printf("image expansion enabled\n");
  1373.             break;
  1374.         case -1:
  1375.             break;
  1376.         }
  1377.     } while (c != -1);
  1378.  
  1379. #if defined __linux__
  1380.     if (ioperm(IO_DATA, IO_LEN, 1)) {
  1381.         perror("rxm: ioperm");
  1382.         exit(-1);
  1383.     }
  1384. #elif defined __NetBSD__
  1385.     if (i386_get_ioperm(iomap)) {
  1386.         perror("rxm: i386_get_ioperm");
  1387.         exit(-1);
  1388.     }
  1389.     iomap[IOMAP_OFFSET] &= ~IOMAP_BITMASK;
  1390.     if (i386_set_ioperm(iomap)) {
  1391.         perror("rxm: i386_set_ioperm");
  1392.         exit(-1);
  1393.     }
  1394. #else
  1395. #error Present system not supported
  1396. #endif
  1397.  
  1398.     printf("  %lld cycles since boot\n", rdtsc());
  1399.  
  1400.     if (verbose)
  1401.         printf("simulating %d bit interface\n", RX_NBITS());
  1402.  
  1403.     for (drv = 0; drv < NUNITS; drv++) {
  1404.         attach_file(drv);
  1405.     }
  1406.  
  1407.     intr_signal = 0;
  1408.     interruptable = 0;
  1409.     if (signal(SIGINT, intr_handler) == SIG_ERR) {
  1410.         printf("rxm: error when setting SIGINT handler\n");
  1411.         exit(-1);
  1412.     }
  1413.  
  1414.     /* copy boot sector into the buffer */
  1415.     offset = (rx2.ta*NSECTS + (rx2.sa - 1))*sec_size(rx2.drv[0].density);
  1416.     memcpy(buffer, &rx2.drv[0].image[offset], sec_size(rx2.drv[0].density));
  1417.  
  1418.     rx_if_clr(0xffffffff); /* clear all interface bits */
  1419.  
  1420.     while (1) {
  1421.         do_func();
  1422.         if (rx_if_get(RX_INIT)) {
  1423.             rx_init();
  1424.         }
  1425.     }
  1426. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement