t_stat cdp_srv(UNIT * uptr) { int chan = UNIT_G_CHAN(uptr->flags); int u = (uptr - cdp_unit); int pos; t_uint64 wd; int bit; t_uint64 mask; int b; int col; struct _card_data *data; /* Channel has disconnected, abort current card. */ if (uptr->u5 & CDPSTA_CMD && chan_stat(chan, DEV_DISCO)) { if ((uptr->u5 & CDPSTA_POSMASK) != 0) { sim_debug(DEBUG_DETAIL, &cdp_dev, "punch card\n"); sim_punch_card(uptr, NULL); uptr->u5 &= ~CDPSTA_PUNCH; } uptr->u5 &= ~(CDPSTA_WRITE | CDPSTA_CMD | CDPSTA_POSMASK); chan_clear(chan, DEV_WEOR | DEV_SEL); sim_debug(DEBUG_CHAN, &cdp_dev, "unit=%d disconnect\n", u); } /* Check to see if we have timed out */ if (uptr->wait != 0) { uptr->wait--; /* If at end of record and channel is still active, do another read */ if ( ((uptr->u5 & (CDPSTA_CMD | CDPSTA_IDLE | CDPSTA_WRITE | CDPSTA_ON)) == (CDPSTA_CMD | CDPSTA_IDLE | CDPSTA_ON)) && uptr->wait > 30 && chan_test(chan, STA_ACTIVE)) { uptr->u5 |= CDPSTA_WRITE; uptr->u5 &= ~CDPSTA_IDLE; chan_set(chan, DEV_WRITE); chan_clear(chan, DEV_WEOR); sim_debug(DEBUG_CHAN, &cdp_dev, "unit=%d restarting\n", u); } sim_activate(uptr, us_to_ticks(1000)); /* activate */ return SCPE_OK; } /* If no write request, go to idle mode */ if ((uptr->u5 & CDPSTA_WRITE) == 0) { if ((uptr->u5 & (CDPSTA_IDLE | CDPSTA_ON)) == (CDPSTA_IDLE | CDPSTA_ON)) { uptr->wait = 85; /* Delay 85ms */ uptr->u5 &= ~CDPSTA_IDLE; /* Not running */ sim_activate(uptr, us_to_ticks(1000)); } else { uptr->u5 &= ~CDPSTA_ON; /* Turn motor off */ } return SCPE_OK; } /* Motor is up to speed now */ uptr->u5 |= CDPSTA_ON; uptr->u5 &= ~CDPSTA_IDLE; /* Not running */ if (dev_pulse[chan] & PUNCH_M) uptr->u5 |= CDPSTA_PUNCH; pos = (uptr->u5 & CDPSTA_POSMASK) >> CDPSTA_POSSHIFT; if (pos == 24) { if (chan_test(chan, STA_ACTIVE)) { sim_debug(DEBUG_CHAN, &cdp_dev, "unit=%d set EOR\n", u); chan_set(chan, DEV_REOR); } else { chan_clear(chan, DEV_WEOR | DEV_SEL); sim_debug(DEBUG_CHAN, &cdp_dev, "unit=%d disconnect\n", u); } sim_debug(DEBUG_DETAIL, &cdp_dev, "punch card\n"); sim_punch_card(uptr, NULL); uptr->u5 |= CDPSTA_IDLE; uptr->u5 &= ~(CDPSTA_WRITE | CDPSTA_POSMASK | CDPSTA_PUNCH); uptr->wait = 85; sim_activate(uptr, us_to_ticks(1000)); return SCPE_OK; } sim_debug(DEBUG_DATA, &cdp_dev, "unit=%d write column %d ", u, pos); wd = 0; data = (struct _card_data *)uptr->up7; switch (chan_read(chan, &wd, 0)) { case DATA_OK: sim_debug(DEBUG_DATA, &cdp_dev, " %012llo\n", wd); /* Bit flip into temp buffer */ bit = 1 << (pos / 2); mask = 1; b = (pos & 1)?36:0; for (col = 35; col >= 0; mask <<= 1, col--) { if (wd & mask) data->image[col + b] |= bit; } pos++; uptr->wait = 0; uptr->u5 &= ~CDPSTA_POSMASK; uptr->u5 |= (pos << CDPSTA_POSSHIFT) & CDPSTA_POSMASK; sim_activate(uptr, (pos & 1) ? us_to_ticks(300) : us_to_ticks(8000)); return SCPE_OK; case END_RECORD: sim_debug(DEBUG_DATA, &cdp_dev, "eor\n"); uptr->wait = 8 * (12 - (pos / 2)) /*+ 85*/; uptr->u5 &= ~(CDPSTA_POSMASK); uptr->u5 |= (24 << CDPSTA_POSSHIFT) & CDPSTA_POSMASK; break; case TIME_ERROR: sim_debug(DEBUG_DATA, &cdp_dev, "no data\n"); uptr->wait = 8 * (12 - (pos / 2)) /*+ 85*/; uptr->u5 &= ~(CDPSTA_POSMASK); uptr->u5 |= (24 << CDPSTA_POSSHIFT) & CDPSTA_POSMASK; break; } sim_activate(uptr, us_to_ticks(1000)); return SCPE_OK; }
/* Handle transfer of data for card reader */ t_stat cdr_srv(UNIT *uptr) { int chan = UNIT_G_CHAN(uptr->flags); int u = (uptr - cdr_unit); uint16 *image = (uint16 *)(uptr->up7); /* Waiting for disconnect */ if (uptr->u5 & URCSTA_WDISCO) { if (chan_stat(chan, DEV_DISCO)) { chan_clear(chan, DEV_SEL|DEV_WEOR); uptr->u5 &= ~ URCSTA_WDISCO; } else { /* No disco yet, try again in a bit */ sim_activate(uptr, 50); return SCPE_OK; } /* If still busy, schedule another wait */ if (uptr->u5 & URCSTA_BUSY) sim_activate(uptr, uptr->wait); } if (uptr->u5 & URCSTA_BUSY) { uptr->u5 &= ~URCSTA_BUSY; #ifdef I7070 switch(uptr->flags & (ATTENA|ATTENB)) { case ATTENA: chan_set_attn_a(chan); break; case ATTENB: chan_set_attn_b(chan); break; } #endif } /* Check if new card requested. */ if (uptr->u4 == 0 && uptr->u5 & URCSTA_READ && (uptr->u5 & URCSTA_CARD) == 0) { switch(sim_read_card(uptr, image)) { case CDSE_EOF: sim_debug(DEBUG_DETAIL, &cdr_dev, "%d: EOF\n", u); /* Fall through */ case CDSE_EMPTY: chan_set_eof(chan); chan_set_attn(chan); chan_clear(chan, DEV_SEL); uptr->u5 |= URCSTA_EOF; uptr->u5 &= ~(URCSTA_BUSY|URCSTA_READ); return SCPE_OK; case CDSE_ERROR: sim_debug(DEBUG_DETAIL, &cdr_dev, "%d: ERF\n", u); uptr->u5 |= URCSTA_ERR; uptr->u5 &= ~(URCSTA_BUSY|URCSTA_READ); chan_set_attn(chan); chan_clear(chan, DEV_SEL); return SCPE_OK; case CDSE_OK: uptr->u5 |= URCSTA_CARD; #ifdef I7010 chan_set_attn_urec(chan, cdr_dib.addr); #endif break; } #ifdef I7070 /* Check if load card. */ if (uptr->capac && (image[uptr->capac-1] & 0x800)) { uptr->u5 |= URCSTA_LOAD; chan_set_load_mode(chan); } else { uptr->u5 &= ~URCSTA_LOAD; } #endif } if (uptr->u5 & URCSTA_NOXFER) { uptr->u5 &= ~(URCSTA_NOXFER|URCSTA_READ); return SCPE_OK; } /* Copy next column over */ if (uptr->u5 & URCSTA_READ && uptr->u4 < 80) { uint8 ch = 0; #ifdef I7080 /* Detect RSU */ if (image[uptr->u4] == 0x924) { uptr->u5 &= ~URCSTA_READ; uptr->u5 |= URCSTA_WDISCO; chan_set(chan, DEV_REOR); sim_activate(uptr, 10); return SCPE_OK; } #endif ch = sim_hol_to_bcd(image[uptr->u4]); /* Handle invalid punch */ if (ch == 0x7f) { #ifdef I7080 uptr->u5 &= ~(URCSTA_READ|URCSTA_BUSY); sim_debug(DEBUG_DETAIL, &cdr_dev, "%d: bad punch %d\n", u, uptr->u4); chan_set_attn(chan); chan_set_error(chan); chan_clear(chan, DEV_SEL); #else uptr->u5 |= URCSTA_ERR; ch = 017; #endif } #ifdef I7070 /* During load, only sign on every 10 columns */ if (uptr->u5 & URCSTA_LOAD && (uptr->u4 % 10) != 9) ch &= 0xf; #endif switch(chan_write_char(chan, &ch, (uptr->u4 == 79)? DEV_REOR: 0)) { case TIME_ERROR: case END_RECORD: uptr->u5 |= URCSTA_WDISCO|URCSTA_BUSY; uptr->u5 &= ~URCSTA_READ; break; case DATA_OK: uptr->u4++; break; } sim_debug(DEBUG_DATA, &cdr_dev, "%d: Char > %02o\n", u, ch); sim_activate(uptr, 10); } return SCPE_OK; }