Ejemplo n.º 1
0
t_stat ptp_svc (UNIT *uptr)
{
dev_done = dev_done | INT_PTP;                          /* set done */
int_req = INT_UPDATE;                                   /* update interrupts */
if ((ptp_unit.flags & UNIT_ATT) == 0)                   /* attached? */
    return IORETURN (ptp_stopioe, SCPE_UNATT);
if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) {
    perror ("PTP I/O error");
    clearerr (ptp_unit.fileref);
    return SCPE_IOERR;
    }
ptp_unit.pos = ptp_unit.pos + 1;
return SCPE_OK;
}
Ejemplo n.º 2
0
t_stat lpt_svc (UNIT *uptr)
{
DEV_CLR_BUSY( INT_LPT ) ;
DEV_SET_DONE( INT_LPT ) ;
DEV_UPDATE_INTR ;
if ((lpt_unit.flags & UNIT_ATT) == 0)                   /* attached? */
    return IORETURN (lpt_stopioe, SCPE_UNATT);
pdflpt_putc (uptr, uptr->buf);
uptr->pos = pdflpt_where (uptr, NULL);
if (pdflpt_error (uptr)) {
    pdflpt_perror (uptr, "LPT I/O error");
    pdflpt_clearerr (uptr);
    return SCPE_IOERR;
    }
return SCPE_OK;
}
Ejemplo n.º 3
0
t_stat lpt_svc (UNIT *uptr)
{
DEV_CLR_BUSY( INT_LPT ) ;
DEV_SET_DONE( INT_LPT ) ;
DEV_UPDATE_INTR ;
if ((lpt_unit.flags & UNIT_ATT) == 0)                   /* attached? */
    return IORETURN (lpt_stopioe, SCPE_UNATT);
fputc (uptr->buf, uptr->fileref);
uptr->pos = ftell (uptr->fileref);
if (ferror (uptr->fileref)) {
    sim_perror ("LPT I/O error");
    clearerr (uptr->fileref);
    return SCPE_IOERR;
    }
return SCPE_OK;
}
Ejemplo n.º 4
0
t_stat ptp_svc (UNIT *uptr)
{
ptp_csr = ptp_csr | CSR_ERR | CSR_DONE;
if (ptp_csr & CSR_IE)
    SET_INT (PTP);
if ((ptp_unit.flags & UNIT_ATT) == 0)
    return IORETURN (ptp_stopioe, SCPE_UNATT);
if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) {
    perror ("PTP I/O error");
    clearerr (ptp_unit.fileref);
    return SCPE_IOERR;
    }
