Exemplo n.º 1
0
Arquivo: id_dp.c Projeto: B-Rich/simh
t_bool dp_dter (UNIT *uptr, uint32 first)
{
uint32 hd, sc, sa;
uint32 dtype = GET_DTYPE (uptr->flags);                 /* get drive type */

if (((uptr->flags & UNIT_ATT) == 0) ||                  /* not attached? */
    ((uptr->flags & UNIT_WPRT) && (dp_cmd == CMC_WR))) {
    dp_done (STC_DTE);                                  /* error, done */
    return TRUE;
    }
hd = GET_SRF (dp_hdsc);                                 /* get head */
sc = GET_SEC (dp_hdsc);                                 /* get sector */
if (dp_cyl != (uint32) uptr->CYL) {                     /* wrong cylinder? */
    if (dp_cyl == 0)
        uptr->CYL = 0;
    else {
        dp_done (STC_ACF);                              /* error, done */
        return TRUE;
        } 
    }
if (sc >= DP_NUMSC) {                                   /* bad sector? */
    dp_done (STC_OVR);                                  /* error, done */
    return TRUE;
    }
if (!first && (sc == 0) && (hd == 0)) {                 /* cyl overflow? */
    dp_done (STC_CYO);                                  /* error, done */
    return TRUE;
    }
sa = GET_SA (dp_plat, uptr->CYL, hd, sc, dtype);        /* curr disk addr */
fseek (uptr->fileref, sa * DP_NUMBY, SEEK_SET);
if ((sc + 1) < DP_NUMSC)                                /* end of track? */
    dp_hdsc = dp_hdsc + 1;
else dp_hdsc = (dp_hdsc ^ HS_HMASK) & HS_HMASK;         /* sec 0, nxt srf */
return FALSE;
}
Exemplo n.º 2
0
t_stat dp_go1 (uint32 dat)
{
int32 ch = dp_dib.chan - 1;                             /* DMA/DMC chan */
uint32 u = CW1_GETUNIT (dat);
UNIT *uptr = dp_dev.units + u;

dp_cw1 = dat;                                           /* store CW1 */
dp_otas = OTA_NOP;                                      /* assume no CW2 */
uptr->FNC = dp_fnc;
if (sim_is_active (uptr))                               /* still seeking? */
    return dp_done (1, STA_UNSER);                      /* unsafe */
if (!(uptr->flags & UNIT_ATT))                          /* not attached? */
    return dp_done (1, STA_OFLER);                      /* offline */

switch (dp_fnc) {                                       /* case on function */

    case FNC_SEEK:                                      /* seek */
    case FNC_SK0:                                       /* recalibrate */
    case FNC_UNL:                                       /* unload */
        sim_activate (uptr, dp_btime);                  /* quick timeout */
        break;

    case FNC_FMT:                                       /* format */
        if (uptr->flags & UNIT_WPRT)                    /* write protect? */
            return dp_done (1, STA_WPRER);              /* stop now */
    case FNC_RCA:                                       /* read current addr */
        dp_xip = u | XIP_SCHED;                         /* operation started */
        sim_activate (uptr, dp_xtime * 10);             /* rotation timeout */
        break;

    case FNC_RW:                                        /* read/write */
        dp_otas = OTA_CW2;                              /* expect CW2 */
        dp_sta = dp_sta | STA_RDY;                      /* set ready */
        if (dp_dma && Q_DMA (ch))                       /* DMA? set chan request */
            SET_CH_REQ (ch);
        break;
        }

return SCPE_OK;
}
Exemplo n.º 3
0
Arquivo: id_dp.c Projeto: B-Rich/simh
t_stat dp_wds (UNIT *uptr)
{
for ( ; dp_bptr < DP_NUMBY; dp_bptr++)
    dpxb[dp_bptr] = dp_db;                              /* fill with last */
fxwrite (dpxb, sizeof (uint8), DP_NUMBY, uptr->fileref);
if (ferror (uptr->fileref)) {                           /* error? */
    sim_perror ("DP I/O error");
    clearerr (uptr->fileref);
    dp_done (STC_DTE);
    return SCPE_IOERR;
    }
return SCPE_OK;
}
Exemplo n.º 4
0
t_stat dp_wrtrk (UNIT *uptr, uint16 *buf, uint32 c, uint32 h)
{
uint32 da = ((c * dp_tab[dp_ctype].surf) + h) * DP_TRKLEN;

fseek (uptr->fileref, da * sizeof (uint16), SEEK_SET);
fxwrite (buf, sizeof (uint16), DP_TRKLEN, uptr->fileref);
if (ferror (uptr->fileref)) {
    perror ("DP I/O error");
    clearerr (uptr->fileref);
    dp_done (1, STA_UNSER);
    return SCPE_IOERR;
    }
return SCPE_OK;
}
Exemplo n.º 5
0
Arquivo: id_dp.c Projeto: B-Rich/simh
t_stat dp_rds (UNIT *uptr)
{
uint32 i;

i = fxread (dpxb, sizeof (uint8), DP_NUMBY, uptr->fileref);
for ( ; i < DP_NUMBY; i++)                              /* fill with 0's */
    dpxb[i] = 0;
if (ferror (uptr->fileref)) {                           /* error? */
    sim_perror ("DP I/O error");
    clearerr (uptr->fileref);
    dp_done (STC_DTE);
    return SCPE_IOERR;
    }
return SCPE_OK;
}
Exemplo n.º 6
0
Arquivo: id_dp.c Projeto: B-Rich/simh
t_stat dp_svc (UNIT *uptr)
{
uint32 u = uptr - dp_dev.units;                         /* get unit number */
int32 cyl = uptr->CYL;                                  /* get cylinder */
uint32 dtype = GET_DTYPE (uptr->flags);                 /* get drive type */
t_stat r;

if (uptr->STD & STD_MOV) {                              /* seek? */
    uptr->STD = 0;                                      /* clr seek in prog */
    if ((uptr->flags & UNIT_ATT) == 0)                  /* offl? hangs */
        return SCPE_OK;
    if (cyl >= drv_tab[dtype].cyl) {                    /* bad cylinder? */
        uptr->STD = STD_ILA;                            /* error */
        uptr->CYL = drv_tab[dtype].cyl - 1;             /* put at edge */
        }
    if (dpd_arm[u])                                     /* req intr */
        SET_INT (v_DPC + u + 1);
    return SCPE_OK;
    }

switch (dp_cmd & 0x7) {                                 /* case on func */

    case CMC_RCHK:                                      /* read check */
        dp_dter (uptr, 1);                              /* check xfr err */
        break;

    case CMC_RD:                                        /* read */
        if (sch_actv (dp_dib.sch, dp_dib.dno)) {        /* sch transfer? */
            if (dp_dter (uptr, dp_1st))                 /* check xfr err */
                return SCPE_OK;
            if ((r = dp_rds (uptr)))                    /* read sec, err? */
                return r;
            dp_1st = 0;
            sch_wrmem (dp_dib.sch, dpxb, DP_NUMBY);     /* write to memory */
            if (sch_actv (dp_dib.sch, dp_dib.dno)) {    /* more to do? */       
                sim_activate (uptr, dp_rtime);          /* reschedule */
                return SCPE_OK;
                }
            break;                                      /* no, set done */
            } 
        dp_sta = dp_sta | STC_DTE;                      /* can't work */
        break;

    case CMC_WR:                                        /* write */
        if (sch_actv (dp_dib.sch, dp_dib.dno)) {        /* sch transfer? */
            if (dp_dter (uptr, dp_1st))                 /* check xfr err */
                return SCPE_OK;
            dp_bptr = sch_rdmem (dp_dib.sch, dpxb, DP_NUMBY); /* read from mem */
            dp_db = dpxb[dp_bptr - 1];                  /* last byte */
            if ((r = dp_wds (uptr)))                    /* write sec, err? */
                return r;
            dp_1st = 0;
            if (sch_actv (dp_dib.sch, dp_dib.dno)) {    /* more to do? */       
                sim_activate (uptr, dp_rtime);          /* reschedule */
                return SCPE_OK;
                }
            break;                                      /* no, set done */
            }
        dp_sta = dp_sta | STC_DTE;                      /* can't work */
        break;
        }                                               /* end case func */

dp_done (0);                                            /* done */
return SCPE_OK;
}
Exemplo n.º 7
0
t_stat dp_wrdone (UNIT *uptr, uint32 flg)
{
dp_done (1, flg);
return dp_wrtrk (uptr, dpxb, uptr->CYL, CW1_GETHEAD (dp_cw1));
}
Exemplo n.º 8
0
t_stat dp_svc (UNIT *uptr)
{
int32 dcyl = 0;                                         /* assume recalibrate */
int32 ch = dp_dib.chan - 1;                             /* DMA/DMC chan */
uint32 h = CW1_GETHEAD (dp_cw1);                        /* head */
int32 st;
uint32 i, offs, lnt, ming, tpos;
t_stat r;

if (!(uptr->flags & UNIT_ATT)) {                        /* not attached? */
    dp_done (1, STA_OFLER);                             /* offline */
    return IORETURN (dp_stopioe, SCPE_UNATT);
    }

switch (uptr->FNC) {                                    /* case on function */

    case FNC_SEEK:                                      /* seek, need cyl */
        offs = CW1_GETOFFS (dp_cw1);                    /* get offset */
        if (dp_cw1 & CW1_DIR)                           /* get desired cyl */
            dcyl = uptr->CYL - offs;
        else dcyl = uptr->CYL + offs;
        if ((offs == 0) ||
            (dcyl < 0) ||
            (dcyl >= (int32) dp_tab[dp_ctype].cyl))     
            return dp_done (1, STA_SEKER);              /* bad seek? */

    case FNC_SK0:                                       /* recalibrate */
        dp_sta = dp_sta & ~STA_BUSY;                    /* clear busy */
        uptr->FNC = FNC_SEEK | FNC_2ND;                 /* next state */
        st = (abs (dcyl - uptr->CYL)) * dp_stime;       /* schedule seek */
        if (st == 0)
            st = dp_stime;
        uptr->CYL = dcyl;                               /* put on cylinder */
        sim_activate (uptr, st);
        return SCPE_OK;

    case FNC_SEEK | FNC_2ND:                            /* seek, 2nd state */
        if (dp_sta & STA_BUSY)                          /* busy? queue intr */
            dp_defint = 1;
        else SET_INT (INT_DP);                          /* no, req intr */
        return SCPE_OK;

    case FNC_UNL:                                       /* unload */
        detach_unit (uptr);                             /* detach unit */
        return dp_done (0, 0);                          /* clear busy, no intr */

    case FNC_RCA:                                       /* read current addr */
        if (h >= dp_tab[dp_ctype].surf)                 /* invalid head? */
            return dp_done (1, STA_ADRER);              /* error */
        if (r = dp_rdtrk (uptr, dpxb, uptr->CYL, h))    /* get track; error? */
            return r;
        dp_rptr = 0;                                    /* init rec ptr */
        if (dpxb[dp_rptr + REC_LNT] == 0)               /* unformated? */
            return dp_done (1, STA_ADRER);              /* error */
        tpos = (uint32) (fmod (sim_gtime () / (double) dp_xtime, DP_TRKLEN));
        do {                                            /* scan down track */
            dp_buf = dpxb[dp_rptr + REC_ADDR];          /* get rec addr */
            dp_rptr = dp_rptr + dpxb[dp_rptr + REC_LNT] + REC_OVHD;
            } while ((dp_rptr < tpos) && (dpxb[dp_rptr + REC_LNT] != 0));
        if (dp_dma) {                                   /* DMA/DMC? */
            if (Q_DMA (ch))                             /* DMA? */
                dma_ad[ch] = dma_ad[ch] | DMA_IN;       /* force input */
            SET_CH_REQ (ch);                            /* request chan */
            }
        return dp_done (1, STA_RDY);                    /* clr busy, set rdy */

/* Formating takes place in five states:

   init - clear track buffer, start at first record
   address - store address word
   data - store data word(s) until end of range
   pause - wait for gap word or stop command
   gap  - validate gap word, advance to next record

   Note that formating is stopped externally by an OCP command; the
   track buffer is flushed at that point.  If the stop does not occur
   in the proper state (gap word received), a format error occurs.
*/

    case FNC_FMT:                                       /* format */
        for (i = 0; i < DP_TRKLEN; i++)                 /* clear track */
            dpxb[i] = 0;
        dp_xip = dp_xip | XIP_FMT;                      /* format in progress */
        dp_rptr = 0;                                    /* init record ptr */
        dp_gap = 0;                                     /* no gap before first */
        dp_bctr = (uint32) (16.0 * dp_tab[dp_ctype].wrds); /* init bit cntr */
        uptr->FNC = uptr->FNC | FNC_2ND;                /* address state */
        break;                                          /* set up next word */

    case FNC_FMT | FNC_2ND:                             /* format, address word */
        dp_wptr = 0;                                    /* clear word ptr */
        if (dp_bctr < (dp_gap + REC_OVHD_BITS + 16))    /* room for gap, record? */
            return dp_wrdone (uptr, STA_FMTER);         /* no, format error */
        dp_bctr = dp_bctr - dp_gap - REC_OVHD_BITS;     /* charge for gap, ovhd */
        dpxb[dp_rptr + REC_ADDR] = dp_buf;              /* store address */
        uptr->FNC = FNC_FMT | FNC_3RD;                  /* data state */
        if (dp_eor) {                                   /* record done? */
            dp_eor = 0;                                 /* clear for restart */
            if (dp_dma)                                 /* DMA/DMC? intr */
                SET_INT (INT_DP);
            }
        break;                                          /* set up next word */

    case FNC_FMT | FNC_3RD:                             /* format, data word */
        if (dp_sta & STA_RDY)                           /* timing failure? */
            return dp_wrdone (uptr, STA_DTRER);         /* write trk, err */
        else {                                          /* no, have word */
            if (dp_bctr < 16)                           /* room for it? */
                return dp_wrdone (uptr, STA_FMTER);     /* no, error */
            dp_bctr = dp_bctr - 16;                     /* charge for word */
            dp_csum = dp_csum ^ dp_buf;                 /* update checksum */
            dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_buf;/* store word */
            dpxb[dp_rptr + REC_LNT]++;                  /* incr rec lnt */
            dp_wptr++;                                  /* incr word ptr */
            }
        if (dp_eor) {                                   /* record done? */
            dp_eor = 0;                                 /* clear for restart */
            if (dp_dma)                                 /* DMA/DMC? intr */
                SET_INT (INT_DP);
            dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; /* store checksum */
            uptr->FNC = uptr->FNC | FNC_4TH;            /* pause state */
            sim_activate (uptr, 5 * dp_xtime);          /* schedule pause */
            return SCPE_OK;                             /* don't request word */
            }
        break;                                          /* set up next word */

    case FNC_FMT | FNC_4TH:                             /* format, pause */
        uptr->FNC = FNC_FMT | FNC_5TH;                  /* gap state */
        break;                                          /* request word */

    case FNC_FMT | FNC_5TH:                             /* format, gap word */
        ming = ((16 * dp_wptr) + REC_OVHD_BITS) / 20;   /* min 5% gap */
        if (dp_buf < ming)                              /* too small? */
            return dp_wrdone (uptr, STA_FMTER);         /* yes, format error */
        dp_rptr = dp_rptr + dp_wptr + REC_OVHD;         /* next record */
        uptr->FNC = FNC_FMT | FNC_2ND;                  /* address state */
        if (dp_eor) {                                   /* record done? */
            dp_eor = 0;                                 /* clear for restart */
            if (dp_dma) SET_INT (INT_DP);               /* DMA/DMC? intr */
            }
        dp_gap = dp_buf;                                /* save gap */
        dp_csum = 0;                                    /* clear checksum */
        break;                                          /* set up next word */

/* Read and write take place in two states:

   init - read track into buffer, find record, validate parameters
   data - (read) fetch data from buffer, stop on end of range
        - (write) write data into buffer, flush on end of range
*/

    case FNC_RW:                                        /* read/write */
        if (h >= dp_tab[dp_ctype].surf)                 /* invalid head? */
            return dp_done (1, STA_ADRER);              /* error */
        if (r = dp_rdtrk (uptr, dpxb, uptr->CYL, h))    /* get track; error? */
            return r;
        if (!dp_findrec (dp_cw2))                       /* find rec; error? */
            return dp_done (1, STA_ADRER);              /* address error */
        if ((dpxb[dp_rptr + REC_LNT] >= (DP_TRKLEN - dp_rptr - REC_OVHD)) ||
            (dpxb[dp_rptr + REC_EXT] >= REC_MAXEXT)) {  /* bad lnt or ext? */
            dp_done (1, STA_UNSER);                     /* stop simulation */
            return STOP_DPFMT;                          /* bad format */
            }
        uptr->FNC = uptr->FNC | FNC_2ND;                /* next state */
        if (dp_cw1 & CW1_RW) {                          /* write? */
            if (uptr->flags & UNIT_WPRT)                /* write protect? */
                return dp_done (1, STA_WPRER);          /* error */
            dp_xip = dp_xip | XIP_WRT;                  /* write in progress */
            dp_sta = dp_sta | STA_RDY;                  /* set ready */
            if (dp_dma)                                 /* if DMA/DMC, req chan */
                SET_CH_REQ (ch);
            }
        else if (Q_DMA (ch))                            /* read; DMA? */
            dma_ad[ch] = dma_ad[ch] | DMA_IN;           /* force input */
        sim_activate (uptr, dp_xtime);                  /* schedule word */
        dp_wptr = 0;                                    /* init word pointer */
        return SCPE_OK;

    case FNC_RW | FNC_2ND:                              /* read/write, word */
        if (dp_cw1 & CW1_RW) {                          /* write? */
            if (dp_sta & STA_RDY)                       /* timing failure? */
                return dp_wrdone (uptr, STA_DTRER);     /* yes, error */
            if (r = dp_wrwd (uptr, dp_buf))             /* wr word, error? */
                return r;
            if (dp_eor) {                               /* transfer done? */
                dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum;
                return dp_wrdone (uptr, 0);             /* clear busy, intr req */
                }
            }
        else {                                          /* read? */
            lnt = dpxb[dp_rptr + REC_LNT] + dpxb[dp_rptr + REC_EXT];
            dp_buf = dpxb[dp_rptr + REC_DATA + dp_wptr];/* current word */
            dp_csum = dp_csum ^ dp_buf;                 /* xor to csum */
            if ((dp_wptr > lnt) || dp_eor)              /* transfer done? */
                return dp_done (1,
                    (dp_csum? STA_CSMER: 0) | ((dp_wptr >= lnt)? STA_EOR: 0));
            if (dp_sta & STA_RDY)                       /* data buf full? */
                return dp_done (1, STA_DTRER);          /* no, underrun */
            dp_wptr++;                                  /* next word */
            }
        break;

    default:
        return SCPE_IERR;
        }                                               /* end case */

dp_sta = dp_sta | STA_RDY;                              /* set ready */
if (dp_dma)                                             /* if DMA/DMC, req chan */
    SET_CH_REQ (ch);
sim_activate (uptr, dp_xtime);                          /* schedule word */
return SCPE_OK;
}
Exemplo n.º 9
0
int32 dpio (int32 inst, int32 fnc, int32 dat, int32 dev)
{
int32 ch = dp_dib.chan - 1;                             /* DMA/DMC chan */
int32 u;
UNIT *uptr;

switch (inst) {                                         /* case on opcode */

    case ioOCP:                                         /* OCP */
        switch (fnc) {                                  /* case on function */

        case FNC_SK0: case FNC_SEEK: case FNC_RCA:      /* data transfer */
        case FNC_UNL: case FNC_FMT: case FNC_RW:
            dp_go (fnc);                                /* if !busy, start */
            break;

        case FNC_STOP:                                  /* stop transfer */
            if (dp_xip) {                               /* transfer in prog? */
                uptr = dp_dev.units + (dp_xip & XIP_UMSK);      /* get unit */
                sim_cancel (uptr);                      /* stop operation */
                if (dp_xip & (XIP_WRT|XIP_FMT))         /* write or format? */
                    dp_wrdone (uptr,                    /* write track */
                        ((dp_xip & XIP_FMT) &&          /* check fmt state */
                        (uptr->FNC != (FNC_FMT|FNC_2ND)))?
                        STA_DTRER: 0);
                else dp_done (1, dp_csum? STA_CSMER: 0);/* no, just clr busy */
                dp_xip = 0;                             /* clear flag */
                }
            dp_otas = OTA_NOP;                          /* clear state */
            dp_sta = dp_sta & ~STA_BUSY;                /* clear busy */
            break;      

        case FNC_RDS:                                   /* read status */
            if (dp_sta & STA_BUSY)                      /* ignore if busy */
                return dat;
            dp_sta = (dp_sta | STA_RDY) & ~(STA_MBZ | STA_ANYER);
            if (dp_sta & STA_ALLERR) dp_sta = dp_sta | STA_ANYER;
            dp_buf = dp_sta;
            if (dp_dma && Q_DMA (ch))                   /* DMA? set chan req */
                SET_CH_REQ (ch);
            break;

        case FNC_DMA:                                   /* set DMA/DMC */
            dp_dma = 1;
            break;

        case FNC_IOBUS:                                 /* set IO bus */
            dp_dma = 0;
            break;

        case FNC_AKI:                                   /* ack intr */
            CLR_INT (INT_DP);
            break;

        default:                                        /* undefined */
            return IOBADFNC (dat);
            }
        break;

    case ioINA:                                         /* INA */
        if (fnc)                                        /* fnc 0 only */
            return IOBADFNC (dat);
        if (dp_sta & STA_RDY) {                         /* ready? */
            dp_sta = dp_sta & ~STA_RDY;                 /* clear ready */
            return IOSKIP (dat | dp_buf);               /* ret buf, skip */
            }
        break;

    case ioOTA:                                         /* OTA */
        if (fnc)                                        /* fnc 0 only */
            return IOBADFNC (dat);
        if (dp_sta & STA_RDY) {                         /* ready? */
            dp_sta = dp_sta & ~STA_RDY;                 /* clear ready */
            dp_buf = dat;                               /* store buf */
            if (dp_otas == OTA_CW1)                     /* expecting CW1? */
                dp_go1 (dat);
            else if (dp_otas == OTA_CW2)                /* expecting CW2? */
                dp_go2 (dat);
            return IOSKIP (dat);
            }
        break;

    case ioSKS:                                         /* SKS */
        u = 7;                                          /* assume unit 7 */
        switch (fnc) {

        case 000:                                       /* ready */
            if (dp_sta & STA_RDY)
                return IOSKIP (dat);
            break;

        case 001:                                       /* !interrupting */
            if (!TST_INTREQ (INT_DP))
                return IOSKIP (dat);
            break;

        case 002:                                       /* operational */
            if (!(dp_sta & (STA_BUSY | STA_ALLERR)))
                return IOSKIP (dat);
            break;

        case 003:                                       /* !error */
            if (!(dp_sta & STA_ALLERR))
                return IOSKIP (dat);
            break;

        case 004:                                       /* !busy */
            if (!(dp_sta & STA_BUSY))
                return IOSKIP (dat);
            break;

        case 011: case 012: case 013:                   /* !not seeking 0-6 */
        case 014: case 015: case 016: case 017:
            u = fnc - 011;
        case 007:                                       /* !not seeking 7 */
            if (!sim_is_active (&dp_unit[u]) ||         /* quiescent? */
                (dp_unit[u].FNC != (FNC_SEEK | FNC_2ND)))
                return IOSKIP (dat);                    /* seeking sets late */
            break;
            }
        break;

    case ioEND:                                         /* end of range */
        dp_eor = 1;                                     /* transfer done */
        break;
        }

return dat;
}