home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1999 mARCH
/
PCWK3A99.iso
/
Archiwiz
/
Tar320
/
SOURCES.ZIP
/
QICFACE.C
< prev
next >
Wrap
Text File
|
1994-10-27
|
9KB
|
316 lines
#include <stdio.h>
#include "sysup.h"
#ifdef MSDOS
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#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<MAXLEX && *s && *s!='.'; i++) {
if (*s == ':' || *s == ';' || *s == ',') goto test_name;
lex[i] = *s++;
}
return FALSE;
test_name:
lex[i] = '\0';
if ((board_type=streamer('?', lex, 0)) < 0) return FALSE;
id.base_address = UNUSED;
id.dma_number = UNUSED;
id.irq_number = UNUSED;
no_rewind = FALSE;
seek_eod = FALSE;
to_skip = 0;
while (*++s) {
for (i=0; i<=MAXLEX; ++i, s++) {
if (*s >= '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<dimof(qiclist); i++) {
if (qiclist[i].nqic == k) {
cmdset = qiclist[i].command; break;
}
}
}
}
if (!cmdset) {
errmsg = "invalid QIC number"; goto error;
}
} else {
if (*s == ':') ++s;
if (*s == '=') ++s;
if (strncmp("base", lex, i) == 0) {
for (id.base_address=0, i=0; i<5; ++i, s++) {
register j = '0';
if (*s>='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<dimof(qiclist); i++) {
if (qiclist[i].tracks == k) {
cmdset = qiclist[i].command; break;
}
}
}
if (!cmdset) {
errmsg = "invalid number of tracks"; goto error;
}
} else if (!strncmp("skip", lex, i)) {
if (seek_eod || no_rewind) goto excl;
for (to_skip=0, i=0; i<5 && *s>='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<<ndrive)&15/*|Q2_SELECT*/))!=0) goto error;
}
if (!no_rewind) {
#if 0
if ((k=c_flag ? streamer('i',NULL,Q2_ERASE) : streamer('n',NULL,0))!=0)
goto error;
#else
if ((k=streamer('n', NULL, 0)) != 0) goto error;
if (c_flag && !(seek_eod || to_skip)) {
if ((k=streamer('i', NULL, Q2_ERASE)) != 0 ||
(k=streamer('n', NULL, 0)) != 0) goto error;
}
#endif
if (cmdset) {/* select tape format */
if ((k=streamer('i', NULL, cmdset)) != 0) goto error;
}
if (to_skip) {
if ((k=streamer('f', NULL, to_skip)) != 0) goto error;
} else if (seek_eod) {
if ((k=streamer('i', NULL, Q2_EOD)) != 0) goto error;
if ((k=streamer('t', NULL, 0)) != 0) {
if (k!=Q2E_ERM && k!=Q2E_NDT) goto error;
k = 0;
}
}
}
return 0;
error:
qerror(k);
return k;
}
void qend(void)
{
if (a_flag) streamer('d',NULL,0);
else if (!no_rewind) streamer('n',NULL,0);
streamer('c',NULL,0);
}
static void ioerror(unsigned mask)
{
register k;
struct qic02_word_status s;
extern int ct_errbit(unsigned);
k = streamer('t', &s, 0);
if (k >= 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
}