ptp_csr = ptp_csr & ~CSR_ERR;
ptp_unit.pos = ptp_unit.pos + 1;
return SCPE_OK;
}
Ejemplo n.º 5
0
t_stat lpt_svc (UNIT *uptr)
{
dev_done = dev_done | INT_LPT;                          /* set done */
int_req = INT_UPDATE;                                   /* update interrupts */
if ((uptr->flags & UNIT_ATT) == 0) {
    lpt_err = 1;
    return IORETURN (lpt_stopioe, SCPE_UNATT);
    }
pdflpt_putc (uptr, uptr->buf);                          /* print char */
uptr->pos = pdflpt_where (uptr, NULL);
if (pdflpt_error (uptr)) {                              /* error? */
    pdflpt_perror (uptr, "LPT I/O error");
    pdflpt_clearerr (uptr);
    return SCPE_IOERR;
    }
return SCPE_OK;
}
Ejemplo n.º 6
0
Archivo: id_lp.c Proyecto: ST3ALth/simh
t_stat lpt_svc (UNIT *uptr)
{
int32 t;
t_stat r = SCPE_OK;

lpt_sta = 0;                                            /* clear busy */
if (lpt_arm)                                            /* armed? intr */
    SET_INT (v_LPT);
if ((uptr->flags & UNIT_ATT) == 0)                      /* attached? */
    return IORETURN (lpt_stopioe, SCPE_UNATT);
t = uptr->buf;                                          /* get character */
if (lpt_spnd || ((t >= LF) && (t < CR))) {              /* spc pend or spc op? */
    lpt_spnd = 0;
    if (lpt_bufout (uptr) != SCPE_OK)                   /* print */
        return SCPE_IOERR;
    if ((t == 1) || (t == LF))                          /* single space */
        lpt_spc (uptr, 1);
    else if (t == VT)                                   /* VT->VFU */
        r = lpt_vfu (uptr, VT_VFU - 1);
    else if (t == 0xC)                                  /* FF->VFU */
        r = lpt_vfu (uptr, FF_VFU - 1);
    else if ((t >= SPC_BASE) && (t < VFU_BASE))
        lpt_spc (uptr, t - SPC_BASE);                   /* space */
    else if ((t >= VFU_BASE) && (t < VFU_BASE + VFU_WIDTH))
        r = lpt_vfu (uptr, t - VFU_BASE);               /* VFU */
    else fputs ("\r", uptr->fileref);                   /* overprint */
    uptr->pos = ftell (uptr->fileref);                  /* update position */
    if (ferror (lpt_unit.fileref)) {
        sim_perror ("LPT I/O error");
        clearerr (uptr->fileref);
        return SCPE_IOERR;
        }
    }
else if (t == CR) {                                     /* CR? */
    lpt_spnd = 1;                                       /* set spc pend */
    return lpt_bufout (uptr);                           /* print line */
    }
else if (t >= 0x20) {                                   /* printable? */
    if ((uptr->flags & UNIT_UC) && islower (t))         /* UC only? */
        t = toupper (t);
    if (lpt_bptr < LPT_WIDTH)
        lpxb[lpt_bptr++] = t;
    }
return r;
}
Ejemplo n.º 7
0
t_stat ptp_svc (UNIT *uptr)
{
if (cpls & CPLS_PTP) {                                  /* completion pulse? */
    ios = 1;                                            /* restart */
    cpls = cpls & ~CPLS_PTP;
    }
iosta = iosta | IOS_PTP;                                /* set flag */
dev_req_int (ptp_sbs);                                  /* req interrupt */
if ((uptr->flags & UNIT_ATT) == 0)                      /* not attached? */
    return IORETURN (ptp_stopioe, SCPE_UNATT);
if (putc (uptr->buf, uptr->fileref) == EOF) {           /* I/O error? */
    perror ("PTP I/O error");
    clearerr (uptr->fileref);
    return SCPE_IOERR;
    }
uptr->pos = uptr->pos + 1;
return SCPE_OK;
}
Ejemplo n.º 8
0
t_stat
lpt_svc(UNIT * uptr)
{
	lpt_csr = lpt_csr | CSR_ERR | CSR_DONE;
	if (lpt_csr & CSR_IE)
		SET_INT(LPT);
	if ((uptr->flags & UNIT_ATT) == 0)
		return IORETURN(lpt_stopioe, SCPE_UNATT);
	fputc(uptr->buf & 0177, uptr->fileref);
	uptr->pos = ftell(uptr->fileref);
	if (ferror(uptr->fileref)) {
		perror("LPT I/O error");
		clearerr(uptr->fileref);
		return SCPE_IOERR;
	}
	lpt_csr = lpt_csr & ~CSR_ERR;
	return SCPE_OK;
}
Ejemplo n.º 9
0
t_stat ptr_svc (UNIT *uptr)
{
int32 temp;

ptr_csr = (ptr_csr | CSR_ERR) & ~CSR_BUSY;
if (ptr_csr & CSR_IE) int_req = int_req | INT_PTR;
if ((ptr_unit.flags & UNIT_ATT) == 0)
	return IORETURN (ptr_stopioe, SCPE_UNATT);
if ((temp = getc (ptr_unit.fileref)) == EOF) {
	if (feof (ptr_unit.fileref)) {
		if (ptr_stopioe) printf ("PTR end of file\n");
		else return SCPE_OK;  }
	else perror ("PTR I/O error");
	clearerr (ptr_unit.fileref);
	return SCPE_IOERR;  }
ptr_csr = (ptr_csr | CSR_DONE) & ~CSR_ERR;
ptr_unit.buf = temp & 0377;
ptr_unit.pos = ptr_unit.pos + 1;
return SCPE_OK;
}
Ejemplo n.º 10
0
t_stat ptp_svc (UNIT *uptr)
{
int32 c;

if (cpls & CPLS_PTP) {                                  /* completion pulse? */
    ios = 1;                                            /* restart */
    cpls = cpls & ~CPLS_PTP;
    }
iosta = iosta | IOS_PTP;                                /* set flag */
dev_req_int (ptp_sbs);                                  /* req interrupt */
if ((uptr->flags & UNIT_ATT) == 0)                      /* not attached? */
    return IORETURN (ptp_stopioe, SCPE_UNATT);
if ((uptr->flags & UNIT_ASCII) != 0) {                  /* ASCII mode? */
    int32 c1 = uptr->buf & 077;
    if (uptr->buf == 0)                                 /* ignore nulls */
        return SCPE_OK;
    if (c1 == FIODEC_UC) {                              /* UC? absorb */
        ptp_uc = UC;
        return SCPE_OK;
        }
    else if (c1 == FIODEC_LC) {                         /* LC? absorb */
        ptp_uc = 0;
        return SCPE_OK;
        }
    else c = fiodec_to_ascii[c1 | ptp_uc];
    if (c == 0)
        return SCPE_OK;
    if (c == '\n') {                                    /* new line? */
        putc ('\r', uptr->fileref);                     /* cr first */
        uptr->pos = uptr->pos + 1;
        }
    }
else c = uptr->buf;        
if (putc (c, uptr->fileref) == EOF) {                   /* I/O error? */
    sim_perror ("PTP I/O error");
    clearerr (uptr->fileref);
    return SCPE_IOERR;
    }
uptr->pos = uptr->pos + 1;
return SCPE_OK;
}
Ejemplo n.º 11
0
t_stat hsr_svc (UNIT *uptr)
{
int32 temp;

if ((hsr_unit.flags & UNIT_ATT) == 0)                   /* attached? */
    return IORETURN (hsr_stopioe, SCPE_UNATT);
if ((temp = getc (hsr_unit.fileref)) == EOF) {          /* read char */
    if (feof (hsr_unit.fileref)) {                      /* err or eof? */
        if (hsr_stopioe)
            printf ("HSR end of file\n");
        else return SCPE_OK;
        }
    else perror ("HSR I/O error");
    clearerr (hsr_unit.fileref);
    return SCPE_IOERR;
    }
dev_done = dev_done | INT_HSR;                          /* set ready */
hsr_unit.buf = temp & 0377;                             /* save char */
hsr_unit.pos = hsr_unit.pos + 1;
return SCPE_OK;
}
Ejemplo n.º 12
0
t_stat ptr_svc (UNIT *uptr)
{
int32 temp;

if ((ptr_unit.flags & UNIT_ATT) == 0)                   /* attached? */
    return IORETURN (ptr_stopioe, SCPE_UNATT);
if ((temp = getc (ptr_unit.fileref)) == EOF) {
    if (feof (ptr_unit.fileref)) {
        if (ptr_stopioe)
            printf ("PTR end of file\n");
        else return SCPE_OK;
        }
    else perror ("PTR I/O error");
    clearerr (ptr_unit.fileref);
    return SCPE_IOERR;
    }
dev_done = dev_done | INT_PTR;                          /* set done */
int_req = INT_UPDATE;                                   /* update interrupts */
ptr_unit.buf = temp & 0377;
ptr_unit.pos = ptr_unit.pos + 1;
return SCPE_OK;
}
Ejemplo n.º 13
0
uint32 clkio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
{
IOSIGNAL signal;
IOCYCLE  working_set = IOADDSIR (signal_set);           /* add ioSIR if needed */

while (working_set) {
    signal = IONEXT (working_set);                      /* isolate next signal */

    switch (signal) {                                   /* dispatch I/O signal */

        case ioCLF:                                     /* clear flag flip-flop */
            clk.flag = clk.flagbuf = CLEAR;
            break;


        case ioSTF:                                     /* set flag flip-flop */
        case ioENF:                                     /* enable flag */
            clk.flag = clk.flagbuf = SET;
            break;


        case ioSFC:                                     /* skip if flag is clear */
            setstdSKF (clk);
            break;


        case ioSFS:                                     /* skip if flag is set */
            setstdSKF (clk);
            break;


        case ioIOI:                                     /* I/O data input */
            stat_data = IORETURN (SCPE_OK, clk_error);  /* merge in return status */
            break;


        case ioIOO:                                     /* I/O data output */
            clk_select = IODATA (stat_data) & 07;       /* save select */
            sim_cancel (&clk_unit);                     /* stop the clock */
            clk.control = CLEAR;                        /* clear control */
            working_set = working_set | ioSIR;          /* set interrupt request (IOO normally doesn't) */
            break;


        case ioPOPIO:                                   /* power-on preset to I/O */
            clk.flag = clk.flagbuf = SET;               /* set flag and flag buffer */
            break;


        case ioCRS:                                     /* control reset */
        case ioCLC:                                     /* clear control flip-flop */
            clk.control = CLEAR;
            sim_cancel (&clk_unit);                     /* deactivate unit */
            break;


        case ioSTC:                                             /* set control flip-flop */
            clk.control = SET;
            if (clk_unit.flags & UNIT_DIAG)                     /* diag mode? */
                clk_unit.flags = clk_unit.flags & ~UNIT_IDLE;   /* not calibrated */
            else
                clk_unit.flags = clk_unit.flags | UNIT_IDLE;    /* is calibrated */

            if (!sim_is_active (&clk_unit)) {                   /* clock running? */
                clk_tick = clk_delay (0);                       /* get tick count */

                if ((clk_unit.flags & UNIT_DIAG) == 0)          /* calibrated? */
                    if (clk_select == 2)                        /* 10 msec. interval? */
                        clk_tick = sync_poll (INITIAL);         /* sync poll */
                    else
                        sim_rtcn_init (clk_tick, TMR_CLK);      /* initialize timer */

                sim_activate (&clk_unit, clk_tick);             /* start clock */
                clk_ctr = clk_delay (1);                        /* set repeat ctr */
                }
            clk_error = 0;                                      /* clear error */
            break;


        case ioSIR:                                     /* set interrupt request */
            setstdPRL (clk);                            /* set standard PRL signal */
            setstdIRQ (clk);                            /* set standard IRQ signal */
            setstdSRQ (clk);                            /* set standard SRQ signal */
            break;


        case ioIAK:                                     /* interrupt acknowledge */
            clk.flagbuf = CLEAR;
            break;


        default:                                        /* all other signals */
            break;                                      /*   are ignored */
        }

    working_set = working_set & ~signal;                /* remove current signal from set */
    }

return stat_data;
}
Ejemplo n.º 14
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;
}
Ejemplo n.º 15
0
static SIGNALS_DATA clk_interface (DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
{
INBOUND_SIGNAL signal;
INBOUND_SET    working_set      = inbound_signals;
HP_WORD        outbound_value   = 0;
OUTBOUND_SET   outbound_signals = NO_SIGNALS;

dprintf (clk_dev, DEB_IOB, "Received data %06o with signals %s\n",
         inbound_value, fmt_bitset (inbound_signals, inbound_format));

while (working_set) {
    signal = IONEXTSIG (working_set);                   /* isolate the next signal */

    switch (signal) {                                   /* dispatch an I/O signal */

        case DCONTSTB:
            control_word = inbound_value;               /* save the control word */

            if (control_word & CN_RESET_LOAD_SEL) {     /* if the reset/load selector is set */
                rate = CN_RATE (control_word);          /*   then load the clock rate */

                if (clk_unit [0].flags & UNIT_CALTIME)  /* if in calibrated timing mode */
                    prescaler = scale [rate];           /*   then set the prescaler */
                else                                    /* otherwise */
                    prescaler = 1;                      /*   the prescaler isn't used */

                sim_cancel (&clk_unit [0]);             /* changing the rate restarts the timing divider */

                if (rate > 0) {                                 /* if the rate is valid */
                    clk_unit [0].wait = delay [rate];           /*   then set the initial service delay */
                    sim_rtcn_init (clk_unit [0].wait, TMR_CLK); /* initialize the clock */
                    resync_clock ();                            /*   and reschedule the service */
                    }
                }

            else if (control_word & CN_MR) {            /* otherwise, if the master reset bit is set */
                clk_reset (&clk_dev);                   /*   then reset the interface */
                control_word = 0;                       /*     (which clears the other settings) */
                }

            if (control_word & CN_IRQ_RESET_ALL) {      /* if a reset of all interrupts is requested */
                limit_irq     = CLEAR;                  /*   then clear the limit = count, */
                lost_tick_irq = CLEAR;                  /*     limit = count overflow, */
                system_irq    = CLEAR;                  /*       and system flip-flops */
                }

            else if (control_word & CN_IRQ_RESET_MASK)  /* otherwise if any single resets are requested */
                switch (CN_RESET (control_word)) {      /*   then reset the specified flip-flop */
                    case 1:
                        limit_irq = CLEAR;              /* clear the limit = count interrupt request */
                        break;

                    case 2:
                        lost_tick_irq = CLEAR;          /* clear the limit = count overflow interrupt request */
                        break;

                    case 3:
                        system_irq = CLEAR;             /* clear the system interrupt request */
                        break;

                    default:                            /* the rest of the values do nothing */
                        break;
                    }

            if (dibptr->interrupt_active == CLEAR)      /* if no interrupt is active */
                working_set |= DRESETINT;               /*   then recalculate interrupt requests */

            dprintf (clk_dev, DEB_CSRW, (inbound_value & CN_RESET_LOAD_SEL
                                           ? "Control is %s | %s rate%s\n"
                                           : "Control is %s%.0s%s\n"),
                     fmt_bitset (inbound_value, control_format),
                     rate_name [CN_RATE (inbound_value)],
                     irq_reset_name [CN_RESET (inbound_value)]);
            break;


        case DSTATSTB:
            status_word = ST_DIO_OK | ST_RATE (rate);   /* set the clock rate */

            if (limit_irq)                              /* if the limit = count flip-flop is set */
                status_word |= ST_LR_EQ_CR;             /*   set the corresponding status bit */

            if (lost_tick_irq)                          /* if the limit = count overflow flip-flop is set */
                status_word |= ST_LR_EQ_CR_OVFL;        /*   set the corresponding status bit */

            if (system_irq)                             /* if the system interrupt request flip-flop is set */
                status_word |= ST_SYSTEM_IRQ;           /*   set the corresponding status bit */

            if (control_word & CN_LIMIT_COUNT_SEL)      /* if the limit/count selector is set */
                status_word |= ST_LIMIT_COUNT_SEL;      /*   set the corresponding status bit */

            if (control_word & CN_COUNT_RESET)          /* if the reset-after-interrupt selector is set */
                status_word |= ST_COUNT_RESET;          /*   set the corresponding status bit */

            outbound_value = status_word;               /* return the status word */

            dprintf (clk_dev, DEB_CSRW, "Status is %s%s rate\n",
                     fmt_bitset (outbound_value, status_format),
                     rate_name [ST_TO_RATE (outbound_value)]);
            break;


        case DREADSTB:
            clk_update_counter ();                          /* update the clock counter register */
            outbound_value = LOWER_WORD (count_register);   /*   and then read it */

            dprintf (clk_dev, DEB_CSRW, "Count register value %u returned\n",
                     count_register);
            break;


        case DWRITESTB:
            if (control_word & CN_LIMIT_COUNT_SEL) {    /* if the limit/count selector is set */
                clk_update_counter ();                  /*   then update the clock counter register */
                count_register = 0;                     /*     and then clear it */

                dprintf (clk_dev, DEB_CSRW, "Count register cleared\n");
                }

            else {                                      /* otherwise */
                limit_register = inbound_value;         /*   set the limit register to the supplied value */

                dprintf (clk_dev, DEB_CSRW, "Limit register value %u set\n",
                         limit_register);

                coschedulable = (ticks [rate] == 1000           /* the clock can be coscheduled if the rate */
                                  && limit_register == 100);    /*   is 1 msec and the limit is 100 ticks */
                }
            break;


        case DSETINT:
            system_irq = SET;                           /* set the system interrupt request flip-flop */

            dibptr->interrupt_request = SET;            /* request an interrupt */
            outbound_signals |= INTREQ;                 /*   and notify the IOP */
            break;


        case DRESETINT:
            dibptr->interrupt_active  = CLEAR;          /* clear the Interrupt Active flip-flop */

            if ((limit_irq == SET || lost_tick_irq == SET)  /* if the limit or lost tick flip-flops are set */
              && control_word & CN_IRQ_ENABLE)              /*   and interrupts are enabled */
                dibptr->interrupt_request = SET;            /*     then set the interrupt request flip-flop */
            else                                            /* otherwise */
                dibptr->interrupt_request = system_irq;     /*   request an interrupt if the system flip-flop is set */

            if (dibptr->interrupt_request)              /* if a request is pending */
                outbound_signals |= INTREQ;             /*   then notify the IOP */
            break;


        case INTPOLLIN:
            if (dibptr->interrupt_request) {            /* if a request is pending */
                dibptr->interrupt_request = CLEAR;      /*   then clear it */
                dibptr->interrupt_active  = SET;        /*     and mark it as now active */

                outbound_signals |= INTACK;             /* acknowledge the interrupt */
                outbound_value = dibptr->device_number; /*   and return our device number */
                }

            else                                        /* otherwise the request has been reset */
                outbound_signals |= INTPOLLOUT;         /*   so let the IOP know to cancel it */
            break;


        case DSTARTIO:                                  /* not used by this interface */
        case DSETMASK:                                  /* not used by this interface */
        case ACKSR:                                     /* not used by this interface */
        case TOGGLESR:                                  /* not used by this interface */
        case SETINT:                                    /* not used by this interface */
        case PCMD1:                                     /* not used by this interface */
        case PCONTSTB:                                  /* not used by this interface */
        case SETJMP:                                    /* not used by this interface */
        case PSTATSTB:                                  /* not used by this interface */
        case PWRITESTB:                                 /* not used by this interface */
        case PREADSTB:                                  /* not used by this interface */
        case EOT:                                       /* not used by this interface */
        case TOGGLEINXFER:                              /* not used by this interface */
        case TOGGLEOUTXFER:                             /* not used by this interface */
        case READNEXTWD:                                /* not used by this interface */
        case TOGGLESIOOK:                               /* not used by this interface */
        case DEVNODB:                                   /* not used by this interface */
        case XFERERROR:                                 /* not used by this interface */
        case CHANSO:                                    /* not used by this interface */
        case PFWARN:                                    /* not used by this interface */
            break;
        }

    IOCLEARSIG (working_set, signal);                   /* remove the current signal from the set */
    }

dprintf (clk_dev, DEB_IOB, "Returned data %06o with signals %s\n",
         outbound_value, fmt_bitset (outbound_signals, outbound_format));

return IORETURN (outbound_signals, outbound_value);     /* return the outbound signals and value */
}
Ejemplo n.º 16
0
t_stat rp_svc (UNIT *uptr)
{
int32 f, u, comp, cyl, sect, surf;
int32 err, pa, da, wc, awc, i;

u = (int32) (uptr - rp_dev.units);                      /* get drv number */
f = uptr->FUNC;                                         /* get function */
if (f == FN_IDLE) {                                     /* idle? */
    rp_busy = 0;                                        /* clear busy */
    return SCPE_OK;
    }

if ((f == FN_SEEK) || (f == FN_RECAL)) {                /* seek or recal? */
    rp_busy = 0;                                        /* not busy */
    cyl = (f == FN_SEEK)? GET_CYL (rp_da): 0;           /* get cylinder */
    sim_activate (uptr, MAX (RP_MIN, abs (cyl - uptr->CYL) * rp_swait));
    uptr->CYL = cyl;                                    /* on cylinder */
    uptr->FUNC = FN_SEEK | FN_2ND;                      /* set second state */
    rp_updsta (0, 0);                                   /* update status */
    return SCPE_OK;
    }

if (f == (FN_SEEK | FN_2ND)) {                          /* seek done? */
    rp_updsta (0, rp_stb | (1 << (STB_V_ATT0 - u)));    /* set attention */
    return SCPE_OK;
    }

if ((uptr->flags & UNIT_ATT) == 0) {                    /* not attached? */
    rp_updsta (STA_DON, STB_SUFU);                      /* done, unsafe */
    return IORETURN (rp_stopioe, SCPE_UNATT);
    }

if ((f == FN_WRITE) && (uptr->flags & UNIT_WPRT)) {     /* write locked? */
    rp_updsta (STA_DON | STA_WPE, 0);                   /* error */
    return SCPE_OK;
    }

if (GET_SECT (rp_da) >= RP_NUMSC)
    rp_updsta (STA_NXS, 0);
if (GET_SURF (rp_da) >= RP_NUMSF)
    rp_updsta (STA_NXF, 0);
if (GET_CYL (rp_da) >= RP_NUMCY)
    rp_updsta (STA_NXC, 0);
if (rp_sta & (STA_NXS | STA_NXF | STA_NXC)) {           /* or bad disk addr? */
    rp_updsta (STA_DON, STB_SUFU);                      /* done, unsafe */
    return SCPE_OK;
    }

pa = rp_ma & AMASK;                                     /* get mem addr */
da = GET_DA (rp_da) * RP_NUMWD;                         /* get disk addr */
wc = 01000000 - rp_wc;                                  /* get true wc */
if (((uint32) (pa + wc)) > MEMSIZE) {                   /* memory overrun? */
    nexm = 1;                                           /* set nexm flag */
    wc = MEMSIZE - pa;                                  /* limit xfer */
    }
if ((da + wc) > RP_SIZE) {                              /* disk overrun? */
    rp_updsta (0, STB_EOP);                             /* error */
    wc = RP_SIZE - da;                                  /* limit xfer */
    }

err = fseek (uptr->fileref, da * sizeof (int), SEEK_SET);

if ((f == FN_READ) && (err == 0)) {                     /* read? */
    awc = fxread (&M[pa], sizeof (int32), wc, uptr->fileref);
    for ( ; awc < wc; awc++)
        M[pa + awc] = 0;
    err = ferror (uptr->fileref);
    }

if ((f == FN_WRITE) && (err == 0)) {                    /* write? */
    fxwrite (&M[pa], sizeof (int32), wc, uptr->fileref);
    err = ferror (uptr->fileref);
    if ((err == 0) && (i = (wc & (RP_NUMWD - 1)))) {
        fxwrite (fill, sizeof (int), i, uptr->fileref);
        err = ferror (uptr->fileref);
        }
    }

if ((f == FN_WRCHK) && (err == 0)) {                    /* write check? */
    for (i = 0; (err == 0) && (i < wc); i++)  {
        awc = fxread (&comp, sizeof (int32), 1, uptr->fileref);
        if (awc == 0)
            comp = 0;
        if (comp != M[pa + i])
            rp_updsta (0, STB_WCE);
        }
    err = ferror (uptr->fileref);
    }

rp_wc = (rp_wc + wc) & DMASK;                           /* final word count */
rp_ma = (rp_ma + wc) & DMASK;                           /* final mem addr */
da = (da + wc + (RP_NUMWD - 1)) / RP_NUMWD;             /* final sector num */
cyl = da / (RP_NUMSC * RP_NUMSF);                       /* get cyl */
if (cyl >= RP_NUMCY)
    cyl = RP_NUMCY - 1;
surf = (da % (RP_NUMSC * RP_NUMSF)) / RP_NUMSC;         /* get surface */
sect = (da % (RP_NUMSC * RP_NUMSF)) % RP_NUMSC;         /* get sector */
rp_da = (cyl << DA_V_CYL) | (surf << DA_V_SURF) | (sect << DA_V_SECT);
rp_busy = 0;                                            /* clear busy */
rp_updsta (STA_DON, 0);                                 /* set done */

if (err != 0) {                                         /* error? */
    perror ("RP I/O error");
    clearerr (uptr->fileref);
    return IORETURN (rp_stopioe, SCPE_IOERR);
    }
return SCPE_OK;
}
Ejemplo n.º 17
0
t_stat rk_svc (UNIT *uptr)
{
int32 err, wc, wc1, awc, swc, pa, da;
UNIT *seluptr;

if (uptr->FUNC == RKC_SEEK) {                           /* seek? */
    seluptr = rk_dev.units + GET_DRIVE (rk_cmd);        /* see if selected */
    if ((uptr == seluptr) && ((rk_cmd & RKC_SKDN) != 0)) {
        rk_sta = rk_sta | RKS_DONE;
        RK_INT_UPDATE;
        }
    return SCPE_OK;
    }

if ((uptr->flags & UNIT_ATT) == 0) {                    /* not att? abort */
    rk_sta = rk_sta | RKS_DONE | RKS_NRDY | RKS_STAT;
    rk_busy = 0;
    RK_INT_UPDATE;
    return IORETURN (rk_stopioe, SCPE_UNATT);
    }

if ((uptr->FUNC == RKC_WRITE) && (uptr->flags & UNIT_WPRT)) {
    rk_sta = rk_sta | RKS_DONE | RKS_WLK;               /* write and locked? */
    rk_busy = 0;
    RK_INT_UPDATE;
    return SCPE_OK;
    }

pa = GET_MEX (rk_cmd) | rk_ma;                          /* phys address */
da = GET_DA (rk_cmd, rk_da) * RK_NUMWD * sizeof (int16);/* disk address */
swc = wc = (rk_cmd & RKC_HALF)? RK_NUMWD / 2: RK_NUMWD; /* get transfer size */
if ((wc1 = ((rk_ma + wc) - 010000)) > 0)                /* if wrap, limit */
    wc = wc - wc1;
err = fseek (uptr->fileref, da, SEEK_SET);              /* locate sector */

if ((uptr->FUNC == RKC_READ) && (err == 0) && MEM_ADDR_OK (pa)) { /* read? */
    awc = fxread (&M[pa], sizeof (int16), wc, uptr->fileref);
    for ( ; awc < wc; awc++)                            /* fill if eof */
        M[pa + awc] = 0;
    err = ferror (uptr->fileref);
    if ((wc1 > 0) && (err == 0))  {                     /* field wraparound? */
        pa = pa & 070000;                               /* wrap phys addr */
        awc = fxread (&M[pa], sizeof (int16), wc1, uptr->fileref);
        for ( ; awc < wc1; awc++)                       /* fill if eof */
            M[pa + awc] = 0;
        err = ferror (uptr->fileref);
        }
    }

if ((uptr->FUNC == RKC_WRITE) && (err == 0)) {          /* write? */
    fxwrite (&M[pa], sizeof (int16), wc, uptr->fileref);
    err = ferror (uptr->fileref);
    if ((wc1 > 0) && (err == 0)) {                      /* field wraparound? */
        pa = pa & 070000;                               /* wrap phys addr */
        fxwrite (&M[pa], sizeof (int16), wc1, uptr->fileref);
        err = ferror (uptr->fileref);
        }
    if ((rk_cmd & RKC_HALF) && (err == 0)) {            /* fill half sector */
        fxwrite (fill, sizeof (int16), RK_NUMWD/2, uptr->fileref);
        err = ferror (uptr->fileref);
        }
    }

rk_ma = (rk_ma + swc) & 07777;                          /* incr mem addr reg */
rk_sta = rk_sta | RKS_DONE;                             /* set done */
rk_busy = 0;
RK_INT_UPDATE;

if (err != 0) {
    sim_perror ("RK I/O error");
    clearerr (uptr->fileref);
    return SCPE_IOERR;
    }
return SCPE_OK;
}
Ejemplo n.º 18
0
uint32 lptio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
{
uint16 data;
IOSIGNAL signal;
IOCYCLE  working_set = IOADDSIR (signal_set);           /* add ioSIR if needed */

while (working_set) {
    signal = IONEXT (working_set);                      /* isolate next signal */

    switch (signal) {                                   /* dispatch I/O signal */

        case ioCLF:                                     /* clear flag flip-flop */
            lpt.flag = lpt.flagbuf = CLEAR;
            break;


        case ioSTF:                                     /* set flag flip-flop */
        case ioENF:                                     /* enable flag */
            lpt.flag = lpt.flagbuf = SET;
            break;


        case ioSFC:                                     /* skip if flag is clear */
            setstdSKF (lpt);
            break;


        case ioSFS:                                     /* skip if flag is set */
            setstdSKF (lpt);
            break;


        case ioIOI:                                         /* I/O data input */
            data = 0;

            if (lpt_unit.flags & UNIT_POWEROFF)             /* power off? */
                data = LPT_PWROFF;

            else if (!(lpt_unit.flags & UNIT_OFFLINE)) {    /* online? */
                if (lpt_unit.flags & UNIT_ATT) {            /* paper loaded? */
                    data = LPT_RDY;
                    if (!sim_is_active (&lpt_unit))         /* printer busy? */
                        data = data | LPT_NBSY;
                    }

                else if (lpt_lcnt == LPT_PAGELNT - 1)       /* paper out, at BOF? */
                    data = LPT_PAPO;
                }

            stat_data = IORETURN (SCPE_OK, data);           /* merge in return status */
            break;


        case ioIOO:                                     /* I/O data output */
            lpt_unit.buf = IODATA (stat_data) & (LPT_CTL | 0177);
            break;


        case ioPOPIO:                                   /* power-on preset to I/O */
            lpt.flag = lpt.flagbuf = SET;               /* set flag and flag buffer */
            lpt_unit.buf = 0;                           /* clear output buffer */
            break;

        case ioCRS:                                     /* control reset */
        case ioCLC:                                     /* clear control flip-flop */
            lpt.control = CLEAR;
            break;


        case ioSTC:                                     /* set control flip-flop */
            lpt.control = SET;
            sim_activate (&lpt_unit,                    /* schedule op */
                (lpt_unit.buf & LPT_CTL)? lpt_ptime: lpt_ctime);
            break;


        case ioSIR:                                     /* set interrupt request */
            setstdPRL (lpt);                            /* set standard PRL signal */
            setstdIRQ (lpt);                            /* set standard IRQ signal */
            setstdSRQ (lpt);                            /* set standard SRQ signal */
            break;


        case ioIAK:                                     /* interrupt acknowledge */
            lpt.flagbuf = CLEAR;
            break;


        default:                                        /* all other signals */
            break;                                      /*   are ignored */
        }

    working_set = working_set & ~signal;                /* remove current signal from set */
    }

return stat_data;
}
Ejemplo n.º 19
0
uint32 dqcio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
{
int32 fnc, drv;
IOSIGNAL signal;
IOCYCLE  working_set = IOADDSIR (signal_set);           /* add ioSIR if needed */

while (working_set) {
    signal = IONEXT (working_set);                      /* isolate next signal */

    switch (signal) {                                   /* dispatch I/O signal */

        case ioCLF:                                     /* clear flag flip-flop */
            dqc.flag = dqc.flagbuf = CLEAR;
            break;


        case ioSTF:                                     /* set flag flip-flop */
        case ioENF:                                     /* enable flag */
            dqc.flag = dqc.flagbuf = SET;
            break;


        case ioSFC:                                     /* skip if flag is clear */
            setstdSKF (dqc);
            break;


        case ioSFS:                                     /* skip if flag is set */
            setstdSKF (dqc);
            break;


        case ioIOI:                                     /* I/O data input */
            stat_data = IORETURN (SCPE_OK, 0);          /* no data */
            break;


        case ioIOO:                                     /* I/O data output */
            dqc_obuf = IODATA (stat_data);              /* clear supplied status */
            break;


        case ioPOPIO:                                   /* power-on preset to I/O */
            dqc.flag = dqc.flagbuf = SET;               /* set flag and flag buffer */
            dqc_obuf = 0;                               /* clear output buffer */
            break;


        case ioCRS:                                     /* control reset */
        case ioCLC:                                     /* clear control flip-flop */
            dqc.command = CLEAR;                        /* clear command */
            dqc.control = CLEAR;                        /* clear control */

            if (dqc_busy)
                sim_cancel (&dqc_unit[dqc_busy - 1]);

            sim_cancel (&dqd_unit);                     /* cancel dch */
            dqd_xfer = 0;                               /* clr dch xfer */
            dqc_busy = 0;                               /* clr busy */
            break;


        case ioSTC:                                     /* set control flip-flop */
            dqc.control = SET;                          /* set ctl */

            if (!dqc.command) {                         /* cmd clr? */
                dqc.command = SET;                      /* set cmd */
                drv = CW_GETDRV (dqc_obuf);             /* get fnc, drv */
                fnc = CW_GETFNC (dqc_obuf);             /* from cmd word */

                switch (fnc) {                          /* case on fnc */
                    case FNC_SEEK: case FNC_RCL:        /* seek, recal */
                    case FNC_CHK:                       /* check */
                        dqc_sta[drv] = 0;               /* clear status */
                    case FNC_STA: case FNC_LA:          /* rd sta, load addr */
                        dq_god (fnc, drv, dqc_dtime);   /* sched dch xfer */
                        break;
                    case FNC_RD: case FNC_WD:           /* read, write */
                    case FNC_RA: case FNC_WA:           /* rd addr, wr addr */
                    case FNC_AS:                        /* address skip */
                        dq_goc (fnc, drv, dqc_ctime);   /* sched drive */
                        break;
                    }                                   /* end case */
                }                                       /* end if !CMD */
            break;


        case ioSIR:                                     /* set interrupt request */
            setstdPRL (dqc);                            /* set standard PRL signal */
            setstdIRQ (dqc);                            /* set standard IRQ signal */
            setstdSRQ (dqc);                            /* set standard SRQ signal */
            break;


        case ioIAK:                                     /* interrupt acknowledge */
            dqc.flagbuf = CLEAR;
            break;


        default:                                        /* all other signals */
            break;                                      /*   are ignored */
        }

    working_set = working_set & ~signal;                /* remove current signal from set */
    }
return stat_data;
}
Ejemplo n.º 20
0
uint32 dqdio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
{
IOSIGNAL signal;
IOCYCLE  working_set = IOADDSIR (signal_set);           /* add ioSIR if needed */

while (working_set) {
    signal = IONEXT (working_set);                      /* isolate next signal */

    switch (signal) {                                   /* dispatch I/O signal */

        case ioCLF:                                     /* clear flag flip-flop */
            dqd.flag = dqd.flagbuf = CLEAR;
            break;


        case ioSTF:                                     /* set flag flip-flop */
        case ioENF:                                     /* enable flag */
            dqd.flag = dqd.flagbuf = SET;
            break;


        case ioSFC:                                     /* skip if flag is clear */
            setstdSKF (dqd);
            break;


        case ioSFS:                                     /* skip if flag is set */
            setstdSKF (dqd);
            break;


        case ioIOI:                                     /* I/O data input */
            stat_data = IORETURN (SCPE_OK, dqd_ibuf);   /* merge in return status */
            break;


        case ioIOO:                                     /* I/O data output */
            dqd_obuf = IODATA (stat_data);              /* clear supplied status */

            if (!dqc_busy || dqd_xfer)
                dqd_wval = 1;                           /* if !overrun, valid */
            break;


        case ioPOPIO:                                   /* power-on preset to I/O */
            dqd.flag = dqd.flagbuf = SET;               /* set flag and flag buffer */
            dqd_obuf = 0;                               /* clear output buffer */
            break;


        case ioCRS:                                     /* control reset */
            dqd.command = CLEAR;                        /* clear command */
                                                        /* fall into CLC handler */

        case ioCLC:                                     /* clear control flip-flop */
            dqd.control = CLEAR;                        /* clear control */
            dqd_xfer = 0;                               /* clr xfer */
            break;


        case ioSTC:                                     /* set control flip-flop */
            dqd.command = SET;                          /* set ctl, cmd */
            dqd.control = SET;

            if (dqc_busy && !dqd_xfer)                  /* overrun? */
                dqc_sta[dqc_busy - 1] |= STA_DTE;
            break;


        case ioSIR:                                     /* set interrupt request */
            setstdPRL (dqd);                            /* set standard PRL signal */
            setstdIRQ (dqd);                            /* set standard IRQ signal */
            setstdSRQ (dqd);                            /* set standard SRQ signal */
            break;


        case ioIAK:                                     /* interrupt acknowledge */
            dqd.flagbuf = CLEAR;
            break;


        default:                                        /* all other signals */
            break;                                      /*   are ignored */
        }

    working_set = working_set & ~signal;                /* remove current signal from set */
    }

return stat_data;
}
Ejemplo n.º 21
0
t_stat rx_svc (UNIT *uptr)
{
int32 i, func;
uint32 da;
int8 *fbuf = uptr->filebuf;

func = RXCS_GETFNC (rx_csr);                            /* get function */
switch (rx_state) {                                     /* case on state */

    case IDLE:                                          /* idle */
        return SCPE_IERR;                               /* done */

    case EMPTY:                                         /* empty buffer */
        if (rx_bptr >= RX_NUMBY)                        /* done all? */
            rx_done (0, 0);
        else {
            rx_dbr = rx_buf[rx_bptr];                   /* get next */
            rx_bptr = rx_bptr + 1;
            rx_csr = rx_csr | RXCS_TR;                  /* set xfer */
            }
        break;

    case FILL:                                          /* fill buffer */
        rx_buf[rx_bptr] = rx_dbr;                       /* write next */
        rx_bptr = rx_bptr + 1;
        if (rx_bptr < RX_NUMBY)                         /* more? set xfer */
            rx_csr = rx_csr | RXCS_TR;
        else rx_done (0, 0);                            /* else done */
        break;

    case RWDS:                                          /* wait for sector */
        rx_sector = rx_dbr & RX_M_SECTOR;               /* save sector */
        rx_csr = rx_csr | RXCS_TR;                      /* set xfer */
        rx_state = RWDT;                                /* advance state */
        return SCPE_OK;

    case RWDT:                                          /* wait for track */
        rx_track = rx_dbr & RX_M_TRACK;                 /* save track */
        rx_state = RWXFR;
        sim_activate (uptr,                             /* sched done */
                rx_swait * abs (rx_track - uptr->TRACK));
        return SCPE_OK;

    case RWXFR:
        if ((uptr->flags & UNIT_BUF) == 0) {            /* not buffered? */
            rx_done (0, 0110);                          /* done, error */
            return IORETURN (rx_stopioe, SCPE_UNATT);
            }
        if (rx_track >= RX_NUMTR) {                     /* bad track? */
            rx_done (0, 0040);                          /* done, error */
            break;
            }
        uptr->TRACK = rx_track;                         /* now on track */
        if ((rx_sector == 0) || (rx_sector > RX_NUMSC)) { /* bad sect? */
            rx_done (0, 0070);                          /* done, error */
            break;
            }
        da = CALC_DA (rx_track, rx_sector);             /* get disk address */
        if (func == RXCS_WRDEL)                         /* del data? */
            rx_esr = rx_esr | RXES_DD;
        if (func == RXCS_READ) {                        /* read? */
            for (i = 0; i < RX_NUMBY; i++)
                rx_buf[i] = fbuf[da + i];
            }
        else {
            if (uptr->flags & UNIT_WPRT) {              /* write and locked? */
                rx_done (RXES_WLK, 0100);               /* done, error */
                break;
                }
            for (i = 0; i < RX_NUMBY; i++)              /* write */
                fbuf[da + i] = rx_buf[i];
            da = da + RX_NUMBY;
            if (da > uptr->hwmark)
                uptr->hwmark = da;
            }
        rx_done (0, 0);                                 /* done */
        break;

    case CMD_COMPLETE:                                  /* command complete */
        if (func == RXCS_ECODE) {                       /* read ecode? */
            rx_dbr = rx_ecode;                          /* set dbr */
            rx_done (0, -1);                            /* don't update */
            }
        else rx_done (0, 0);
        break;

    case INIT_COMPLETE:                                 /* init complete */
        rx_unit[0].TRACK = 1;                           /* drive 0 to trk 1 */
        rx_unit[1].TRACK = 0;                           /* drive 1 to trk 0 */
        if ((rx_unit[0].flags & UNIT_BUF) == 0) {       /* not buffered? */
            rx_done (RXES_ID, 0010);                    /* init done, error */
            break;
            }
        da = CALC_DA (1, 1);                            /* track 1, sector 1 */
        for (i = 0; i < RX_NUMBY; i++)                  /* read sector */
            rx_buf[i] = fbuf[da + i];
        rx_done (RXES_ID, 0);                           /* set done */
        if ((rx_unit[1].flags & UNIT_ATT) == 0)
            rx_ecode = 0020;
        break;
        }                                               /* end case state */

return SCPE_OK;
}
Ejemplo n.º 22
0
Archivo: id_mt.c Proyecto: ST3ALth/simh
t_stat mt_svc (UNIT *uptr)
{
uint32 i;
int32 u = uptr - mt_dev.units;
uint32 dev = mt_dib.dno + (u * o_MT0);
t_mtrlnt tbc;
t_bool passed_eot;
t_stat st, r = SCPE_OK;

if ((uptr->flags & UNIT_ATT) == 0) {                    /* not attached? */
    uptr->UCMD = 0;                                     /* clr cmd */
    uptr->UST = 0;                                      /* set status */
    mt_xfr = 0;                                         /* clr op flags */
    mt_sta = STA_ERR | STA_EOM;                         /* set status */
    if (mt_arm[u])                                      /* interrupt */
        SET_INT (v_MT + u);
    return IORETURN (mt_stopioe, SCPE_UNATT);
    }

if (uptr->UCMD & MTC_STOP2) {                           /* stop, gen NMTN? */
    uptr->UCMD = 0;                                     /* clr cmd */
    uptr->UST = uptr->UST | STA_NMTN;                   /* set nmtn */
    mt_xfr = 0;                                         /* clr xfr */
    if (mt_arm[u])                                      /* set intr */
        SET_INT (v_MT + u);
    return SCPE_OK;
    }

if (uptr->UCMD & MTC_STOP1) {                           /* stop, gen EOM? */
    uptr->UCMD = uptr->UCMD | MTC_STOP2;                /* clr cmd */
    mt_sta = (mt_sta & ~STA_BSY) | STA_EOM;             /* clr busy, set eom */
    if (mt_arm[u])                                      /* set intr */
        SET_INT (v_MT + u);
    sim_activate (uptr, mt_rtime);                      /* schedule */
    return SCPE_OK;
    }

passed_eot = sim_tape_eot (uptr);                       /* passed EOT? */
switch (uptr->UCMD) {                                   /* case on function */

    case MTC_REW:                                       /* rewind */
        sim_tape_rewind (uptr);                         /* reposition */
        uptr->UCMD = 0;                                 /* clr cmd */
        uptr->UST = STA_NMTN | STA_EOT;                 /* update status */
        mt_sta = mt_sta & ~STA_BSY;                     /* don't set EOM */
        if (mt_arm[u])                                  /* interrupt */
            SET_INT (v_MT + u);
        return SCPE_OK;

/* For read, busy = 1 => buffer empty
   For write, busy = 1 => buffer full
   For read, data transfers continue for the full length of the
        record, or the maximum size of the transfer buffer
   For write, data transfers continue until a write is attempted
        and the buffer is empty
*/

    case MTC_RD:                                        /* read */
        if (mt_blnt == 0) {                             /* first time? */
            st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
            if (st == MTSE_RECE)                        /* rec in err? */
                mt_sta = mt_sta | STA_ERR;
            else if (st != SCPE_OK) {                   /* other error? */
                r = mt_map_err (uptr, st);              /* map error */
                if (sch_actv (mt_dib.sch, dev))         /* if sch, stop */
                    sch_stop (mt_dib.sch);
                break;
                }
            mt_blnt = tbc;                              /* set buf lnt */
            }

        if (sch_actv (mt_dib.sch, dev)) {               /* sch active? */
            i = sch_wrmem (mt_dib.sch, mtxb, mt_blnt);  /* store rec in mem */
            if (sch_actv (mt_dib.sch, dev))             /* sch still active? */
                sch_stop (mt_dib.sch);                  /* stop chan, long rd */
            else if (i < mt_blnt)                       /* process entire rec? */
                mt_sta = mt_sta | STA_ERR;              /* no, overrun error */
            }
        else if (mt_bptr < mt_blnt) {                   /* no, if !eor */
            if (!(mt_sta & STA_BSY))                    /* busy still clr? */
                mt_sta = mt_sta | STA_ERR;              /* read overrun */
            mt_db = mtxb[mt_bptr++];                    /* get next byte */
            mt_sta = mt_sta & ~STA_BSY;                 /* !busy = buf full */
            if (mt_arm[u])                              /* set intr */
                SET_INT (v_MT + u);
            sim_activate (uptr, mt_wtime);              /* reschedule */
            return SCPE_OK;
            }
        break;                                          /* record done */

    case MTC_WR:                                        /* write */
        if (sch_actv (mt_dib.sch, dev)) {               /* sch active? */
            mt_bptr = sch_rdmem (mt_dib.sch, mtxb, MT_MAXFR); /* get rec */
            if (sch_actv (mt_dib.sch, dev))             /* not done? */
                sch_stop (mt_dib.sch);                  /* stop chan */
            }
        else if (mt_sta & STA_BSY) {                    /* no, if !eor */
            if (mt_bptr < MT_MAXFR)                     /* if room */
                mtxb[mt_bptr++] = mt_db;                /* store in buf */
            mt_sta = mt_sta & ~STA_BSY;                 /* !busy = buf emp */
            if (mt_arm[u])                              /* set intr */
                SET_INT (v_MT + u);
            sim_activate (uptr, mt_wtime);              /* reschedule */
            return SCPE_OK;
            }

        if (mt_bptr) {                                  /* any chars? */
            if ((st = sim_tape_wrrecf (uptr, mtxb, mt_bptr)))/* write, err? */
                r = mt_map_err (uptr, st);              /* map error */
            }
        break;                                          /* record done */

    case MTC_WEOF:                                      /* write eof */
        if ((st = sim_tape_wrtmk (uptr)))               /* write tmk, err? */
            r = mt_map_err (uptr, st);                  /* map error */
        mt_sta = mt_sta | STA_EOF;                      /* set eof */
        if (mt_arm[u])                                  /* set intr */
            SET_INT (v_MT + u);
        break;

    case MTC_SKFF:                                      /* skip file fwd */
        while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
        if (st == MTSE_TMK) {                           /* stopped by tmk? */
            mt_sta = mt_sta | STA_EOF;                  /* set eof */
            if (mt_arm[u])                              /* set intr */
                SET_INT (v_MT + u);
            }
        else r = mt_map_err (uptr, st);                 /* map error */
        break;

    case MTC_SKFR:                                      /* skip file rev */
        while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
        if (st == MTSE_TMK) {                           /* stopped by tmk? */
            mt_sta = mt_sta | STA_EOF;                  /* set eof */
            if (mt_arm[u])                              /* set intr */
                SET_INT (v_MT + u);
            }
        else r = mt_map_err (uptr, st);                 /* map error */
        break;

    case MTC_SPCR:                                      /* backspace */
        if ((st = sim_tape_sprecr (uptr, &tbc)))        /* skip rec rev, err? */
            r = mt_map_err (uptr, st);                  /* map error */
        break;
        }                                               /* end case */

if (!passed_eot && sim_tape_eot (uptr))                 /* just passed EOT? */
    uptr->UST = uptr->UST | STA_EOT;
uptr->UCMD = uptr->UCMD | MTC_STOP1;                    /* set stop stage 1 */
sim_activate (uptr, mt_rtime);                          /* schedule */
return r;
}
Ejemplo n.º 23
0
uint32 ptpio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
{
IOSIGNAL signal;
IOCYCLE  working_set = IOADDSIR (signal_set);           /* add ioSIR if needed */

while (working_set) {
    signal = IONEXT (working_set);                      /* isolate next signal */

    switch (signal) {                                   /* dispatch I/O signal */

        case ioCLF:                                     /* clear flag flip-flop */
            ptp.flag = ptp.flagbuf = CLEAR;
            break;


        case ioSTF:                                     /* set flag flip-flop */
        case ioENF:                                     /* enable flag */
            ptp.flag = ptp.flagbuf = SET;
            break;


        case ioSFC:                                     /* skip if flag is clear */
            setstdSKF (ptp);
            break;


        case ioSFS:                                     /* skip if flag is set */
            setstdSKF (ptp);
            break;


        case ioIOI:                                         /* I/O data input */
            if ((ptp_unit.flags & UNIT_ATT) == 0)           /* not attached? */
                stat_data = IORETURN (SCPE_OK, PTP_LOW);    /* report as out of tape */
            else
                stat_data = IORETURN (SCPE_OK, 0);
            break;


        case ioIOO:                                     /* I/O data output */
            ptp_unit.buf = IODATA (stat_data);          /* clear supplied status */
            break;


        case ioPOPIO:                                   /* power-on preset to I/O */
            ptp.flag = ptp.flagbuf = SET;               /* set flag and flag buffer */
            ptp_unit.buf = 0;                           /* clear output buffer */
            break;


        case ioCRS:                                     /* control reset */
        case ioCLC:                                     /* clear control flip-flop */
            ptp.control = CLEAR;
            break;


        case ioSTC:                                     /* set control flip-flop */
            ptp.control = SET;
            sim_activate (&ptp_unit, ptp_unit.wait);
            break;


        case ioSIR:                                     /* set interrupt request */
            setstdPRL (ptp);                            /* set standard PRL signal */
            setstdIRQ (ptp);                            /* set standard IRQ signal */
            setstdSRQ (ptp);                            /* set standard SRQ signal */
            break;


        case ioIAK:                                     /* interrupt acknowledge */
            ptp.flagbuf = CLEAR;
            break;


        default:                                        /* all other signals */
            break;                                      /*   are ignored */
        }

    working_set = working_set & ~signal;                /* remove current signal from set */
    }

return stat_data;
}
Ejemplo n.º 24
0
t_stat mtc_svc (UNIT *uptr)
{
t_mtrlnt tbc;
t_stat st, r = SCPE_OK;

if ((mtc_unit.flags & UNIT_ATT) == 0) {                 /* offline? */
    mtc_sta = STA_LOCAL | STA_REJ;                      /* rejected */
    mtcio (mtc_dib.devno, ioENF, 0);                    /* set cch flg */
    return IORETURN (mtc_stopioe, SCPE_UNATT);
    }

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

    case FNC_REW:                                       /* rewind */
        sim_tape_rewind (uptr);                         /* BOT */
        mtc_sta = STA_BOT;                              /* update status */
        break;

    case FNC_RWS:                                       /* rewind and offline */
        sim_tape_rewind (uptr);                         /* clear position */
        return sim_tape_detach (uptr);                  /* don't set cch flg */

    case FNC_WFM:                                       /* write file mark */
        if (st = sim_tape_wrtmk (uptr))                 /* write tmk, err? */
            r = mt_map_err (uptr, st);                  /* map error */
        mtc_sta = STA_EOF;                              /* set EOF status */
        break;

    case FNC_GAP:                                       /* erase gap */
        break;

    case FNC_FSR:                                       /* space forward */
        if (st = sim_tape_sprecf (uptr, &tbc))          /* space rec fwd, err? */
            r = mt_map_err (uptr, st);                  /* map error */
        break;

    case FNC_BSR:                                       /* space reverse */
        if (st = sim_tape_sprecr (uptr, &tbc))          /* space rec rev, err? */
            r = mt_map_err (uptr, st);                  /* map error */
        break;

    case FNC_RC:                                        /* read */
        if (mtc_1st) {                                  /* first svc? */
            mtc_1st = mt_ptr = 0;                       /* clr 1st flop */
            st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */
            if (st == MTSE_RECE) mtc_sta = mtc_sta | STA_PAR;   /* rec in err? */
            else if (st != MTSE_OK) {                   /* other error? */
                r = mt_map_err (uptr, st);              /* map error */
                if (r == SCPE_OK) {                     /* recoverable? */
                    sim_activate (uptr, mtc_gtime);     /* sched IRG */
                    mtc_fnc = 0;                        /* NOP func */
                    return SCPE_OK;
                    }
                break;                                  /* non-recov, done */
                }
            if (mt_max < 12) {                          /* record too short? */
                mtc_sta = mtc_sta | STA_PAR;            /* set flag */
                break;
                }
            }
        if (mtc_dtf && (mt_ptr < mt_max)) {             /* more chars? */
            if (mtd_flag) mtc_sta = mtc_sta | STA_TIM;
            mtc_unit.buf = mtxb[mt_ptr++];              /* fetch next */
            mtdio (mtd_dib.devno, ioENF, 0);            /* set dch flg */
            sim_activate (uptr, mtc_xtime);             /* re-activate */
            return SCPE_OK;
            }
        sim_activate (uptr, mtc_gtime);                 /* schedule gap */
        mtc_fnc = 0;                                    /* nop */
        return SCPE_OK;

    case FNC_WC:                                                /* write */
        if (mtc_1st) mtc_1st = 0;                       /* no xfr on first */
        else {
            if (mt_ptr < DBSIZE) {                      /* room in buffer? */
                mtxb[mt_ptr++] = mtc_unit.buf;
                mtc_sta = mtc_sta & ~STA_BOT;           /* clear BOT */
                }
            else mtc_sta = mtc_sta | STA_PAR;
            }
        if (mtc_dtf) {                                  /* xfer flop set? */
            mtdio (mtd_dib.devno, ioENF, 0);            /* set dch flg */
            sim_activate (uptr, mtc_xtime);             /* re-activate */
            return SCPE_OK;
            }
        if (mt_ptr) {                                   /* write buffer */
            if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) {    /* write, err? */
                r = mt_map_err (uptr, st);              /* map error */
                break;                                  /* done */
                }
            }
        sim_activate (uptr, mtc_gtime);                 /* schedule gap */
        mtc_fnc = 0;                                    /* nop */
        return SCPE_OK;

    default:                                            /* unknown */
        break;
        }

