Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* rxm.c */
- static char *rcsid = "$Id: rxm.c,v 1.29 2007/07/02 01:39:01 chd Exp $";
- //#define __linux__
- //#define __NetBSD__
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <signal.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <time.h>
- #if defined __linux__
- #include <sys/io.h>
- #include <sched.h>
- #elif defined __NetBSD__
- #include <machine/pio.h>
- #include <machine/sysarch.h>
- #else
- #error No system defined!
- #endif
- #include "rx_version.h"
- /* fundamental definitions */
- /* parallel port definitions */
- /* this is a retrofit of the address from being compile time to runtime */
- #define IO_BASE (io_base)
- #define IO_DATA IO_BASE
- #define IO_STATUS (IO_BASE + 1)
- #define IO_CNTRL (IO_BASE + 2)
- #define FAST_IO /* use 32bit port access instructions instead of 8bit */
- /* LINUX port I/O permissions are enabled as number of ports starting at a base address */
- #ifdef FAST_IO
- #define IO_LEN ((IO_CNTRL - IO_BASE + 4) & 0xFFFFFFFC) /* round up to 32bit */
- #else
- #define IO_LEN (IO_CNTRL - IO_BASE + 1)
- #endif
- /* NetBSD port I/O permissions are handled by a bitmap */
- #define IOMAP_OFFSET (IO_BASE/32)
- #ifndef FAST_IO
- #define IOMAP_BITMASK ((1 << (IO_DATA%32)) | (1 << (IO_STATUS%32)) | (1 << (IO_CNTRL%32)))
- #else
- #define IOMAP_BITMASK (0x0F << (IO_DATA%32))
- #endif
- #ifdef __NetBSD__
- u_long iomap[32];
- #endif
- #define BIT_D0 0001
- #define BIT_D1 0002
- #define BIT_D2 0004
- #define BIT_D3 0010
- #define BIT_D4 0020
- #define BIT_D5 0040
- #define BIT_D6 0100
- #define BIT_D7 0200
- #define BIT_C0 0001
- #define BIT_C5 0040
- #define BIT_S3 0010
- #define BIT_S4 0020
- #define BIT_S5 0040
- #define BIT_S6 0100
- #define BIT_S7 0200
- /* RX hardware interface definitions */
- #define HW_RX_REG_1 DATA /* bits in register 1 */
- #define HW_RX_ERROR BIT_D0
- #define HW_RX_TR BIT_D1
- #define HW_RX_DONE BIT_D2
- #define HW_RX_SHIFT BIT_D3
- #define HW_RX_OUT BIT_D4
- #define HW_RX_AC_LO BIT_D5
- #define HW_RX_LED1 BIT_D5
- #define HW_RX_LED2 BIT_D6
- #define HW_RX_INITFF BIT_D7
- #define HW_RX_REG_1_INV (BIT_D7)
- #define DATA_INV HW_RX_REG_1_INV
- #define HW_RX_REG_2 CNTRL /* bits in register 2 */
- #define HW_RX_DATA_O BIT_C0
- #define HW_RX_REG_2_INV (BIT_C0)
- #define CNTRL_INV HW_RX_REG_2_INV
- #define HW_RX_REG_3 STATUS /* bits in register 3 */
- #define HW_RX_RUN BIT_S7
- #define HW_RX_DMA BIT_S6
- #define HW_RX_INIT BIT_S5
- #define HW_RX_DATA_I BIT_S4
- #define HW_RX_12BIT BIT_S3
- #define HW_RX_REG_3_INV (BIT_S3 | BIT_S4 | BIT_S6)
- #define STATUS_INV HW_RX_REG_3_INV
- /* RX interface definitions */
- #define RX_ERROR (HW_RX_ERROR)
- #define RX_TR (HW_RX_TR)
- #define RX_DONE (HW_RX_DONE)
- #define RX_SHIFT (HW_RX_SHIFT)
- #define RX_OUT (HW_RX_OUT)
- #define RX_AC_LO (HW_RX_AC_LO)
- #define RX_INITFF (HW_RX_INITFF)
- #define RX_LED1 (HW_RX_LED1)
- #define RX_LED2 (HW_RX_LED2)
- #define RX_DATA_O (HW_RX_DATA_O << 8)
- #define RX_DATA_I (HW_RX_DATA_I << 16)
- #define RX_RUN (HW_RX_RUN << 16)
- #define RX_INIT (HW_RX_INIT << 16)
- #define RX_12BIT (HW_RX_12BIT << 16)
- #define RX_DMA (HW_RX_DMA << 16)
- // #define rx_wait() while(!(rx_if_get(RX_RUN | RX_INIT))) sleep(0);
- #define RX_WAIT 1
- #define RX_NOWAIT 0
- /* function codes */
- #define RX_FUNC 0000016 /* mask for function code */
- #define RX_FILL 0000000 /* fill buffer */
- #define RX_EMPTY 0000002 /* empty */
- #define RX_WSECT 0000004 /* write sector */
- #define RX_RSECT 0000006 /* read sector */
- #define RX_SMD 0000010 /* set media density */
- #define RX_RDSTAT 0000012 /* read status */
- #define RX_WDDSECT 0000014 /* write deleted data sector */
- #define RX_RDEC 0000016 /* read error code */
- #define RX_UNIT 0000020 /* unit select */
- #define RX_DEN 0000400 /* function density */
- #define RX_GO 0000001 /* GO bit */
- #define RX_IE 0000100 /* IE bit */
- #define RX_EXADDR 0030000 /* upper 2 bits of 18bit address */
- #define RX_CS_INIT 0040000 /* initialize RX02 */
- /* status codes */
- #define RX_CRC 0000001 /* CRC error */
- #define RX_DS 0000002 /* double sided - RX03 */
- #define RX_ID 0000004 /* controller initialization done */
- #define RX_RX02_ID 0000010 /* set if an RX02 drive */
- #define RX_DEN_ERR 0000020 /* density error */
- #define RX_DENSITY_B 0000040 /* diskette is double density */
- #define RX_DD 0000100 /* deleted data detected */
- #define RX_DRDY_B 0000200 /* drive ready */
- #define RX_USEL_B 0000400 /* unit selected */
- #define RX_WC_OVFL 0001000 /* word count overflow */
- /* emulation types */
- #define RX_RX01 1 /* RX02 in RX01 emulation mode */
- #define RX_RX02 2 /* RX02 in RX02 mode */
- #define rx_mode(x) (rx2.type == (x))
- #define RX_XFER_PIO 0 /* RX02 with a PIO interface or an RX01 */
- #define RX_XFER_DMA 1 /* RX02 with a DMA interface */
- #define rx_xfer_mode(x) (rx2.xfer_mode == (x))
- /* disk definitions */
- #define RX0_IMAGE "rx0.dsk"
- #define RX1_IMAGE "rx1.dsk"
- #define NTRKS 77 /* number of tracks / disk */
- #define NSECTS 26 /* number of sectors / track */
- #define NBPS 128 /* bytes per sector - SD */
- #define DENSITY_SD 1
- #define DENSITY_DD 2
- #define NUNITS 2 /* Unit Number: 0 = left, 1 = right */
- #define NORMAL_DATA 0
- #define DELETED_DATA 1
- #define sec_size(d) (NBPS*(d))
- #define dsk_size(d) (NTRKS*NSECTS*sec_size(d))
- /* timing */
- #define RX02_ACTUAL_SPEED 0
- /* a test configuration */
- #if (RX02_ACTUAL_SPEED == 3)
- #define MS 1000 /* sleep millisecond */
- #define RX_RDSTAT_TIME (25*MS) /* read status function time */
- #define RX_INIT_TIME (50*MS) /* initialize floppy drive system time */
- #define RX_STEP_TIME 0 /* track step time */
- #define RX_SETTLE_TIME 0 /* seek settling time */
- #define RX_SEC_TIME 0
- #endif
- /* a faster, but still simulating delays */
- #if (RX02_ACTUAL_SPEED == 2)
- #define MS 1000 /* sleep millisecond */
- #define RX_RDSTAT_TIME (200*MS) /* read status function time */
- #define RX_INIT_TIME (400*MS) /* initialize floppy drive system time */
- #define RX_STEP_TIME (8*MS) /* track step time */
- #define RX_SETTLE_TIME (15*MS) /* seek settling time */
- #define RX_SEC_TIME (3*60*1000*MS/360/NSECTS)
- #endif
- /* actual speed of real hardware */
- #if (RX02_ACTUAL_SPEED == 1)
- #define MS 1000 /* sleep millisecond */
- #define RX_RDSTAT_TIME (250*MS) /* read status function time */
- #define RX_INIT_TIME (500*MS) /* initialize floppy drive system time */
- #define RX_STEP_TIME (10*MS) /* track step time */
- #define RX_SETTLE_TIME (20*MS) /* seek settling time */
- #define RX_SEC_TIME (3*60*1000*MS/360/NSECTS)
- #endif
- /* as fast as it can go */
- #if (RX02_ACTUAL_SPEED == 0) /* this is too fast for the diagnostics */
- #define MS 1000 /* sleep millisecond */
- #define RX_RDSTAT_TIME (25*MS) /* read status function time */
- #define RX_INIT_TIME (50*MS) /* initialize floppy drive system time */
- #define RX_STEP_TIME 0 /* track step time */
- #define RX_SETTLE_TIME 0 /* seek settling time */
- #define RX_SEC_TIME 0
- #endif
- #ifndef MS
- #error RX02_ACTUAL_SPEED must be set properly.
- #endif
- #define seek_time(d) (RX_SEC_TIME + ((abs(d) == 0) ? 0 : abs(d)*RX_STEP_TIME + RX_SETTLE_TIME))
- struct drv_t {
- int ta;
- char fn[50];
- int fd;
- int density;
- unsigned char image[dsk_size(DENSITY_DD)];
- };
- struct rx2_t {
- int type; /* emulation type */
- int xfer_mode; /* transfer mode: RX_PIO or RX_DMA */
- int cs; /* image of CSR */
- int db; /* image of DB */
- int ta; /* track address */
- int sa; /* sector address */
- int wc; /* word count */
- int ba; /* buffer address */
- int es; /* extended status */
- int err_code; /* error code */
- struct drv_t *unit; /* active drive */
- struct drv_t drv[NUNITS]; /* drive specific parameters */
- } rx2;
- unsigned char buffer[sec_size(DENSITY_DD)];
- unsigned char dd_sec_map[NUNITS][NTRKS][NSECTS]; /* 0 == normal data, 1 == deleted data */
- int func_count[8]; /* count the number of times a function has been executed */
- int verbose;
- int expand_image;
- int intr_signal;
- int interruptable;
- int rx_if_image;
- int io_base; /* parallel port base address */
- void prompt(void);
- void spinner(int);
- #define NO_DOT '\000' /* flag indicating to turn the spinner, but not advance it */
- #define DOT '.' /* advance spinner: leaving a dot behind, usual means a pause */
- #define BANG '!' /* leaving a bang behind, means a pause but not interruptable */
- #define LATE 'L' /* leaving an L behind, means the run bit was set immediately and we are late */
- #define RX_DRDY(u) ((rx2.drv[(u)].fd > 0) ? RX_DRDY_B : 0)
- #define RX_USEL(u) ((unit == 0) ? 0 : RX_USEL_B)
- #define RX_DENSITY(u) (((rx2.drv[(u)].density) == DENSITY_SD) ? 0 : RX_DENSITY_B)
- #define RX_NBITS() (rx_if_get(RX_12BIT) ? 12 : 8)
- #define RX_DELDAT(u) (dd_sec_map[(u)][rx2.ta][rx2.sa - 1] == DELETED_DATA)
- #define rx_nbits(x) (RX_NBITS() == (x))
- #define verbosity(x) ((x) <= verbose)
- /* read the processor clock cycle counter */
- extern __inline__ unsigned long long int rdtsc()
- {
- unsigned long long int x;
- __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
- return x;
- }
- // RX interface bit I/O
- // return the bits from the RX interface bit vector
- // only those bits in mask are accurate, the rest are zeroed
- int rx_if_getx(int mask)
- {
- int val = 0;
- #ifdef FAST_IO
- int port_val;
- port_val = inl(IO_DATA) ^ (DATA_INV | (STATUS_INV << 8) | (CNTRL_INV << 16));
- val = (port_val & 0x0000ff) | ((port_val & 0x00ff00) << 8) | ((port_val & 0xff0000) >> 8);
- #else
- if (mask & 0x0000ff) {
- val |= inb(IO_DATA) ^ DATA_INV;
- }
- if (mask & 0x00ff00) {
- val |= (inb(IO_CNTRL) ^ CNTRL_INV) << 8;
- }
- if (mask & 0xff0000) {
- val |= (inb(IO_STATUS) ^ STATUS_INV) << 16;
- }
- #endif
- return val & mask;
- }
- int rx_if_get(int mask)
- {
- #if 1
- return rx_if_getx(mask);
- #else
- int val1, val2, loops;
- loops = 0;
- do {
- val1 = rx_if_getx(mask);
- val2 = rx_if_getx(mask);
- loops += 1;
- if ((loops % 10) == 9)
- printf("rx_if_get: took 9 tries\n");
- }
- while (val1 != val2);
- if (loops > 2)
- printf("rx_if_get: took %d tries\n", loops);
- return val1;
- #endif
- }
- // change the state of mask bits to val
- void rx_if_put(int mask, int val)
- {
- static int dat;
- #if defined __linux__
- #ifdef FAST_IO
- int port_dat;
- dat &= ~mask;
- dat |= (mask & val);
- port_dat = (dat & 0x0000ff) | ((dat & 0x00ff00) << 8);
- port_dat ^= DATA_INV | (CNTRL_INV << 16);
- outl(port_dat, IO_DATA);
- #else
- dat &= ~mask;
- dat |= (mask & val);
- if (mask & 0x000000ff)
- outb(dat ^ DATA_INV, IO_DATA);
- if (mask & 0x0000ff00)
- outb((dat >> 8) ^ CNTRL_INV, IO_CNTRL);
- #endif
- #elif defined __NetBSD__
- #ifdef FAST_IO
- int port_dat;
- dat &= ~mask;
- dat |= (mask & val);
- port_dat = (dat & 0x0000ff) | ((dat & 0x00ff00) << 8);
- port_dat ^= DATA_INV | (CNTRL_INV << 16);
- outl(IO_DATA, port_dat);
- #else
- dat &= ~mask;
- dat |= (mask & val);
- if (mask & 0x000000ff)
- outb(IO_DATA, dat ^ DATA_INV);
- if (mask & 0x0000ff00)
- outb(IO_CNTRL, (dat >> 8) ^ CNTRL_INV);
- #endif
- #endif
- rx_if_image = dat;
- }
- void rx_if_set(int mask)
- {
- rx_if_put(mask, 0x00FFFFFF);
- }
- void rx_if_clr(int mask)
- {
- rx_if_put(mask, 0x00000000);
- }
- /* ---------------------------------------------------------- */
- /* delay for x microseconds */
- void rxdelay(ulong x) {
- struct timespec interval;
- #if 0
- usleep(x);
- #else
- interval.tv_sec = x / 1000000L;
- interval.tv_nsec = 1000*(x % 1000000L);
- nanosleep(&interval, NULL);
- #endif
- }
- #define NICE_VALUE 10
- /* wait until the RX_RUN signal is asserted */
- /* This function waits until the RX_RUN signal is asserted indicating */
- /* that a new value has been loaded into the CS or DB registers. */
- /* It also returns when RX_INIT is asserted. */
- /* RX_TR is cleared. */
- #define WAIT_LOOPS 1000
- void rx_wait(void)
- {
- int sleeping, loops;
- loops = 0;
- sleeping = 0;
- while (!(rx_if_get(RX_RUN | RX_INIT))) {
- if (loops > WAIT_LOOPS) {
- if (!sleeping) {
- sleeping = 1;
- if (verbosity(3))
- printf("rx_wait: yielding processor\n");
- else {
- if (interruptable)
- spinner(DOT);
- else
- spinner(BANG);
- }
- }
- if ((interruptable && intr_signal > 0) || intr_signal > 4)
- prompt();
- #ifdef __linux__
- nice(NICE_VALUE); /* lower priority */
- sched_yield();
- #else
- sleep(0);
- #endif
- } else
- loops += 1;
- }
- nice(0); /* restore to base priority */
- rx_if_clr(RX_TR);
- }
- /* receive a word of n bits*/
- /* transfer is msb first */
- int rx_recv(int n) {
- int i, x;
- x = 0;
- rx_if_clr(RX_DATA_O | RX_OUT | RX_SHIFT | RX_ERROR | RX_DONE);
- for (i = 0; i < n; i++) {
- x <<= 1; /* make room */
- x |= (rx_if_get(RX_DATA_I)) ? 1 : 0; /* insert new bit */
- rx_if_set(RX_SHIFT); /* pulse for shift */
- rx_if_clr(RX_SHIFT);
- }
- /* The extra pulse on RX_SHIFT is included in the RX02 TM flowchart, */
- /* but it seems to get the RX211 state machine out of sync. */
- /* It is commented out here for that reason. */
- #if 0
- rx_if_set(RX_SHIFT); /* pulse for shift */
- rx_if_clr(RX_SHIFT); /* to get parity, I think */
- #endif
- return x;
- }
- /* receive a word of n bits with handshakes */
- /* RX_TR is asserted indicating that a transfer is requested. */
- /* We now wait until RX_RUN is asserted by the PDP interface, indicating */
- /* that a value has been loaded into a register. */
- /* RX_TR is deasserted. */
- /* The value loaded by the PDP is then tranfered bit by bit. */
- int rx_get(int n) {
- rx_if_set(RX_TR);
- if (verbosity(3))
- printf("setting TR\n");
- rx_wait();
- rx_if_clr(RX_TR);
- return(rx_recv(n));
- }
- /* transmit a word of n bits */
- /* transfer is msb first */
- /* Data is clocked into the RX interface on the rising edge of RX_SHIFT. */
- /* RX_SHIFT is cleared and the data bit is set on the same output cycle */
- /* so that only 2 i/o port writes are necessary. */
- /* (Unfortunately the data bit and shift bit are in different output ports, */
- /* so there is no advantage.) */
- void rx_xmit(int val, int n) {
- int i, mask;
- #if 0
- int bit;
- #endif
- rx_if_clr(RX_SHIFT);
- rx_if_set(RX_OUT);
- mask = 1 << (n - 1);
- #if 0
- for (i = 0; i < n; i++) {
- if (val & mask)
- bit = RX_DATA_O;
- else
- bit = 0;
- rx_if_put(RX_DATA_O | RX_SHIFT, bit); /* set the output state */
- rx_if_set(RX_SHIFT); /* clock in the bit */
- mask >>= 1;
- }
- #else
- for (i = 0; i < n; i++) {
- if (val & mask)
- rx_if_set(RX_DATA_O);
- else
- rx_if_clr(RX_DATA_O);
- rx_if_clr(RX_SHIFT);
- rx_if_set(RX_SHIFT); /* pulse for shift */
- mask >>= 1;
- }
- #endif
- rx_if_clr(RX_SHIFT);
- rx_if_set(RX_DATA_O);
- }
- /* transmit a word of n bits with handshakes */
- /* if wait, then wait for RX_RUN from interface */
- void rx_put(int val, int n, int wait) {
- rx_if_set(RX_OUT);
- rx_if_clr(RX_DONE | RX_TR);
- rx_xmit(val, n);
- rx_if_set(RX_TR);
- if (verbosity(3))
- printf("setting TR\n");
- if (wait) {
- rx_wait();
- rx_if_clr(RX_TR);
- }
- }
- /* transmit an extended status word of 12 bits */
- void rx_put_es(int val) {
- if (verbose)
- printf("rx_put_es: ex stat = %05o, ", val);
- if (rx_xfer_mode(RX_XFER_DMA)) {
- if (verbose)
- printf("DMA mode\n");
- rx_if_clr(RX_TR);
- rx_if_set(RX_OUT);
- rx_if_set(RX_DONE);
- rx_xmit(val, 12);
- rx_if_set(RX_TR);
- }
- else {
- if (verbose)
- printf("PIO mode\n");
- rx_if_clr(RX_TR);
- rx_if_set(RX_OUT);
- if (!rx_mode(RX_RX01) && !rx_nbits(12)) /* RX8E */
- rx_if_set(RX_DONE);
- rx_xmit(val, 12);
- if (!rx_mode(RX_RX01) && !rx_nbits(12)) {/* RX8E */
- rx_if_set(RX_TR);
- if (verbosity(3))
- printf("setting TR\n");
- }
- }
- }
- /* display an activity indicator on the controlling terminal */
- /* if dot is true then a dot is deposited and the cursor moves on */
- void spinner(int dot) {
- char phases[] = "|/-\\";
- static int cur_phase;
- if (dot)
- printf("\010%c.", dot); /* BS a char and a dot */
- #if 0
- if (dot == DOT)
- printf("\010.."); /* BS and two dots */
- if (dot == BANG)
- printf("\010!."); /* BS a bang and a dot */
- #endif
- if (cur_phase < 0 || cur_phase > 3)
- cur_phase = 0;
- printf("\010%c", phases[cur_phase++]); /* BS and the next turn */
- fflush(NULL);
- }
- /* show the current state of the interface signals */
- void show_rx_if(void) {
- if (rx_if_image & (RX_ERROR | RX_TR | RX_DONE | RX_SHIFT | RX_OUT | RX_AC_LO | RX_INITFF))
- printf("rx_if_signals asserted: ");
- else {
- printf("rx_if_signals asserted: none\n");
- return;
- }
- if (rx_if_image & RX_ERROR)
- printf("RX_ERROR ");
- if (rx_if_image & RX_TR)
- printf("RX_TR ");
- if (rx_if_image & RX_DONE)
- printf("RX_DONE ");
- if (rx_if_image & RX_SHIFT)
- printf("RX_SHIFT ");
- if (rx_if_image & RX_OUT)
- printf("RX_OUT ");
- // if (rx_if_image & RX_AC_LO)
- // printf("RX_AC_LO ");
- if (rx_if_image & RX_LED1)
- printf("RX_LED1 ");
- if (rx_if_image & RX_INITFF)
- printf("RX_INITFF ");
- printf("\n");
- }
- /* do a function request */
- void do_func(void) {
- int i, j, val, offset;
- int unit;
- int distance;
- rx_if_clr(RX_TR);
- rx_if_clr(RX_OUT);
- rx_if_set(RX_DATA_O);
- rx_if_set(RX_DONE);
- interruptable = 1;
- rx_if_set(RX_LED1);
- rx_wait();
- interruptable = 0;
- rx_if_clr(RX_LED1);
- if (rx_if_get(RX_INIT)) {
- if (verbose)
- printf("RX_INIT request.\n");
- return;
- }
- if (rx_xfer_mode(RX_XFER_DMA) || (rx_mode(RX_RX01) && rx_nbits(12)) || (rx_mode(RX_RX02) && rx_nbits(12))) {
- rx2.cs = rx_recv(12);
- if (verbosity(3))
- printf("receiving 12 bit command\n");
- }
- else { /* two 8-bit transfers with an RX11 or an RX28 in 8bit mode */
- rx2.cs = rx_recv(8);
- // rx2.cs |= rx_get(8) << 8;
- if (verbosity(3))
- printf("receiving 8 bit command\n");
- }
- if (verbose)
- printf("RX_RUN request: function = %06o\n", rx2.cs);
- // else
- // spinner(NO_DOT);
- unit = (rx2.cs & RX_UNIT) ? 1 : 0;
- rx2.unit = &rx2.drv[unit];
- // if (!(rx2.cs & RX_GO)) {
- // printf("ERROR: Received command without a GO bit.\nMajor protocol violation.\n");
- // goto error;
- // }
- func_count[(rx2.cs & RX_FUNC) >> 1] += 1;
- switch(rx2.cs & RX_FUNC) {
- /* fill buffer - 000 */
- /* empty buffer - 001 */
- /* RX02 DMA */
- /* func */
- /* word count (8) */
- /* xfer of N bytes (8) */
- /* RX02 PIO */
- /* func */
- /* xfer of N bytes (8) or (12) */
- /* RX01 */
- /* func */
- /* xfer of N bytes (8) or (12) */
- case RX_FILL:
- case RX_EMPTY:
- if (verbose)
- printf("%s buffer request\n", ((rx2.cs & RX_FUNC) == RX_FILL) ? "fill" : "empty");
- if (rx_xfer_mode(RX_XFER_DMA))
- rx2.wc = rx_get(8);
- else {
- rx2.wc = rx_nbits(8) ? 128/2 : 64/2;
- if (RX_DENSITY(unit))
- rx2.wc *= 2;
- }
- if (verbose || rx2.wc == 0)
- if (rx_nbits(8))
- printf("word count = %06o (%d bytes)\n", rx2.wc, rx2.wc*2);
- if (2*rx2.wc > sec_size(rx2.unit->density)) {
- if (verbose)
- printf("word count overflow\n");
- rx2.err_code = 0230;
- rx2.es = RX_WC_OVFL | RX_USEL(unit) | RX_DENSITY(unit);
- goto error;
- }
- if ((rx2.cs & RX_FUNC) == RX_EMPTY) {
- for (i = 0; i < 2*rx2.wc; i++) {
- if (rx_nbits(8))
- val = buffer[i];
- else { /* 12 bit values are packed into the first 2/3 of the sector */
- j = 3*i/2;
- val = (i & 1) ? ((buffer[j] & 017) << 8) | buffer[j + 1] : (buffer[j] << 4) | ((buffer[j + 1] >> 4) & 017);
- }
- rx_put(val, RX_NBITS(), RX_WAIT);
- }
- }
- else {
- for (i = 0; i < 2*rx2.wc; i++) {
- if (rx_nbits(8))
- buffer[i] = rx_get(8);
- else {
- val = rx_get(12);
- j = 3*i/2;
- if (i & 1) {
- buffer[j] |= (val >> 8) & 017;
- buffer[j + 1] = val;
- } else {
- buffer[j] = val >> 4;
- buffer[j + 1] = (val & 017) << 4;
- }
- }
- }
- if (2*rx2.wc*RX_NBITS()/8 < sec_size(rx2.unit->density))
- memset(&buffer[2*rx2.wc*RX_NBITS()/8], 0x00, sec_size(rx2.unit->density) - 2*rx2.wc*RX_NBITS()/8);
- }
- if (verbose) {
- if (rx_nbits(8))
- printf("transferred %d bytes\n", rx2.wc*2);
- else
- printf("transferred %d words\n", rx2.wc*2);
- }
- rx2.wc = 0;
- rx2.es = RX_USEL(unit) | RX_DENSITY(unit);
- break;
- /* write sector - 010 */
- /* read sector - 011 */
- /* write deleted data sector - 110 */
- /* func */
- /* sector (8) or (12) */
- /* track (8) or (12) */
- case RX_RSECT:
- case RX_WSECT:
- case RX_WDDSECT:
- if (verbose)
- printf("transfer sector request: ");
- if (verbose && ((rx2.cs & RX_FUNC) == RX_WSECT))
- printf("write\n");
- if (verbose && ((rx2.cs & RX_FUNC) == RX_RSECT))
- printf("read\n");
- if (verbose && ((rx2.cs & RX_FUNC) == RX_WDDSECT))
- printf("write deleted data\n");
- if (verbosity(3))
- printf("getting sector address\n");
- rx2.sa = rx_get(RX_NBITS()) & 037;
- if (verbosity(3))
- printf("xfr: sector = %d\n", rx2.sa);
- if (verbosity(3))
- printf("getting track address\n");
- rx2.ta = rx_get(RX_NBITS()) & 0177;
- if (verbosity(3))
- printf("xfr: track = %d\n", rx2.ta);
- rx_if_clr(RX_SHIFT | RX_DATA_O | RX_DONE | RX_OUT | RX_TR | RX_ERROR);
- // if (verbose)
- // printf("transfer sector request: ");
- // if (verbose && ((rx2.cs & RX_FUNC) == RX_WSECT))
- // printf("write\n");
- // if (verbose && ((rx2.cs & RX_FUNC) == RX_RSECT))
- // printf("read\n");
- // if (verbose && ((rx2.cs & RX_FUNC) == RX_WDDSECT))
- // printf("write deleted data\n");
- distance = rx2.ta - rx2.unit->ta;
- rx2.unit->ta = rx2.ta;
- /* check that drive is ready */
- if (!RX_DRDY(unit)) {
- rx2.es = RX_USEL(unit) | RX_DENSITY(unit);
- printf("drive %d not ready\n", unit);
- goto error;
- }
- /* check that density matches */
- if (!rx_mode(RX_RX01) && /* RX01 ignores density bit and OS/8 does too */
- ((RX_DENSITY(unit) && !(rx2.cs & RX_DEN))
- || (!RX_DENSITY(unit) && (rx2.cs & RX_DEN)))) {
- rx2.es = RX_USEL(unit) | RX_DENSITY(unit) | RX_DEN_ERR;
- rx2.err_code = 0240; /* Density Error */
- if (verbose)
- printf("sector density error on unit %d\n", unit);
- goto error;
- }
- if (rx2.ta < 0 || rx2.ta >= NTRKS || rx2.sa < 1 || rx2.sa > NSECTS) {
- if (rx2.ta < 0 || rx2.ta >= NTRKS)
- printf("track value out of range: track = %06o, sector = %06o\n", rx2.ta, rx2.sa);
- if (rx2.sa < 1 || rx2.sa > NSECTS)
- printf("sector value out of range: track = %06o, sector = %06o\n", rx2.ta, rx2.sa);
- }
- else {
- offset = (rx2.ta*NSECTS + (rx2.sa - 1))*sec_size(rx2.unit->density);
- if ((rx2.cs & RX_FUNC) == RX_RSECT) { /* read */
- if (verbose) printf("read: unit = %d, track = %d, sector = %d\n", unit, rx2.ta, rx2.sa);
- memcpy(buffer, &rx2.unit->image[offset], sec_size(rx2.unit->density));
- }
- else { /* write */
- if (verbose) printf("write: unit = %d, track = %d, sector = %d\n", unit, rx2.ta, rx2.sa);
- if ((rx2.cs & RX_FUNC) == RX_WDDSECT)
- dd_sec_map[unit][rx2.ta][rx2.sa - 1] = DELETED_DATA;
- else
- dd_sec_map[unit][rx2.ta][rx2.sa - 1] = NORMAL_DATA;
- memcpy(&rx2.unit->image[offset], buffer, sec_size(rx2.unit->density));
- lseek(rx2.unit->fd, offset, SEEK_SET);
- write(rx2.unit->fd, buffer, sec_size(rx2.unit->density));
- }
- }
- // printf("seek distance is %d, waiting for %d uS\n", abs(distance), seek_time(distance));
- rxdelay(seek_time(distance));
- rx2.es = RX_USEL(unit) | RX_DRDY(unit) | RX_DENSITY(unit) | RX_DELDAT(unit);
- break;
- /* set media density - 100 */
- /* func */
- /* "I" */
- case RX_SMD:
- if (rx_mode(RX_RX01)) { /* function 100 is a NOP for the RX01 */
- if (verbose)
- printf("NOP request\n");
- break;
- }
- if (verbose)
- printf("set media density\n waiting for password...\n");
- val = rx_get(RX_NBITS());
- if (val != 'I') {
- rx2.err_code = 0250;
- rx2.es = RX_USEL(unit) | RX_DENSITY(unit);
- if (verbose)
- printf(" password error: received %04o, expected 0111\n", val);
- goto error;
- }
- else {
- rx2.drv[unit].density = (rx2.cs & RX_DEN) ? DENSITY_DD : DENSITY_SD;
- if (verbose)
- printf(" correct password received.\n");
- }
- rx2.es = RX_USEL(unit) | RX_DENSITY(unit);
- break;
- /* maintenance read status - 101 */ /***************/
- /* func */
- case RX_RDSTAT:
- rxdelay(RX_RDSTAT_TIME); /* delay */
- if (verbosity(3))
- printf("Density = %o, com_stat = %o\n", rx2.unit->density, rx2.cs);
- if (RX_DRDY(unit) && (((rx2.unit->density == DENSITY_DD) && !(rx2.cs & RX_DEN)) /* check that density matches */
- || ((rx2.unit->density == DENSITY_SD) && (rx2.cs & RX_DEN)))) {
- rx2.es = RX_USEL(unit) | RX_DRDY(unit) | RX_DENSITY(unit) | RX_DEN_ERR | (rx_mode(RX_RX02) ? RX_RX02_ID : 0);
- rx2.err_code = 0240; /* Density Error */
- if (verbosity(3))
- printf("density error\n");
- goto error;
- }
- rx2.es = RX_USEL(unit) | RX_DRDY(unit) | RX_DENSITY(unit) | (rx_mode(RX_RX02) ? RX_RX02_ID : 0);
- if (verbosity(3))
- printf("read status: status = %04o\n", rx2.es);
- break;
- /* read error code - 111 */ /***************/
- /* func */
- case RX_RDEC:
- if (verbose)
- printf("read error code\n");
- if (rx_xfer_mode(RX_XFER_DMA)) {
- rx_put(rx2.err_code, RX_NBITS(), RX_WAIT);
- rx_put(rx2.wc, 8, RX_WAIT);
- printf("error_code = %03o, wordcnt = %03o -> word 1 = %06o\n", rx2.err_code, rx2.wc, (rx2.wc << 8) | rx2.err_code);
- rx_put(rx2.drv[0].ta, 8, RX_WAIT);
- rx_put(rx2.drv[1].ta, 8, RX_WAIT);
- printf("rx[0].track = %04o (%d.), rx[1].track = %04o (%d.) -> word 2 = %06o,\n",
- rx2.drv[0].ta, rx2.drv[0].ta, rx2.drv[1].ta, rx2.drv[1].ta, (rx2.drv[1].ta << 8) | rx2.drv[0].ta);
- rx_put(rx2.ta, 8, RX_WAIT);
- rx_put(rx2.sa, 8, RX_WAIT);
- printf("track = %04o (%d.), sector = %03o (%d.) -> word 3 = %06o\n",
- rx2.ta, rx2.ta, rx2.sa, rx2.sa, (rx2.sa << 8) + rx2.ta);
- rx_put(((unit) ? 0200 : 0) | (RX_DRDY(unit) ? 040 : 0)
- | ((rx2.drv[1].density == DENSITY_SD) ? 0 : 0100)
- | ((rx2.drv[0].density == DENSITY_SD) ? 0 : 020)
- | ((rx2.cs & RX_DEN) ? 1 : 0), 8, RX_WAIT); /* *** */
- rx_put(rx2.unit->ta, 8, RX_NOWAIT);
- printf("misc stat = %03o, rx[unit].track = %04o (%d.) -> word 4 = %06o\n",
- ((unit) ? 0200 : 0) | (RX_DRDY(unit) ? 040 : 0)
- | ((rx2.drv[1].density == DENSITY_SD) ? 0 : 0100)
- | ((rx2.drv[0].density == DENSITY_SD) ? 0 : 020)
- | ((rx2.cs & RX_DEN) ? 1 : 0),
- rx2.unit->ta, rx2.unit->ta,
- (rx2.unit->ta << 8) | ((unit) ? 0200 : 0) | (RX_DRDY(unit) ? 040 : 0)
- | ((rx2.drv[1].density == DENSITY_SD) ? 0 : 0100)
- | ((rx2.drv[0].density == DENSITY_SD) ? 0 : 020)
- | ((rx2.cs & RX_DEN) ? 1 : 0));
- rx2.es = RX_USEL(unit) | RX_DRDY(unit) | RX_DENSITY(unit);
- } // else
- // rx_put(rx2.err_code, RX_NBITS(), RX_NOWAIT);
- break;
- }
- done:
- rx_put_es(rx2.es);
- return;
- error:
- rx_if_set(RX_ERROR);
- goto done;
- }
- void rx_init() {
- int offset;
- rx_if_clr(RX_DONE);
- printf("Initializing...\n");
- rxdelay(RX_INIT_TIME);
- rx_if_set(RX_INITFF);
- rx_if_clr(RX_INITFF);
- if (rx_if_get(RX_INIT))
- printf(" held by RX_INIT. Waiting... \n");
- while (rx_if_get(RX_INIT)) {
- sleep(1);
- if (intr_signal > 0)
- prompt();
- rx_if_set(RX_INITFF);
- rx_if_clr(RX_INITFF);
- }
- rx2.cs = 0;
- rx2.db = 0;
- rx2.ta = 1;
- rx2.sa = 1;
- rx2.wc = 0;
- rx2.ba = 0;
- rx2.es = 0;
- rx2.err_code = 0;
- rx2.unit = &rx2.drv[0];
- rx2.drv[0].ta = rx2.ta;
- rx2.drv[1].ta = 0;
- /* copy boot sector into the buffer */
- offset = (rx2.ta*NSECTS + (rx2.sa - 1))*sec_size(rx2.drv[0].density);
- memcpy(buffer, &rx2.drv[0].image[offset], sec_size(rx2.drv[0].density));
- rx_if_clr(RX_ERROR);
- rx2.err_code = 0;
- rx2.es = RX_DRDY(0) | RX_DENSITY(0) | RX_DELDAT(0) | RX_ID | (rx_mode(RX_RX02) ? RX_RX02_ID : 0);
- rx_put_es(rx2.es);
- }
- void attach_file(int drv) {
- struct drv_t *unit;
- struct stat stat_buf;
- unit = &rx2.drv[drv];
- /* if the unit is attached to file then close it */
- if (unit->fd >= 0) {
- if(close(unit->fd))
- perror("rxm: attach_file: close");
- else {
- unit->fd = -1; /* make it a non-fd */
- if (verbose)
- printf("file successfully closed\n");
- }
- }
- /* attempt to open the new image file */
- /* a null file name or a file name of a single . is considered a message to detach and not reopen */
- /* if no file is found, create one of the appropriate size */
- if (unit->fn[0] != '.' || unit->fn[0] != '\0' || unit->fn[1] != '\0') {
- unit->fd = open(unit->fn, O_RDWR);
- if (unit->fd < 0) {
- if (errno == ENOENT) {
- unit->fd = open(unit->fn, O_RDWR | O_CREAT, 0664);
- if (unit->fd < 0) {
- printf("rxm: attach_file: could not create disk %d image file\n", drv);
- unit->fd = -1;
- } else {
- memset(unit->image, 0, dsk_size(unit->density));
- write(unit->fd, unit->image, dsk_size(unit->density));
- }
- } else {
- printf("rxm: attach_file: could not open disk %d image file\n", drv);
- unit->fd = -1;
- }
- } else {
- if (verbose)
- printf("rxm: attach_file: file %s attached OK as drive %d\n", unit->fn, drv);
- }
- } else {
- unit->fd = -1;
- if (verbose)
- printf("rxm: attach_file: file not attached to disk %d because the name was . or NULL\n", drv);
- }
- /* if a file was opened, check that it is the right size */
- /* if it is the right size then all is well */
- /* if it is not the right size and it is small and we have set the option to expand */
- /* then expand the image to the correct size for this density */
- if (unit->fd >= 0) {
- if (fstat(unit->fd, &stat_buf) >= 0) {
- /* check for a block special file meaning this is a real floppy */
- if (stat_buf.st_mode & S_IFBLK) {
- read(unit->fd, unit->image, dsk_size(unit->density));
- }
- /* check for a size miss-match */
- else if (stat_buf.st_size != dsk_size(unit->density)) {
- printf("rxm: file image size does not equal disk %d image size\n", drv);
- if (stat_buf.st_size > dsk_size(unit->density) || !expand_image) {
- close(unit->fd);
- unit->fd = -1;
- printf("rxm: image not attached\n");
- } else {
- printf("rxm: image file expanded\n");
- memset(unit->image, 0, dsk_size(unit->density));
- read(unit->fd, unit->image, stat_buf.st_size);
- lseek(unit->fd, 0, SEEK_SET);
- write(unit->fd, unit->image, dsk_size(unit->density));
- }
- } else {
- read(unit->fd, unit->image, dsk_size(unit->density));
- }
- } else
- printf("rxm: the image file was opened for disk %d, but the fstat failed\n", drv);
- }
- }
- char *func_name[2][8] = { { "Fill Buffer ", /* RX01 */
- "Empty Buffer ",
- "Write Sector ",
- "Read Sector ",
- "NOP ",
- "Read Status ",
- "Write DD Sector ",
- "Read Error Code " },
- { "Fill Buffer ", /* RX02 */
- "Empty Buffer ",
- "Write Sector ",
- "Read Sector ",
- "Set Media Density",
- "Read Status ",
- "Write DD Sector ",
- "Read Error Code " }
- };
- void rx2_reg_dump(void) {
- int i;
- printf("RX02 Emulator V%d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION);
- printf("%s ", rx_mode(2) ? "in native mode" : "in RX01 mode");
- printf("with a %s interface\n", rx_xfer_mode(RX_XFER_DMA) ? "DMA" : "PIO");
- printf("%s\n", rcsid);
- printf("RX2CS = %06o\n ", rx2.cs);
- if (rx2.cs & RX_GO)
- printf("GO ");
- printf("func = %03o ", (rx2.cs & RX_FUNC) >> 1);
- printf("unit = %d ", (rx2.cs & RX_UNIT) ? 1 : 0);
- if (rx2.cs & RX_IE)
- printf("IE ");
- printf("%s ", (rx2.cs & RX_DEN) ? "DD" : "SD");
- printf("ex addr = %o ", (rx2.cs & RX_EXADDR) >> 12);
- if (rx2.cs & RX_CS_INIT)
- printf("INIT ");
- printf("\n");
- printf("RX2TA = %d. (%03o)\n", rx2.ta, rx2.ta);
- printf("RX2SA = %d. (%03o)\n", rx2.sa, rx2.sa);
- printf("RX2WC = %d. (%03o)\n", rx2.wc, rx2.wc);
- printf("RX2ES = %04o\n", rx2.es);
- printf("\nDrive 0: track = %d. (%03o)\n", rx2.drv[0].ta, rx2.drv[0].ta);
- printf(" %s\n", (rx2.drv[0].density == 1) ? "single density" : "double density");
- if (RX_DRDY(0))
- printf(" file name = %s\n", rx2.drv[0].fn);
- else
- printf(" drive is not attached to a file\n");
- printf("\nDrive 1: track = %d. (%03o)\n", rx2.drv[1].ta, rx2.drv[1].ta);
- printf(" %s\n", (rx2.drv[1].density == 1) ? "single density" : "double density");
- if (RX_DRDY(1))
- printf(" file name = %s\n", rx2.drv[1].fn);
- else
- printf(" drive is not attached to a file\n");
- printf("\nFunction counts\n");
- for (i = 0; i < 8; i++)
- printf(" %01o %s %d\n", i, func_name[rx_mode(RX_RX01) ? 0 : 1][i], func_count[i]);
- }
- void prompt(void){
- char command[255];
- char com_s[10];
- char fn_s[255];
- char density_s[10];
- int drv;
- if (!interruptable)
- printf("\nWARNING! Prompting when NOT INTERRUPTABLE.\n"
- "Loss of data is possible!\n");
- printf("\ncommand prompt\n");
- printf(" c\n");
- printf(" 0 [fn | .] [SD | DD]\n");
- printf(" 1 [fn | .] [SD | DD]\n");
- printf(" p\n");
- printf(" s\n");
- printf(" v 0 | 1 | 2 | 3\n");
- printf(" q\n\n");
- do {
- com_s[0] = '\0';
- fn_s[0] = '\0';
- density_s[0] = '\0';
- if (!interruptable)
- printf("NOT INTERRUPTABLE ");
- printf("> ");
- fgets(command, sizeof(command), stdin);
- sscanf(command, "%10s %255s %10s", com_s, fn_s, density_s);
- switch(com_s[0]) {
- case 'c':
- case 'C':
- break;
- case '0':
- case '1':
- drv = (com_s[0] == '0') ? 0 : 1;
- strncpy(rx2.drv[drv].fn, fn_s, sizeof(rx2.drv[0].fn));
- if (strcmp("SD", density_s) == 0)
- rx2.drv[drv].density = DENSITY_SD;
- else if (strcmp("DD", density_s) == 0)
- rx2.drv[drv].density = DENSITY_DD;
- else if (rx2.type == RX_RX02)
- rx2.drv[drv].density = DENSITY_DD;
- else
- rx2.drv[drv].density = DENSITY_SD;
- attach_file(drv);
- break;
- case 'p':
- case 'P':
- rx2_reg_dump();
- break;
- case 's':
- case 'S':
- for (drv = 0; drv < 2; drv++) {
- printf("Drive %d: ", drv);
- if (rx2.drv[drv].fd == -1)
- printf("not attached\n");
- else
- printf("(%s) %s\n", (rx2.drv[drv].density == DENSITY_SD) ? "SD" : "DD", rx2.drv[drv].fn);
- }
- break;
- case 'v':
- case 'V':
- if (fn_s[0] == '0')
- verbose = 0;
- else if (fn_s[0] == '1')
- verbose = 1;
- else if (fn_s[0] == '2')
- verbose = 2;
- else if (fn_s[0] == '3')
- verbose = 3;
- else
- printf("bad parameter for v command\n");
- printf("verbose flag == %d\n", verbose);
- break;
- case 'q':
- case 'Q':
- exit(0);
- default:
- printf("error\n");
- }
- } while (com_s[0] != 'c' && com_s[0] != 'C');
- printf("\n.");
- fflush(NULL);
- intr_signal = 0;
- }
- void intr_handler(int signum) {
- intr_signal += 1;
- if (verbose) {
- printf(" (intr_signal = %d)\n", intr_signal);
- fflush(NULL);
- }
- if (intr_signal >= 10) /* should never occur */
- exit(0);
- signal(SIGINT, intr_handler);
- }
- int main(int argc, char * const argv[]) {
- int c;
- int drv;
- int offset;
- printf("Digital RX02 Disk Simulator V%d.%d.%d\n%s\n", MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION, rcsid);
- verbose = 0;
- expand_image = 0;
- io_base = 0x378;
- rx2.type = RX_RX02;
- // rx2.xfer_mode = rx_if_get(RX_DMA) ? RX_XFER_DMA : RX_XFER_PIO;
- rx2.xfer_mode = RX_XFER_DMA;
- rx2.cs = 0;
- rx2.db = 0;
- rx2.ta = 1;
- rx2.sa = 1;
- rx2.wc = 0;
- rx2.ba = 0;
- rx2.es = 0;
- rx2.err_code = 0;
- rx2.unit = &rx2.drv[0];
- rx2.drv[0].ta = rx2.ta;
- rx2.drv[0].density = DENSITY_DD;
- strncpy(rx2.drv[0].fn, RX0_IMAGE, sizeof(rx2.drv[0].fn));
- rx2.drv[0].fd = -1;
- memset(rx2.drv[0].image, 0, sizeof(rx2.drv[0].image));
- rx2.drv[1].ta = 0;
- rx2.drv[1].density = DENSITY_DD;
- strncpy(rx2.drv[1].fn, RX1_IMAGE, sizeof(rx2.drv[1].fn));
- rx2.drv[1].fd = -1;
- memset(rx2.drv[1].image, 0, sizeof(rx2.drv[1].image));
- memset(buffer, 0, sizeof(buffer));
- memset(dd_sec_map, NORMAL_DATA, sizeof(dd_sec_map));
- rx2.es = RX_DRDY(0) | RX_DENSITY(0) | RX_ID | (rx_mode(RX_RX02) ? RX_RX02_ID : 0); /* drive ready */
- drv = 0; /* initial options for drive 0 */
- do {
- c = getopt(argc, argv, "t:0:1:d:p:vhx");
- switch(c) {
- case 't': /* set drive type */
- if (verbose)
- printf("option: t (set drive type)\n");
- if (optarg != NULL && strcmp("RX01", optarg) == 0) {
- if (verbose)
- printf("simulating RX01 drive\n");
- rx2.type = RX_RX01;
- rx2.xfer_mode = RX_XFER_PIO;
- if (verbose)
- printf("simulating PIO interface (RX8E, RXV11, RX11)\n");
- rx2.drv[0].density = DENSITY_SD;
- rx2.drv[1].density = DENSITY_SD;
- } else if (optarg != NULL && strcmp("RX02", optarg) == 0) {
- if (verbose)
- printf("simulating RX02 drive\n");
- rx2.type = RX_RX02;
- /* this is really not necessary if the DMA signal line was hooked up */
- } else if (optarg != NULL && strcmp("PIO", optarg) == 0) {
- if (verbose)
- printf("simulating PIO interface (RX8E, RXV11, RX11)\n");
- rx2.xfer_mode = RX_XFER_PIO;
- } else if (optarg != NULL && strcmp("DMA", optarg) == 0) {
- if (rx2.type == RX_RX01) {
- printf("rxm: invalid xfer mode for an RX01\n");
- break;
- }
- if (verbose)
- printf("simulating DMA interface (RXV21, RX211)\n");
- rx2.xfer_mode = RX_XFER_DMA;
- } else
- printf("rxm: invalid drive type or transfer mode\n");
- break;
- case '0': /* set filename for drive 0 or 1 */
- case '1':
- drv = (c == '0') ? 0 : 1;
- if (verbose)
- printf("option: %d (set drive %d file name)\n", drv, drv);
- if (optarg != NULL)
- strncpy(rx2.drv[drv].fn, optarg, sizeof(rx2.drv[drv].fn));
- else
- printf("rxm: no file name\n");
- if (verbose)
- printf("drive %d file name = %s\n", drv, rx2.drv[drv].fn);
- break;
- case 'd': /* set floppy density in drive */
- if (verbose)
- printf("option: d (set floppy density in drive %d)\n", drv);
- if (optarg != NULL && strcmp("SD", optarg) == 0)
- rx2.drv[drv].density = DENSITY_SD;
- else if (optarg != NULL && strcmp("DD", optarg) == 0)
- rx2.drv[drv].density = DENSITY_DD;
- else
- printf("rxm: bad density value\n");
- if (verbose)
- printf("drive %d density set to %s\n", drv, (rx2.drv[drv].density == DENSITY_SD) ? "SD" : "DD");
- if (rx2.type == 1 && rx2.drv[drv].density == DENSITY_DD) {
- printf("rxm: WARNING: attempt to set double density in an RX01. Ignored.\n");
- rx2.drv[drv].density = DENSITY_SD;
- }
- break;
- case 'p':
- if (verbose)
- printf("option: p (set the parallel port address)\n");
- if (optarg != NULL && strcmp("0x378", optarg) == 0)
- io_base = 0x378;
- else if (optarg != NULL && strcmp("0x278", optarg) == 0)
- io_base = 0x278;
- else
- printf("rxm: bad parallel port address\n");
- break;
- case 'h':
- printf("Usage: rxm [OPTION]...\n");
- printf("Emulate a DEC RX02 Floppy Drive System\n");
- printf("Using parallel port at 0x%04x\n", IO_BASE);
- printf("\n");
- printf(" -0 FILENAME use FILENAME for drive 0 image\n");
- printf(" -1 FILENAME use FILENAME for drive 1 image\n");
- printf(" -x expand images that are too small\n");
- printf(" -d SD | DD act as though previous image was of density\n");
- printf(" -h print help message and exit\n");
- printf(" -t RX01 | RX02 | DMA | PIO select emulation type and tranfer mode\n");
- printf(" -p ADDRESS set the parallel port address\n");
- printf(" -v display extra information\n");
- printf("\n");
- exit(0);
- break;
- case 'v':
- verbose += 1;
- printf("entering verbose mode\n");
- break;
- case 'x':
- expand_image = 1;
- if (verbose)
- printf("image expansion enabled\n");
- break;
- case -1:
- break;
- }
- } while (c != -1);
- #if defined __linux__
- if (ioperm(IO_DATA, IO_LEN, 1)) {
- perror("rxm: ioperm");
- exit(-1);
- }
- #elif defined __NetBSD__
- if (i386_get_ioperm(iomap)) {
- perror("rxm: i386_get_ioperm");
- exit(-1);
- }
- iomap[IOMAP_OFFSET] &= ~IOMAP_BITMASK;
- if (i386_set_ioperm(iomap)) {
- perror("rxm: i386_set_ioperm");
- exit(-1);
- }
- #else
- #error Present system not supported
- #endif
- printf(" %lld cycles since boot\n", rdtsc());
- if (verbose)
- printf("simulating %d bit interface\n", RX_NBITS());
- for (drv = 0; drv < NUNITS; drv++) {
- attach_file(drv);
- }
- intr_signal = 0;
- interruptable = 0;
- if (signal(SIGINT, intr_handler) == SIG_ERR) {
- printf("rxm: error when setting SIGINT handler\n");
- exit(-1);
- }
- /* copy boot sector into the buffer */
- offset = (rx2.ta*NSECTS + (rx2.sa - 1))*sec_size(rx2.drv[0].density);
- memcpy(buffer, &rx2.drv[0].image[offset], sec_size(rx2.drv[0].density));
- rx_if_clr(0xffffffff); /* clear all interface bits */
- while (1) {
- do_func();
- if (rx_if_get(RX_INIT)) {
- rx_init();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement