#include #include "sysup.h" #ifdef MSDOS #include #include #include #include "modern.h" #include "define.h" #include "qic02.h" #define MAXLEX 8 #define SKIP_RESET 0x80 static int board_type = UNUSED; static struct init_data id = { UNUSED, UNUSED, UNUSED }; static int no_rewind = FALSE, seek_eod = FALSE, to_skip = 0; static BYTE cmdset = 0; static struct { int nqic; BYTE tracks, command; } qiclist[] = { { 11, 4, Q2_QIC11 }, { 24, 9, Q2_QIC24 }, { 120, 15, Q2_QIC120 }, { 150, 18, Q2_QIC150 }, { 300, -1, 0x2A }, { 2100,-1, 0x2A }, { 600, -1, 0x2B }, { 2200,-1, 0x2B }, }; int qparse(char *s) { static char already[] = "tape format already defined"; char lex[MAXLEX+1], *errmsg; register i, k; for (i=0; i= 'A' && *s <= 'Z') lex[i] = *s | ('z'^'Z'); else if (*s >= 'a' && *s <= 'z') lex[i] = *s; else break; } if (i < 1 || i > MAXLEX) { errmsg = "device parameter error"; goto error; } lex[i] = '\0'; /* for diagnostic printing */ if (!strncmp("norewind", lex, i)) { if (seek_eod || to_skip) goto excl; no_rewind = TRUE; } else if (!strncmp("add", lex, i)) { if (to_skip || no_rewind) goto excl; seek_eod = TRUE; } else if (!strncmp("qic", lex, i)) { if (cmdset) { errmsg = already; goto error; } if (*s == '-') { ++s; } else { if (*s == ':') ++s; if (*s == '=') ++s; } if (*s >= '1' && *s <= '9') { k = 0; i = 0; do { k = (*s++ - '0') + 10*k; } while (++i < 5 && *s >= '0' && *s <= '9'); if (i < 5) { for (i=0; i='A' && *s<='F') j = 'A' - 10; else if (*s>='a' && *s<='f') j = 'a' - 10; else if (*s <'0' || *s >'9') break; id.base_address = (id.base_address << 4) | (*s - j); } if (i<1 || i>4) { errmsg = "invalid base address"; goto error; } if (*s == 'h' || *s == 'H') ++s; } else if (strncmp("dma", lex, i) == 0) { if (*s<'0' || *s>'7') { errmsg = "invalid DMA channel number"; goto error; } id.dma_number = *s++ & 7; } else if (strncmp("irq", lex, i) == 0) { for (id.irq_number=0, i=0; i<3 && *s>='0' && *s<='9'; ++i, s++) { id.irq_number = 10*id.irq_number + *s - '0'; } if (i<1 || i>2 || id.irq_number > 15) { errmsg = "invalid IRQ number"; goto error; } } else if (strncmp("tracks", lex, i) == 0) { if (cmdset) { errmsg = already; goto error; } for (k=0, i=0; i<3 && *s>='0' && *s<='9'; ++i, s++) { k = (*s - '0') + 10*k; } if (i > 0 && i < 3) { for (i=0; i='0' && *s<='9'; ++i, s++) { to_skip = (*s - '0') + 10*to_skip; } } else { (void)fprintf(stderr,"Tar: unknown parameter \'%s\'\n",lex); return ERROR; } } if (*s == '\0') break; if (*s != ',' && *s != ':' && *s != '.') { (void)fprintf(stderr,"Tar: invalid character after \'%s\'\n",lex); return ERROR; } } if (id.base_address == UNUSED) { errmsg = "base address must be specified"; goto error; } if (!cblock) cblock = 1; return TRUE; excl: errmsg = "\'add\', \'skip\' and \'norewind\' are mutually exclusive"; error: (void)fprintf(stderr,"Tar: %s\n", errmsg); return ERROR; } static void qerror(int k) { if (k < 0) { (void)fprintf(stderr, "Tar: %s\n", strerror(errno)); } else if (k < qic02_nerr) { (void)fprintf(stderr, "Tar: %s\n", qic02_errlist[k]); } else { (void)fprintf(stderr, "Tar: error #%d\n", k); } } int qbegin(void) { register k; if (no_rewind) board_type |= SKIP_RESET; if ((k=streamer('o', &id, board_type)) != 0) { if (k != CTE_FAULT || errno != EINVDAT) goto error; (void)fprintf(stderr, "Tar: unsupported hardware configuration\n"); return k; } if (setdrive) { if ((k=streamer('i',NULL,(1<= 0 && k <= CTE_BUSY) { k = ct_errbit(mask & s.status); } qerror(k); } /* Interface routines */ int qread(char *buf, register int n) { if (n & (BLKSIZE-1)) return -1; if (streamer('r', buf, n) != n) { ioerror(~(Q2E_BOM|Q2E_WRP)); return -1; } return n; } int qwrite(char *buf, register int n) { n = (BLKSIZE-1 + n) & ~(BLKSIZE-1); if (streamer('w', buf, n) != n) { ioerror(~Q2E_BOM); return -1; } return n; } int qback(n) register n; { register j, k; for (j=(n+cblock-1)/cblock; j; j--) if ((k=streamer('i',NULL,Q2_REVERSE)) != 0) { qerror(k); return -1; } return n; } #endif char *getbuf(length) int length; { register char *ptr; #ifdef MSDOS int dw; /* size of DMA word */ dw = id.dma_number & ~7 ? 0 : 1 + (id.dma_number >> 2); ptr = malloc(length); if (!ptr) { (void)fprintf(stderr, "Tar: not enough memory\n"); } else if (dw > 0) { long a; register s; a = ptr2abs(ptr); s = dw + 15; /* shift factor to get DMA page number */ /* Compare DMA pages */ if ((a >> s) != ((a+length-1) >> s)) { /* Attempt to get DMA page-aligned buffer assumes: */ /* - length is not greater than half of DMA page; */ /* - malloc() heap is unfragmented. */ register void *tmp; tmp = ptr; ptr = malloc(length); free(tmp); if (!ptr) { (void)fprintf(stderr, "Tar: no memory to align buffer\n"); return (void *)0; } a = ptr2abs(ptr); if ((a >> s) != ((a+length-1) >> s)) { (void)fprintf(stderr, "Tar: fail to align buffer\n"); free(ptr); return (void *)0; } } if (a & (dw - 1)) { (void)fprintf(stderr, "Tar: DMA buffer is not word-aligned\n"); free(ptr); return (void *)0; } } return ptr; #else extern char *malloc(); ptr = malloc(length); if (!ptr) (void)fprintf(stderr, "Tar: not enough memory\n"); return ptr; #endif }