mtcio (mtc_dib.devno, ioENF, 0);                        /* set cch flg */
mtc_sta = mtc_sta & ~STA_BUSY;                          /* not busy */
return r;
}
Ejemplo n.º 25
0
uint32 ttyio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
{
uint16 data;
IOSIGNAL signal;
IOCYCLE  working_set = IOADDSIR (signal_set);           /* add ioSIR if needed */

while (working_set) {
    signal = IONEXT (working_set);                      /* isolate next signal */

    switch (signal) {                                   /* dispatch I/O signal */

        case ioCLF:                                     /* clear flag flip-flop */
            tty.flag = tty.flagbuf = CLEAR;
            break;


        case ioSTF:                                     /* set flag flip-flop */
        case ioENF:                                     /* enable flag */
            tty.flag = tty.flagbuf = SET;
            break;


        case ioSFC:                                     /* skip if flag is clear */
            setstdSKF (tty);
            break;


        case ioSFS:                                     /* skip if flag is set */
            setstdSKF (tty);
            break;


        case ioIOI:                                     /* I/O data input */
            data = tty_buf;

            if (!(tty_mode & TM_KBD) && sim_is_active (&tty_unit[TTO]))
                data = data | TP_BUSY;

            stat_data = IORETURN (SCPE_OK, data);       /* merge in return status */
            break;


        case ioIOO:                                     /* I/O data output */
            data = IODATA (stat_data);                  /* clear supplied status */

            if (data & TM_MODE)
                tty_mode = data & (TM_KBD|TM_PRI|TM_PUN);

            tty_buf = data & 0377;
            break;


        case ioCRS:                                     /* control reset */
            tty.control = CLEAR;                        /* clear control */
            tty.flag = tty.flagbuf = SET;               /* set flag and flag buffer */
            tty_mode = TM_KBD;                          /* set tty, clear print/punch */
            tty_shin = 0377;                            /* input inactive */
            tty_lf = 0;                                 /* no lf pending */
            break;


        case ioCLC:                                     /* clear control flip-flop */
            tty.control = CLEAR;
            break;


        case ioSTC:                                     /* set control flip-flop */
            tty.control = SET;

            if (!(tty_mode & TM_KBD))                   /* output? */
                sim_activate (&tty_unit[TTO], tty_unit[TTO].wait);
            break;


        case ioSIR:                                     /* set interrupt request */
            setstdPRL (tty);                            /* set standard PRL signal */
            setstdIRQ (tty);                            /* set standard IRQ signal */
            setstdSRQ (tty);                            /* set standard SRQ signal */
            break;


        case ioIAK:                                     /* interrupt acknowledge */
            tty.flagbuf = CLEAR;
            break;


        default:                                        /* all other signals */
            break;                                      /*   are ignored */
        }

    working_set = working_set & ~signal;                /* remove current signal from set */
    }

return stat_data;
}
Ejemplo n.º 26
0
t_stat ry_svc (UNIT *uptr)
{
int32 i, t, func, bps;
static uint8 estat[8];
uint32 ba, da;
int8 *fbuf = uptr->filebuf;

func = RYCS_GETFNC (ry_csr);                            /* get function */
bps = (ry_csr & RYCS_DEN)? RY_NUMBY: RX_NUMBY;          /* get sector size */
ba = (RYCS_GETUAE (ry_csr) << 16) | ry_ba;              /* get mem addr */
switch (ry_state) {                                     /* case on state */

    case IDLE:                                          /* idle */
        return SCPE_IERR;

    case FEWC:                                          /* word count */
        ry_wc = ry_dbr & 0377;                          /* save WC */
        ry_csr = ry_csr | RYCS_TR;                      /* set TR */
        ry_state = FEBA;                                /* next state */
        return SCPE_OK;

    case FEBA:                                          /* buffer address */
        ry_ba = ry_dbr;                                 /* save buf addr */
        ry_state = FEXFR;                               /* next state */
        sim_activate (uptr, ry_cwait);                  /* schedule xfer */
        return SCPE_OK;

    case FEXFR:                                         /* transfer */
        if ((ry_wc << 1) > bps) {                       /* wc too big? */
            ry_done (RYES_WCO, 0230);                   /* error */
            break;
            }
        if (func == RYCS_FILL) {                        /* fill? read */
            for (i = 0; i < RY_NUMBY; i++)
                rx2xb[i] = 0;
            t = Map_ReadB (ba, ry_wc << 1, rx2xb);
            }
        else t = Map_WriteB (ba, ry_wc << 1, rx2xb);
        ry_wc = t >> 1;                                 /* adjust wc */
        ry_done (t? RYES_NXM: 0, 0);                    /* done */
        break;

    case RWDS:                                          /* wait for sector */
        ry_sector = ry_dbr & RX_M_SECTOR;               /* save sector */
        ry_csr = ry_csr | RYCS_TR;                      /* set xfer */
        ry_state = RWDT;                                /* advance state */
        return SCPE_OK;

    case RWDT:                                          /* wait for track */
        ry_track = ry_dbr & RX_M_TRACK;                 /* save track */
        ry_state = RWXFR;                               /* next state */
        sim_activate (uptr,                             /* sched xfer */
            ry_swait * abs (ry_track - uptr->TRACK));
        return SCPE_OK;

    case RWXFR:                                         /* read/write */
        if ((uptr->flags & UNIT_BUF) == 0) {            /* not buffered? */
            ry_done (0, 0110);                          /* done, error */
            return IORETURN (ry_stopioe, SCPE_UNATT);
            }
        if (ry_track >= RX_NUMTR) {                     /* bad track? */
            ry_done (0, 0040);                          /* done, error */
            break;
            }
        uptr->TRACK = ry_track;                         /* now on track */
        if ((ry_sector == 0) || (ry_sector > RX_NUMSC)) { /* bad sect? */
            ry_done (0, 0070);                          /* done, error */
            break;
            }
        if (((uptr->flags & UNIT_DEN) != 0) ^
            ((ry_csr & RYCS_DEN) != 0)) {               /* densities agree? */
            ry_done (RYES_DERR, 0240);                  /* no, error */
            break;
            }
        da = CALC_DA (ry_track, ry_sector, bps);        /* get disk address */
        if (func == RYCS_WRDEL)                         /* del data? */
            ry_esr = ry_esr | RYES_DD;
        if (func == RYCS_READ) {                        /* read? */
            for (i = 0; i < bps; i++)
                rx2xb[i] = fbuf[da + i];
             }
        else {
            if (uptr->flags & UNIT_WPRT) {              /* write and locked? */
                ry_done (0, 0100);                      /* done, error */
                break;
                }
            for (i = 0; i < bps; i++)                   /* write */
                fbuf[da + i] = rx2xb[i];
            da = da + bps;
            if (da > uptr->hwmark)
                uptr->hwmark = da;
            }
        ry_done (0, 0);                                 /* done */
        break;

    case SDCNF:                                         /* confirm set density */
        if ((ry_dbr & 0377) != 0111) {                  /* confirmed? */
            ry_done (0, 0250);                          /* no, error */
            break;
            }
        ry_state = SDXFR;                               /* next state */
        sim_activate (uptr, ry_cwait * 100);            /* schedule operation */
        break;

	case SDXFR:                                         /* erase disk */
		for (i = 0; i < (int32) uptr->capac; i++)
            fbuf[i] = 0;
		uptr->hwmark = (uint32) uptr->capac;
		if (ry_csr & RYCS_DEN)
            uptr->flags = uptr->flags | UNIT_DEN;
		else uptr->flags = uptr->flags & ~UNIT_DEN;
		ry_done (0, 0);
		break;


	case ESBA:
		ry_ba = ry_dbr;                                 /* save WC */
		ry_state = ESXFR;                               /* next state */
		sim_activate (uptr, ry_cwait);                  /* schedule xfer */
		return SCPE_OK;

	case ESXFR:
		estat[0] = ry_ecode;                            /* fill 8B status */
		estat[1] = ry_wc;
		estat[2] = ry_unit[0].TRACK;
		estat[3] = ry_unit[1].TRACK;
		estat[4] = ry_track;
		estat[5] = ry_sector;
		estat[6] = ((ry_csr & RYCS_DRV)? 0200: 0) |
			       ((ry_unit[1].flags & UNIT_DEN)? 0100: 0) |
                   ((uptr->flags & UNIT_ATT)? 0040: 0) |
                   ((ry_unit[0].flags & UNIT_DEN)? 0020: 0) |
                   ((ry_csr & RYCS_DEN)? 0001: 0);
		estat[7] = uptr->TRACK;
		t = Map_WriteB (ba, 8, estat);                  /* DMA to memory */
		ry_done (t? RYES_NXM: 0, 0);                    /* done */
		break;

	case CMD_COMPLETE:                                  /* command complete */
		ry_done (0, 0);
		break;

	case INIT_COMPLETE:                                 /* init complete */
		ry_unit[0].TRACK = 1;                           /* drive 0 to trk 1 */
		ry_unit[1].TRACK = 0;                           /* drive 1 to trk 0 */
		if ((uptr->flags & UNIT_BUF) == 0) {            /* not buffered? */
			ry_done (RYES_ID, 0010);                    /* init done, error */
			break;
			}
		da = CALC_DA (1, 1, bps);                       /* track 1, sector 1 */
		for (i = 0; i < bps; i++)                       /* read sector */
			rx2xb[i] = fbuf[da + i];
		ry_done (RYES_ID, 0);                           /* set done */
		if ((ry_unit[1].flags & UNIT_ATT) == 0)
            ry_ecode = 0020;
		break;
		}                                               /* end case state */

return SCPE_OK;
}