home *** CD-ROM | disk | FTP | other *** search
- /* NOVA moving head disk simulator
-
- Copyright (c) 1993, 1994, 1995, 1996,
- Robert M Supnik, Digital Equipment Corporation
- Commercial use prohibited
-
- dkp moving head disk
- */
-
- #include "nova_defs.h"
-
- #define DKP_NUMDR 4 /* #drives */
- #define DKP_NUMWD 256 /* words/sector */
- #define UNIT_V_ONLINE (UNIT_V_UF + 0) /* present */
- #define UNIT_V_WLK (UNIT_V_UF + 1) /* write locked */
- #define UNIT_V_DTYPE (UNIT_V_UF + 2) /* disk type */
- #define UNIT_M_DTYPE 7
- #define UNIT_V_AUTO (UNIT_V_UF + 5) /* autosize */
- #define UNIT_W_UF 6 /* saved flag width */
- #define UNIT_ONLINE (1 << UNIT_V_ONLINE)
- #define UNIT_WLK (1 << UNIT_V_WLK)
- #define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)
- #define UNIT_AUTO (1 << UNIT_V_AUTO)
- #define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
- #define FUNC u3 /* function */
- #define CYL u4 /* on cylinder */
-
- /* Unit, surface, sector, count register */
-
- #define USSC_V_COUNT 0 /* count */
- #define USSC_M_COUNT 017
- #define USSC_V_SECTOR 4 /* sector */
- #define USSC_M_SECTOR 017
- #define USSC_V_SURFACE 8 /* surface */
- #define USSC_M_SURFACE 077
- #define USSC_V_UNIT 14 /* unit */
- #define USSC_M_UNIT 03
- #define USSC_UNIT (USSC_M_UNIT << USSC_V_UNIT)
- #define GET_COUNT(x) (((x) >> USSC_V_COUNT) & USSC_M_COUNT)
- #define GET_SECT(x) (((x) >> USSC_V_SECTOR) & USSC_M_SECTOR)
- #define GET_SURF(x) (((x) >> USSC_V_SURFACE) & USSC_M_SURFACE)
- #define GET_UNIT(x) (((x) >> USSC_V_UNIT) & USSC_M_UNIT)
-
- /* Flags, command, cylinder register */
-
- #define FCCY_V_CYL 0 /* cylinder */
- #define FCCY_M_CYL 0377
- #define FCCY_V_CMD 8 /* command */
- #define FCCY_M_CMD 3
- #define FCCY_READ 0
- #define FCCY_WRITE 1
- #define FCCY_SEEK 2
- #define FCCY_RECAL 3
- #define FCCY_V_CEX 10 /* cyl extension */
- #define FCCY_CEX (1 << FCCY_V_CEX)
- #define FCCY_FLAGS 0174000 /* flags */
- #define GET_CMD(x) (((x) >> FCCY_V_CMD) & FCCY_M_CMD)
- #define GET_CYL(x) ((((x) >> FCCY_V_CYL) & FCCY_M_CYL) | \
- (((x) & FCCY_CEX) >> (FCCY_V_CEX - FCCY_V_CMD)))
- /* Status */
-
- #define STA_ERR 0000001 /* error */
- #define STA_DLT 0000002 /* data late */
- #define STA_CRC 0000004 /* crc error */
- #define STA_UNS 0000010 /* unsafe */
- #define STA_XCY 0000020 /* cross cylinder */
- #define STA_CYL 0000040 /* nx cylinder */
- #define STA_DRDY 0000100 /* drive ready */
- #define STA_SEEK3 0000200 /* seeking unit 3 */
- #define STA_SEEK2 0000400 /* seeking unit 2 */
- #define STA_SEEK1 0001000 /* seeking unit 1 */
- #define STA_SEEK0 0002000 /* seeking unit 0 */
- #define STA_SKDN3 0004000 /* seek done unit 3 */
- #define STA_SKDN2 0010000 /* seek done unit 2 */
- #define STA_SKDN1 0020000 /* seek done unit 1 */
- #define STA_SKDN0 0040000 /* seek done unit 0 */
- #define STA_DONE 0100000 /* operation done */
-
- #define STA_DYN (STA_DRDY | STA_CYL) /* set from unit */
- #define STA_EFLGS (STA_ERR | STA_DLT | STA_CRC | STA_UNS | \
- STA_XCY | STA_CYL) /* error flags */
- #define STA_DFLGS (STA_DONE | STA_SKDN0 | STA_SKDN1 | \
- STA_SKDN2 | STA_SKDN3) /* done flags */
-
- #define GET_SA(cy,sf,sc,t) (((((cy)*drv_tab[t].surf)+(sf))* \
- drv_tab[t].sect)+(sc))
-
- /* This controller supports many different disk drive types:
-
- type #sectors/ #surfaces/ #cylinders/
- surface cylinder drive
-
- floppy 8 1 77
- Diablo 31 12 2 203
- Century 111 6 10 203
- Diablo 44 12 4 408
- Century 114 12 20 203
-
- In theory, each drive can be a different type. The size field in
- each unit selects the drive capacity for each drive and thus the
- drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE.
- */
-
- #define FLP_DTYPE 0
- #define FLP_SECT 8
- #define FLP_SURF 1
- #define FLP_CYL 77
- #define FLP_SIZE (FLP_SECT * FLP_SURF * FLP_CYL * DKP_NUMWD)
-
- #define D31_DTYPE 1
- #define D31_SECT 12
- #define D31_SURF 2
- #define D31_CYL 203
- #define D31_SIZE (D31_SECT * D31_SURF * D31_CYL * DKP_NUMWD)
-
- #define C111_DTYPE 2
- #define C111_SECT 6
- #define C111_SURF 10
- #define C111_CYL 203
- #define C111_SIZE (C111_SECT * C111_SURF * C111_CYL * DKP_NUMWD)
-
- #define D44_DTYPE 3
- #define D44_SECT 12
- #define D44_SURF 4
- #define D44_CYL 408
- #define D44_SIZE (D44_SECT * D44_SURF * D44_CYL * DKP_NUMWD)
-
- #define C114_DTYPE 4
- #define C114_SECT 12
- #define C114_SURF 20
- #define C114_CYL 203
- #define C114_SIZE (C114_SECT * C114_SURF * C114_CYL * DKP_NUMWD)
-
- struct drvtyp {
- int sect; /* sectors */
- int surf; /* surfaces */
- int cyl; /* cylinders */
- int size; /* #blocks */
- };
-
- struct drvtyp drv_tab[] = {
- { FLP_SECT, FLP_SURF, FLP_CYL, FLP_SIZE },
- { D31_SECT, D31_SURF, D31_CYL, D31_SIZE },
- { C111_SECT, C111_SURF, C111_CYL, C111_SIZE },
- { D44_SECT, D44_SURF, D44_CYL, D44_SIZE },
- { C114_SECT, C114_SURF, C114_CYL, C114_SIZE },
- { 0 } };
-
- extern unsigned short M[];
- extern UNIT cpu_unit;
- extern int int_req, dev_busy, dev_done, dev_disable;
- int dkp_ma = 0; /* memory address */
- int dkp_ussc = 0; /* unit/sf/sc/cnt */
- int dkp_fccy = 0; /* flags/cylinder */
- int dkp_sta = 0; /* status register */
- int dkp_swait = 100; /* seek latency */
- int dkp_rwait = 100; /* rotate latency */
- int dkp_svc (UNIT *uptr);
- int dkp_reset (DEVICE *dptr);
- int dkp_boot (int unitno);
- int dkp_attach (UNIT *uptr, char *cptr);
- int dkp_go (void);
- int dkp_set_size (UNIT *uptr, int value);
- extern int sim_activate (UNIT *uptr, int interval);
- extern int sim_cancel (UNIT *uptr);
- extern int sim_is_active (UNIT *uptr);
- extern int attach_unit (UNIT *uptr, char *cptr);
-
- /* DKP data structures
-
- dkp_dev DKP device descriptor
- dkp_unit DKP unit list
- dkp_reg DKP register list
- dkp_mod DKP modifier list
- */
-
- UNIT dkp_unit[] = {
- { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_ONLINE+
- (D31_DTYPE << UNIT_V_DTYPE), D31_SIZE) },
- { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_ONLINE+
- (D31_DTYPE << UNIT_V_DTYPE), D31_SIZE) },
- { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_ONLINE+
- (D31_DTYPE << UNIT_V_DTYPE), D31_SIZE) },
- { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_ONLINE+
- (D31_DTYPE << UNIT_V_DTYPE), D31_SIZE) } };
-
- REG dkp_reg[] = {
- { ORDATA (FCCY, dkp_fccy, 16) },
- { ORDATA (USSC, dkp_ussc, 16) },
- { ORDATA (STA, dkp_sta, 16) },
- { ORDATA (MA, dkp_ma, 16) },
- { FLDATA (INT, int_req, INT_V_DKP) },
- { FLDATA (BUSY, dev_busy, INT_V_DKP) },
- { FLDATA (DONE, dev_done, INT_V_DKP) },
- { FLDATA (DISABLE, dev_disable, INT_V_DKP) },
- { DRDATA (STIME, dkp_swait, 24), PV_LEFT },
- { DRDATA (RTIME, dkp_rwait, 24), PV_LEFT },
- { GRDATA (FLG0, dkp_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF), REG_HRO },
- { GRDATA (FLG1, dkp_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF), REG_HRO },
- { GRDATA (FLG2, dkp_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF), REG_HRO },
- { GRDATA (FLG3, dkp_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF), REG_HRO },
- { DRDATA (CAPAC0, dkp_unit[0].capac, 32), PV_LEFT + REG_HRO },
- { DRDATA (CAPAC1, dkp_unit[1].capac, 32), PV_LEFT + REG_HRO },
- { DRDATA (CAPAC2, dkp_unit[2].capac, 32), PV_LEFT + REG_HRO },
- { DRDATA (CAPAC3, dkp_unit[3].capac, 32), PV_LEFT + REG_HRO },
- { NULL } };
-
- MTAB dkp_mod[] = {
- { UNIT_ONLINE, 0, "offline", "OFFLINE", NULL },
- { UNIT_ONLINE, UNIT_ONLINE, "online", "ONLINE", NULL },
- { UNIT_WLK, 0, "write enabled", "ENABLED", NULL },
- { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
- { (UNIT_DTYPE+UNIT_ATT), (FLP_DTYPE << UNIT_V_DTYPE) + UNIT_ATT,
- "floppy", NULL, NULL },
- { (UNIT_DTYPE+UNIT_ATT), (D31_DTYPE << UNIT_V_DTYPE) + UNIT_ATT,
- "Diablo 31", NULL, NULL },
- { (UNIT_DTYPE+UNIT_ATT), (D44_DTYPE << UNIT_V_DTYPE) + UNIT_ATT,
- "Diablo 44", NULL, NULL },
- { (UNIT_DTYPE+UNIT_ATT), (C111_DTYPE << UNIT_V_DTYPE) + UNIT_ATT,
- "Century 111", NULL, NULL },
- { (UNIT_DTYPE+UNIT_ATT), (C114_DTYPE << UNIT_V_DTYPE) + UNIT_ATT,
- "Century 114", NULL, NULL },
- { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (FLP_DTYPE << UNIT_V_DTYPE),
- "floppy", NULL, NULL },
- { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (D31_DTYPE << UNIT_V_DTYPE),
- "Diablo 31", NULL, NULL },
- { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (D44_DTYPE << UNIT_V_DTYPE),
- "Diablo 44", NULL, NULL },
- { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (C111_DTYPE << UNIT_V_DTYPE),
- "Century 111", NULL, NULL },
- { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (C114_DTYPE << UNIT_V_DTYPE),
- "Century 114", NULL, NULL },
- { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL },
- { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL },
- { (UNIT_AUTO+UNIT_DTYPE), (FLP_DTYPE << UNIT_V_DTYPE),
- NULL, "FLOPPY", &dkp_set_size },
- { (UNIT_AUTO+UNIT_DTYPE), (D31_DTYPE << UNIT_V_DTYPE),
- NULL, "D31", &dkp_set_size },
- { (UNIT_AUTO+UNIT_DTYPE), (D44_DTYPE << UNIT_V_DTYPE),
- NULL, "D44", &dkp_set_size },
- { (UNIT_AUTO+UNIT_DTYPE), (C111_DTYPE << UNIT_V_DTYPE),
- NULL, "C111", &dkp_set_size },
- { (UNIT_AUTO+UNIT_DTYPE), (C114_DTYPE << UNIT_V_DTYPE),
- NULL, "C114", &dkp_set_size },
- { 0 } };
-
- DEVICE dkp_dev = {
- "DP", dkp_unit, dkp_reg, dkp_mod,
- DKP_NUMDR, 8, 30, 1, 8, 16,
- NULL, NULL, &dkp_reset,
- &dkp_boot, &dkp_attach, NULL };
-
- /* IOT routine */
-
- int dkp (int pulse, int code, int AC)
- {
- UNIT *uptr;
- int u, rval;
-
- rval = 0;
- switch (code) { /* decode IR<5:7> */
- case ioDIA: /* DIA */
- dkp_sta = dkp_sta & ~STA_DYN; /* clear dynamic */
- uptr = dkp_dev.units + GET_UNIT (dkp_ussc); /* select unit */
- if ((uptr -> flags & UNIT_ATT) && (uptr -> flags & UNIT_ONLINE))
- dkp_sta = dkp_sta | STA_DRDY; /* online? */
- if (uptr -> CYL >= drv_tab[GET_DTYPE (uptr -> flags)].cyl)
- dkp_sta = dkp_sta | STA_CYL; /* bad cylinder? */
- if (dkp_sta & STA_EFLGS) dkp_sta = dkp_sta | STA_ERR;
- rval = dkp_sta;
- break;
- case ioDOA: /* DOA */
- if ((dev_busy & INT_DKP) == 0) {
- dkp_fccy = AC; /* save cmd, cyl */
- dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS); }
- break;
- case ioDIB: /* DIB */
- rval = dkp_ma & ADDRMASK; /* return buf addr */
- break;
- case ioDOB: /* DOB */
- if ((dev_busy & INT_DKP) == 0) dkp_ma = AC & ADDRMASK; /* save ma */
- break;
- case ioDIC: /* DIC */
- rval = dkp_ussc; /* return unit, sect */
- break;
- case ioDOC: /* DOC */
- if ((dev_busy & INT_DKP) == 0) dkp_ussc = AC; /* save unit, sect */
- break; } /* end switch code */
-
- /* IOT, continued */
-
- u = GET_UNIT(dkp_ussc); /* select unit */
- switch (pulse) { /* decode IR<8:9> */
- case iopS: /* start */
- dev_busy = dev_busy | INT_DKP; /* set busy */
- dev_done = dev_done & ~INT_DKP; /* clear done */
- int_req = int_req & ~INT_DKP; /* clear int */
- if (dkp_go ()) break; /* new cmd, error? */
- dev_busy = dev_busy & ~INT_DKP; /* clear busy */
- dev_done = dev_done | INT_DKP; /* set done */
- int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
- dkp_sta = dkp_sta | STA_DONE;
- break;
- case iopC: /* clear */
- dev_busy = dev_busy & ~INT_DKP; /* clear busy */
- dev_done = dev_done & ~INT_DKP; /* clear done */
- int_req = int_req & ~INT_DKP; /* clear int */
- dkp_sta = dkp_sta & ~(STA_DFLGS + STA_EFLGS);
- if (dkp_unit[u].FUNC != FCCY_SEEK) sim_cancel (&dkp_unit[u]);
- break;
- case iopP: /* pulse */
- dev_done = dev_done & ~INT_DKP; /* clear done */
- if (dkp_go ()) break; /* new seek command */
- dev_done = dev_done | INT_DKP; /* set done */
- int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
- dkp_sta = dkp_sta | (STA_SKDN0 >> u); /* set seek done */
- break; } /* end case pulse */
- return rval;
- }
-
- /* New command, start vs pulse handled externally
- Returns true if command ok, false if error
- */
-
- int dkp_go (void)
- {
- UNIT *uptr;
- int newcyl, func, u;
-
- dkp_sta = dkp_sta & ~STA_EFLGS; /* clear errors */
- u = GET_UNIT (dkp_ussc); /* get unit number */
- uptr = dkp_dev.units + u; /* get unit */
- if (((uptr -> flags & UNIT_ONLINE) == 0) || /* drive offline */
- ((uptr -> flags & UNIT_ATT) == 0) || /* or not attached */
- sim_is_active (uptr)) { /* or active? */
- dkp_sta = dkp_sta | STA_ERR; /* yes, error */
- return FALSE; }
- func = GET_CMD (dkp_fccy); /* get function */
- newcyl = GET_CYL (dkp_fccy); /* get cylinder */
- switch (func) { /* decode command */
- case FCCY_READ: case FCCY_WRITE:
- sim_activate (uptr, dkp_rwait); /* schedule */
- break;
- case FCCY_RECAL: /* recalibrate */
- newcyl = 0;
- func = FCCY_SEEK;
- case FCCY_SEEK: /* seek */
- sim_activate (uptr, dkp_swait * abs (newcyl - uptr -> CYL));
- dkp_sta = dkp_sta | (STA_SEEK0 >> u); /* set seeking */
- uptr -> CYL = newcyl; /* on cylinder */
- break; } /* end case command */
- uptr -> FUNC = func; /* save command */
- return TRUE; /* no error */
- }
-
- /* Unit service
-
- If seek done, put on cylinder;
- else, do read or write
- If controller was busy, clear busy, set done, interrupt
-
- NXM calculation: this takes advantage of the 4KW granularity of
- memory, versus the 4KW maximum transfer size. The end address
- is calculated as an absolute value; thus it may be ok, non-
- existant, or greater than 32KW (wraps to first bank).
-
- start addr end addr wc wc1
- ok ok unchanged 0
- ok nxm MEMSIZE-dkp_ma < 0
- ok wrapped MEMSIZE-dkp_ma dkp_ma+wc mod 32K
- nxm ok impossible
- nxm nxm < 0 < 0
- nxm wrapped < 0 dkp-ma+wc mod 32K
- */
-
- int dkp_svc (uptr)
- UNIT *uptr;
- {
- int sc, sa, xcsa, wc, wc1, awc, fc, bda;
- int dtype, u, err, rval, newsect, newsurf;
-
- rval = SCPE_OK;
- dtype = GET_DTYPE (uptr -> flags); /* get drive type */
- if (uptr -> FUNC == FCCY_SEEK) { /* seek? */
- if (uptr -> CYL >= drv_tab[dtype].cyl) /* bad cylinder? */
- dkp_sta = dkp_sta | STA_ERR | STA_CYL;
- dev_done = dev_done | INT_DKP; /* set done */
- int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
- u = uptr - dkp_dev.units; /* get unit number */
- dkp_sta = (dkp_sta | (STA_SKDN0 >> u)) /* set seek done */
- & ~(STA_SEEK0 >> u); /* clear seeking */
- return SCPE_OK; }
-
- if (((uptr -> flags & UNIT_ONLINE) == 0) || /* drive offline */
- ((uptr -> flags & UNIT_ATT) == 0) || /* or not attached? */
- ((uptr -> flags & UNIT_WLK) && (uptr -> FUNC == FCCY_WRITE)))
- dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */
-
- else if ((uptr -> CYL >= drv_tab[dtype].cyl) || /* bad cylinder */
- (GET_SURF (dkp_ussc) >= drv_tab[dtype].surf) || /* bad surface */
- (GET_SECT (dkp_ussc) >= drv_tab[dtype].sect)) /* or bad sector? */
- dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS;
-
- else { sc = 16 - GET_COUNT (dkp_ussc); /* get sector count */
- sa = GET_SA (uptr -> CYL, GET_SURF (dkp_ussc),
- GET_SECT (dkp_ussc), dtype); /* get disk block */
- xcsa = GET_SA (uptr -> CYL + 1, 0, 0, dtype); /* get next cyl addr */
- if ((sa + sc) > xcsa ) { /* across cylinder? */
- sc = xcsa - sa; /* limit transfer */
- dkp_sta = dkp_sta | STA_XCY; } /* xcyl error */
- wc = sc * DKP_NUMWD; /* convert blocks */
- bda = sa * DKP_NUMWD * sizeof (short); /* to words, bytes */
- if ((dkp_ma + wc) <= MEMSIZE) wc1 = 0; /* xfer fit? */
- else { wc = MEMSIZE - dkp_ma; /* calculate xfer */
- wc1 = (dkp_ma + wc) - MAXMEMSIZE; } /* calculate wrap */
-
- err = fseek (uptr -> fileref, bda, SEEK_SET); /* position drive */
-
- if (uptr -> FUNC == FCCY_READ) { /* read? */
- if ((wc > 0) && (err == 0)) { /* start in memory? */
- awc = fread (&M[dkp_ma], sizeof (short), wc, uptr -> fileref);
- for ( ; awc < wc; awc++) M[(dkp_ma + awc) & ADDRMASK] = 0;
- err = ferror (uptr -> fileref);
- dkp_ma = (dkp_ma + wc) & ADDRMASK; }
- if ((wc1 > 0) && (err == 0)) { /* memory wrap? */
- awc = fread (&M[0], sizeof (short), wc1, uptr -> fileref);
- for ( ; awc < wc1; awc++) M[0 + awc] = 0;
- err = ferror (uptr -> fileref);
- dkp_ma = (dkp_ma + wc1) & ADDRMASK; } }
-
- if (uptr -> FUNC == FCCY_WRITE) { /* write? */
- if ((wc > 0) && (err == 0)) { /* start in memory? */
- fwrite (&M[dkp_ma], sizeof (short), wc, uptr -> fileref);
- err = ferror (uptr -> fileref);
- dkp_ma = (dkp_ma + wc + 2) & ADDRMASK; }
- if ((wc1 > 0) && (err == 0)) { /* memory wrap? */
- fwrite (&M[0], sizeof (short), wc1, uptr -> fileref);
- err = ferror (uptr -> fileref);
- dkp_ma = (dkp_ma + wc1) & ADDRMASK; } }
-
- if (err != 0) {
- perror ("DKP I/O error");
- rval = SCPE_IOERR; }
- clearerr (uptr -> fileref);
-
- sa = sa + sc; /* update sector addr */
- newsect = sa % drv_tab[dtype].sect;
- newsurf = (sa / drv_tab[dtype].sect) % drv_tab[dtype].surf;
- dkp_ussc = (dkp_ussc & USSC_UNIT) | (newsurf << USSC_V_SURFACE) |
- (newsect << USSC_V_SECTOR) | ((dkp_ussc + sc) & USSC_M_COUNT);
- dkp_sta = dkp_sta | STA_DONE; } /* set status */
-
- dev_busy = dev_busy & ~INT_DKP; /* clear busy */
- dev_done = dev_done | INT_DKP; /* set done */
- int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
- return rval;
- }
-
- /* Reset routine */
-
- int dkp_reset (dptr)
- DEVICE *dptr;
- {
- int i, u;
- UNIT *uptr;
-
- dev_busy = dev_busy & ~INT_DKP; /* clear busy */
- dev_done = dev_done & ~INT_DKP; /* clear done, int */
- int_req = int_req & ~INT_DKP;
- dkp_fccy = dkp_ussc = dkp_ma = dkp_sta = 0; /* clear registers */
- for (u = 0; u < DKP_NUMDR; u++) { /* loop thru units */
- uptr = dkp_dev.units + u;
- sim_cancel (uptr); /* cancel activity */
- uptr -> CYL = uptr -> FUNC = 0; }
- return SCPE_OK;
- }
-
- /* Attach routine (with optional autosizing) */
-
- int dkp_attach (UNIT *uptr, char *cptr)
- {
- int i, p, r;
-
- uptr -> capac = drv_tab[GET_DTYPE (uptr -> flags)].size;
- r = attach_unit (uptr, cptr);
- if ((r != SCPE_OK) || ((uptr -> flags & UNIT_AUTO) == 0)) return r;
- if (fseek (uptr -> fileref, 0, SEEK_END)) return SCPE_OK;
- if ((p = ftell (uptr -> fileref)) == 0) return SCPE_OK;
- for (i = 0; drv_tab[i].sect != 0; i++) {
- if (p <= (drv_tab[i].size * sizeof (short))) {
- uptr -> flags = (uptr -> flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE);
- uptr -> capac = drv_tab[i].size;
- return SCPE_OK; } }
- return SCPE_OK;
- }
-
- /* Set size command validation routine */
-
- int dkp_set_size (UNIT *uptr, int value)
- {
- if (uptr -> flags & UNIT_ATT) return SCPE_ALATT;
- uptr -> capac = drv_tab[GET_DTYPE (value)].size;
- return SCPE_OK;
- }
-
- /* Bootstrap routine */
-
- #define BOOT_START 02000
- #define BOOT_UNIT 02021
- #define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
-
- static const int boot_rom[] = {
- 060233, /* NIOC 0,DKP ; clear disk */
- 020420, /* LDA 0,USSC ; unit, sfc, sec, cnt */
- 063033, /* DOC 0,DKP ; select disk */
- 020417, /* LDA 0,SEKCMD ; command, cylinder */
- 061333, /* DOAP 0,DKP ; start seek */
- 024415, /* LDA 1,SEKDN */
- 060433, /* DIA 0,DKP ; get status */
- 0123415, /* AND# 1,0,SZR ; skip if done */
- 000776, /* JMP .-2 */
- 0102400, /* SUB 0,0 ; mem addr = 0 */
- 062033, /* DOB 0,DKP */
- 020411, /* LDA 0,REDCMD ; command, cylinder */
- 061133, /* DOAS 0,DKP ; start read */
- 060433, /* DIA 0, DKP ; get status */
- 0101113, /* MOVL# 0,0,SNC ; skip if done */
- 000776, /* JMP .-2 */
- 000377, /* JMP 377 */
- 000016, /* USSC: 0.B1+0.B7+0.B11+16 */
- 0175000, /* SEKCMD: 175000 */
- 074000, /* SEKDN: 074000 */
- 0174000 /* REDCMD: 174000 */
- };
-
- int dkp_boot (int unitno)
- {
- int i;
- extern int saved_PC;
-
- for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
- M[BOOT_UNIT] = M[BOOT_UNIT] | ((unitno & USSC_M_UNIT) << USSC_V_UNIT);
- saved_PC = BOOT_START;
- return SCPE_OK;
- }
-