home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Boot_Images / 2.11_on_rl02 / pdpsim.tz / pdpsim / pdp18b_rf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-29  |  7.7 KB  |  251 lines

  1. /* pdp18b_rf.c: fixed head disk simulator
  2.  
  3.    Copyright (c) 1996, Robert M Supnik, Digital Equipment Corporation
  4.    Commercial use prohibited
  5.  
  6.    rf        RF09/RF09 for PDP-9
  7.         RF15/RS09 for PDP-15
  8.  
  9.    The RFxx is a head-per-track disk.  It uses the multicycle data break
  10.    facility.  To minimize overhead, the entire RFxx is buffered in memory.
  11.  
  12.    Two timing parameters are provided:
  13.  
  14.    rf_time    Interword timing.  If 0, treated as 1.
  15.    rf_burst    Burst mode.  If 0, DMA occurs cycle by cycle; otherwise,
  16.         DMA occurs in a burst.
  17. */
  18.  
  19. #ifndef PDP9
  20. #define PDP9    0
  21. #endif
  22.  
  23. #include "pdp18b_defs.h"
  24. #include <math.h>
  25.  
  26. /* Constants */
  27.  
  28. #define RF_NUMWD    2048                /* words/track */
  29. #define RF_NUMTR    128                /* tracks/disk */
  30. #define RF_NUMDK    8                /* disks/controller */
  31. #define RF_SIZE        (RF_NUMDK * RF_NUMTR * RF_NUMWD) /* words/drive */
  32. #define RF_WMASK    (RF_NUMWD - 1)            /* word mask */
  33. #define RF_WC        036                /* word count */
  34. #define RF_MA        037                /* mem address */
  35.  
  36. /* Function/status register */
  37.  
  38. #define RFS_ERR        0400000                /* error */
  39. #define RFS_HDW        0200000                /* hardware error */
  40. #define RFS_APE        0100000                /* addr parity error */
  41. #define RFS_MXF        0040000                /* missed transfer */
  42. #define RFS_WCE        0020000                /* write check error */
  43. #define RFS_DPE        0010000                /* data parity error */
  44. #define RFS_WLO        0004000                /* write lock error */
  45. #define RFS_NED        0002000                /* non-existent disk */
  46. #define RFS_DCH        0001000                /* data chan timing */
  47. #define RFS_PGE        0000400                /* programming error */
  48. #define RFS_DON        0000200                /* transfer complete */
  49. #define RFS_V_FNC    1                /* function */
  50. #define RFS_M_FNC    03
  51. #define RFS_FNC        (RFS_M_FNC << RFS_V_FNC)
  52. #define  FN_NOP        0
  53. #define     FN_READ    1
  54. #define  FN_WRITE    2
  55. #define  FN_WCHK    3
  56. #define RFS_IE        0000001                /* interrupt enable */
  57.  
  58. #define RFS_CLR        0000170                /* always clear */
  59. #define RFS_EFLGS    (RFS_HDW | RFS_APE | RFS_MXF | RFS_WCE | \
  60.              RFS_DPE | RFS_WLO | RFS_NED )    /* error flags */
  61. #define MIN_TIME(x)    ((x > 0)? (x): 1)
  62. #define GET_FNC(x)    (((x) >> RFS_V_FNC) & RFS_M_FNC)
  63. #define GET_POS(x)    ((int) fmod (sim_gtime() / ((double) (MIN_TIME(x))), \
  64.             ((double) RF_NUMWD)))
  65. #define RF_BUSY        (sim_is_active (&rf_unit))
  66.  
  67. extern unsigned int M[];
  68. extern int int_req;
  69. extern UNIT cpu_unit;
  70. int rf_sta = 0;                        /* status register */
  71. int rf_da = 0;                        /* disk address */
  72. int rf_dbuf = 0;                    /* data buffer */
  73. int rf_wlk[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };        /* write lock */
  74. int rf_time = 10;                    /* inter-word time */
  75. int rf_burst = 1;                    /* burst mode flag */
  76. int rf_stopioe = 1;                    /* stop on error */
  77. int rf_svc (UNIT *uptr);
  78. int rf_reset (DEVICE *dptr);
  79. int rf_updsta (int new);
  80. extern int sim_activate (UNIT *uptr, int interval);
  81. extern int sim_cancel (UNIT *uptr);
  82. extern int sim_is_active (UNIT *uptr);
  83. extern double sim_gtime(void);
  84.  
  85. /* RF data structures
  86.  
  87.    rf_dev    RF device descriptor
  88.    rf_unit    RF unit descriptor
  89.    rf_reg    RF register list
  90. */
  91.  
  92. UNIT rf_unit =
  93.     { UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
  94.     RF_SIZE) };
  95.  
  96. REG rf_reg[] = {
  97.     { ORDATA (STA, rf_sta, 18) },
  98.     { ORDATA (DA, rf_da, 21) },
  99.     { ORDATA (MA, M[RF_MA], 18) },
  100.     { ORDATA (WC, M[RF_WC], 18) },
  101.     { ORDATA (BUF, rf_dbuf, 18) },
  102.     { FLDATA (INT, int_req, INT_V_RF) },
  103.     { ORDATA (WLK0, rf_wlk[0], 16) },
  104.     { ORDATA (WLK1, rf_wlk[1], 16) },
  105.     { ORDATA (WLK2, rf_wlk[2], 16) },
  106.     { ORDATA (WLK3, rf_wlk[3], 16) },
  107.     { ORDATA (WLK4, rf_wlk[4], 16) },
  108.     { ORDATA (WLK5, rf_wlk[5], 16) },
  109.     { ORDATA (WLK6, rf_wlk[6], 16) },
  110.     { ORDATA (WLK7, rf_wlk[7], 16) },
  111.     { DRDATA (TIME, rf_time, 24), PV_LEFT },
  112.     { FLDATA (BURST, rf_burst, 0) },
  113.     { FLDATA (STOP_IOE, rf_stopioe, 0) },
  114.     { NULL }  };
  115.  
  116. DEVICE rf_dev = {
  117.     "RF", &rf_unit, rf_reg, NULL,
  118.     1, 8, 21, 1, 8, 18,
  119.     NULL, NULL, &rf_reset,
  120.     NULL, NULL, NULL };
  121.  
  122. /* IOT routines */
  123.  
  124. int rf70 (int pulse, int AC)
  125. {
  126. int t;
  127.  
  128. if (pulse == 001)                    /* DSSF */
  129.     return (rf_sta & (RFS_ERR | RFS_DON))? IOT_SKP + AC: AC;
  130. if (pulse == 021) rf_reset (&rf_dev);            /* DSCC */
  131. if ((pulse & 061) == 041) {                /* DSCF */
  132.     if (RF_BUSY) rf_sta = rf_sta | RFS_PGE;        /* busy inhibits */
  133.     else rf_sta = rf_sta & ~(RFS_FNC | RFS_IE);  }    /* clear func */
  134. if (pulse == 002)  {                    /* DRBR */
  135.     if (RF_BUSY) rf_sta = rf_sta | RFS_PGE;        /* busy sets PGE */
  136.     return AC | rf_dbuf;  }
  137. if (pulse == 022) {                    /* DRAL */
  138.     if (RF_BUSY) rf_sta = rf_sta | RFS_PGE;        /* busy sets PGE */
  139.     return rf_da & 0777777;  }
  140. if (pulse == 062) {                    /* DRAH */
  141.     if (RF_BUSY) rf_sta = rf_sta | RFS_PGE;        /* busy sets PGE */
  142.     return (rf_da >> 18) | ((rf_sta & RFS_NED)? 010: 0);  }
  143. if ((pulse & 062) == 042) {                /* DSFX */
  144.     if (RF_BUSY) rf_sta = rf_sta | RFS_PGE;        /* busy inhibits */
  145.     else rf_sta = rf_sta ^ (AC & (RFS_FNC | RFS_IE));  } /* xor func */
  146. if (pulse == 004) {                    /* DLBR */
  147.     if (RF_BUSY) rf_sta = rf_sta | RFS_PGE;        /* busy inhibits */
  148.     else rf_dbuf = AC;  }
  149. if (pulse == 024) {                    /* DLAL */
  150.     if (RF_BUSY) rf_sta = rf_sta | RFS_PGE;        /* busy inhibits */
  151.     else rf_da = (rf_da & ~0777777) | AC;  }
  152. if (pulse == 064) {                    /* DLAH */
  153.     if (RF_BUSY) rf_sta = rf_sta | RFS_PGE;        /* busy inhibits */
  154.     else rf_da = (rf_da & 0777777) | ((AC & 07) << 18);  }
  155. if ((pulse & 064) == 044) {                /* DSCN */
  156.     if (RF_BUSY) rf_sta = rf_sta | RFS_PGE;        /* busy inhibits */
  157.     else if (GET_FNC (rf_sta) != FN_NOP) {
  158.         t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new */
  159.         if (t < 0) t = t + RF_NUMWD;             /* wrap around? */
  160.         sim_activate (&rf_unit, t * rf_time);  }  }  /* schedule op */
  161. rf_updsta (0);                        /* update status */
  162. return AC;
  163. }
  164.  
  165. int rf72 (int pulse, int AC)
  166. {
  167. if (pulse == 002) return AC | GET_POS (rf_time) |    /* DLOK */
  168.     (sim_is_active (&rf_unit)? 0400000: 0);
  169. if (pulse == 042) {                    /* DSCD */
  170.     if (RF_BUSY) rf_sta = rf_sta | RFS_PGE;        /* busy inhibits */
  171.     else rf_sta = 0;
  172.     rf_updsta (0);  }
  173. if (pulse == 0062) {                    /* DSRS */
  174.     if (RF_BUSY) rf_sta = rf_sta | RFS_PGE;        /* busy sets PGE */
  175.     return rf_updsta (0);  }
  176. return AC;
  177. }
  178.  
  179. /* Unit service
  180.  
  181.    This code assumes the entire disk is buffered.
  182. */
  183.  
  184. int rf_svc (UNIT *uptr)
  185. {
  186. int f, pa, d, t;
  187.  
  188. if ((uptr -> flags & UNIT_BUF) == 0) {            /* not buf? abort */
  189.     rf_updsta (RFS_NED | RFS_DON);            /* set nxd, done */
  190.     return IORETURN (rf_stopioe, SCPE_UNATT);  }
  191.  
  192. f = GET_FNC (rf_sta);                    /* get function */
  193. do {     pa = M[RF_MA] = (M[RF_MA] + 1) & ADDRMASK;    /* incr mem addr */
  194.     if ((f == FN_READ) && MEM_ADDR_OK (pa))        /* read? */
  195.         M[pa] = *(((int *) uptr -> filebuf) + rf_da);
  196.     if ((f == FN_WCHK) &&                /* write check? */
  197.         (M[pa] != *(((int *) uptr -> filebuf) + rf_da))) {
  198.         rf_updsta (RFS_WCE);            /* flag error */
  199.         break;  }
  200.     if (f == FN_WRITE) {                /* write? */
  201.         d = (rf_da >> 18) & 07;            /* disk */
  202.         t = (rf_da >> 14) & 017;        /* track groups */
  203.         if ((rf_wlk[d] >> t) & 1) {        /* write locked? */
  204.             rf_updsta (RFS_WLO);
  205.             break;  }
  206.         else {    *(((int *) uptr -> filebuf) + rf_da) = M[pa];
  207.             if (rf_da >= uptr -> hwmark)
  208.                 uptr -> hwmark = rf_da + 1;  }  }
  209.     rf_da = rf_da + 1;                /* incr disk addr */
  210.     if (rf_da > RF_SIZE) {                /* disk overflow? */
  211.         rf_da = 0;
  212.         rf_updsta (RFS_NED);            /* nx disk error */
  213.         break;  }
  214.     M[RF_WC] = (M[RF_WC] + 1) & 0777777;  }        /* incr word count */
  215. while ((M[RF_WC] != 0) && (rf_burst != 0));        /* brk if wc, no brst */
  216.  
  217. if ((M[RF_WC] != 0) && ((rf_sta & RFS_ERR) == 0))    /* more to do? */
  218.     sim_activate (&rf_unit, MIN_TIME (rf_time));    /* sched next */
  219. else rf_updsta (RFS_DON);
  220. return SCPE_OK;
  221. }
  222.  
  223. /* Update status */
  224.  
  225. int rf_updsta (int new)
  226. {
  227. rf_sta = (rf_sta | new) & ~(RFS_ERR | RFS_CLR);
  228. if (rf_sta & RFS_EFLGS) rf_sta = rf_sta | RFS_ERR;
  229. if ((rf_sta & (RFS_ERR | RFS_DON)) && (rf_sta & RFS_IE))
  230.      int_req = int_req | INT_RF;
  231. else int_req = int_req & ~INT_RF;
  232. return rf_sta;
  233. }
  234.  
  235. /* Reset routine */
  236.  
  237. int rf_reset (DEVICE *dptr)
  238. {
  239. rf_sta = rf_da = rf_dbuf = 0;
  240. rf_updsta (0);
  241. sim_cancel (&rf_unit);
  242. return SCPE_OK;
  243. }
  244.  
  245. /* IORS routine */
  246.  
  247. int rf_iors (void)
  248. {
  249. return ((rf_sta & (RFS_ERR | RFS_DON))? IOS_RF: 0);
  250. }
  251.