|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 17525 (0x4475)
Types: TextFile
Notes: UNIX file
Names: »tcf.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦2d53db1df⟧ UNIX Filesystem
└─⟦this⟧ »sys/z8001/diag/tcf.c«
/* (-lgl
* The information contained herein is a trade secret of Mark Williams
* Company, and is confidential information. It is provided under a
* license agreement, and may be copied or disclosed only under the
* terms of that agreement. Any reproduction or disclosure of this
* material without the express written authorization of Mark Williams
* Company or persuant to the license agreement is unlawful.
*
* COHERENT Version 0.7.3
* Copyright (c) 1982, 1983, 1984.
* An unpublished work by Mark Williams Company, Chicago.
* All rights reserved.
-lgl) */
/*
* Driver for Commodore floppy disk controller for the Z8000HR.
*
* Uses Commodore's SASI-like command block structure.
*
* April 1, 1985 Original version based upon WD hard disk diagnostic. (nrb)
* April 12, 1985 added fixes for command block clearing. (nrb)
*/
#define CMDBLKPADDR (0x80010L) /* WD command blk phys addr */
#define BUFPADDR (0x80400L) /* CMDBLKPADDR + 1K */
#define LONGBUFPADDR (0xA0000L) /* CMDBLKPADDR + 128K */
#define VERS "V1.2" /* version # */
#include <coherent.h>
#include <buf.h>
#include <con.h>
#include <stat.h>
#include <uproc.h>
#include <errno.h>
/*
* this is to make this file compatable with tmd.s
*/
#undef WDS
#define WDS 0x3C
int wdload();
int wdopen();
int wdread();
int wdwrite();
int wdblock();
int wdintr();
int nulldev();
int nonedev();
char *pfix(); /* map phys addr to a char * */
int wfill(); /* fill block w/ test pattern */
int wcheck(); /* compare data pattern */
CON wdcon = {
DFBLK|DFCHR, /* Flags */
2, /* Major index */
wdopen, /* Open */
nulldev, /* Close */
wdblock, /* Block */
wdread, /* Read */
wdwrite, /* Write */
nonedev, /* Ioctl */
nulldev, /* Powerfail */
nulldev, /* Timeout */
wdload, /* Load */
nulldev /* Unload */
};
/*
* Western Digital Controller port addresses
*/
#define WDIO 0x0500 /* Data Register (word mode) */
#define TRUE (0 == 0)
#define FALSE (0 != 0)
#define NBLK 2300 /* number of blocks per floppy */
#define NBLOCK 32 /* for highest density region */
#define CFFMT 0x04 /* format entire floppy */
#define CFREAD 0x08 /* read */
#define CFWRITE 0x0A /* write */
#define WDIRQ 0x80 /* base of interrupt vector */
typedef struct wdcmd { /* command block layout */
unsigned char c_opcode; /* command class & opcode */
unsigned char c_lunhiaddr; /* lun [7:5] & sector addr [4:0] */
unsigned char c_midaddr; /* middle sector address */
unsigned char c_lowaddr; /* low part of sector address */
unsigned char c_blockcnt; /* number of blocks in I/O */
unsigned char c_control; /* reserved control byte */
unsigned char c_highdma; /* high DMA addr (phys segment) */
unsigned char c_middma; /* middle DMA address */
unsigned char c_lowdma; /* low DMA address */
unsigned char c_rsvd1; /* reserved */
unsigned char c_rsvd2; /* reserved */
unsigned char c_rsvd3; /* reserved */
unsigned char c_errorbits; /* error information */
unsigned char c_lunladd2; /* error lun and high sector addr */
unsigned char c_ladd1; /* error middle address */
unsigned char c_ladd0; /* error low address */
} WDCMD;
int wdiflag; /* interrupt acknowledge flag */
int timeouts; /* number of timeouts */
int errors; /* total # of errors */
int typeno; /* drive type selected from table */
int patno; /* pattern selection # */
int unit; /* which physical drive ? */
long nblk; /* number of blocks on device */
int errsup; /* suppress error messages */
int wdlwait = FALSE; /* long timeout ?? */
extern char databuf[512];
extern unsigned char pattern[512];
unsigned int seedy;
/*
* simple test routine to try and format the floppy disk using the new
* floppy controller for the Commodore Z8000HR...
*/
wdload()
{
register long l;
register unsigned pass = 0;
register int ans, i;
register int tfmt, tver, bwrite, bread, rndread;
register int prwrite, prread, cylread, cylrdwr;
#ifdef NOINTERRUPTS
sphi(); /* never to be set low again! */
#endif
timeouts = 0; errors=0; unit=0; typeno=0; patno=0; errsup=0;
tfmt=0; tver=0; bwrite=0; bread=0; rndread=0; cylread=0; cylrdwr=0;
prwrite=0; prread=0;
printf("Floppy disk diagnostic for Commodore controller, %s\n\n",VERS);
nblk = NBLK;
printf("Select drive unit number [%d]: ", unit);
while ((ans=getchar()) != '\n')
if (ans == '0' || ans == '1')
unit = ans - '0';
printf("Select pattern: 0=<00-FF> 1=worst 2=<0-F> 3=FFxx 4=xxFF [%d]: ",
patno);
while ((ans=getchar()) != '\n')
if (ans >= '0' && ans <= '4')
patno = ans - '0';
printf("Suppress error messages ? [n]: ");
while ((ans=getchar()) != '\n')
if (ans == 'y' || ans == 'Y')
errsup = 1;
printf("Disk parameters: unit=%d blocks=%d\n", unit, (int)NBLK);
printf("Select desired options:\n 1=format/verify device\n");
printf(" 3=block write\n 4=block read\n 5=random read\n");
printf(" 6=multi-block read\n 7=multi-block write/read/compare\n");
printf(" 8=pseudo-random data write\n 9=pseudo-random read\n? ");
while ((ans=getchar()) != '\n')
switch (ans) {
case '1':
++tfmt; break;
case '3':
++bwrite; break;
case '4':
++bread; break;
case '5':
++rndread; break;
case '6':
++cylread; break;
case '7':
++cylrdwr; break;
case '8':
++prwrite; break;
case '9':
++prread; break;
};
cmdblkclear(CMDBLKPADDR-0x10); /* clear WD command block */
cmdblkclear(CMDBLKPADDR); /* clear floppy command blk */
setivec(WDIRQ, wdintr);
switch (patno) {
case 0:
for (i = 0; i <= 255; ++i)
pattern[i] = i;
for (i = 255; i >= 0; --i)
pattern[511-i] = i;
break;
case 2:
for (i = 0; i < 32; ++i)
for (ans = 0; ans < 16; ++ans)
pattern[16*i+ans] = ans;
break;
case 3: /* pattern for Eric */
for (i=0; i < 256; ++i) {
pattern[2*i] = 0xFF; /* data bits 15:8 */
pattern[2*i+1] = i;
}
break;
case 4:
for (i = 0; i < 256; ++i) {
pattern[2*i] = i;
pattern[2*i+1] = 0xFF;
}
break;
}
testloop:
if (tfmt) {
printf("Starting disk format\n");
wdfmttrk();
}
if (bwrite) {
printf("Starting write phase\n");
seedy = 0;
for (l = 0; l < nblk; ++l)
wdwrite(l);
}
if (bread) {
printf("Starting read phase\n");
seedy = 0;
for (l = 0; l < nblk; ++l)
wdread(l);
}
if (rndread) {
printf("Starting random read phase\n");
for (l = 0; l < 250L; ++l)
wdread((long)(((long)rand())%nblk));
}
if (cylread) {
printf("Starting multi-block read phase - %d sectors/IO\n",
(int)NBLOCK);
for (l = 0; l < (long)(nblk/NBLOCK); ++l)
wdlread(l*NBLOCK);
}
if (cylrdwr) {
printf("Starting multi-block write/read/compare phase\n");
seedy = 0;
for (l = 0; l < (long)(nblk/NBLOCK); ++l)
wdcrdwr(l*NBLOCK);
}
if (prwrite) {
printf("Starting pseudo-random write phase\n");
srand(0); /* seed for random # generator */
for (l = 0; l < nblk; ++l)
wdprwrite(l);
}
if (prread) {
printf("Starting pseudo-random read phase\n");
srand(0); /* seed for random # generator */
for (l = 0; l < nblk; ++l)
wdprread(l);
}
printf("\n\007Unit %d: pass count = %d, timeouts = %d errors=%d\n",
unit, ++pass, timeouts, errors);
goto testloop;
}
wdwait()
{
register int s;
register long l = 1000000L;
#ifdef NOINTERRUPTS
register WDCMD *cbp;
register unsigned i;
#endif
if (wdlwait)
l = 120000000L;
out(WDIO, 1); /* strobe I/O line to floppy */
#ifdef NOINTERRUPTS
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
do {
i = cbp->c_errorbits;
--l;
} while ((i&0xFF) == 0xFF && l);
#else
wdiflag = 0;
s = splo();
while (!wdiflag && --l > 0)
;
spl(s);
#endif
if (!l) {
eprintf("\nTIMEOUT ERROR\n");
++timeouts; ++errors;
#ifndef NOINTERRUPTS
out(WDIO, 0);
#endif
}
#ifdef NOINTERRUPTS
out(WDIO, 0); /* reset IEO on DMA chip */
#endif
}
wdfmttrk()
{
register int i;
register WDCMD *cbp;
register unsigned char *cp;
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
cp[i] = 0;
cbp->c_opcode = CFFMT; /* format device */
cbp->c_highdma =(BUFPADDR >> 16); /* phys segment */
cbp->c_middma = (BUFPADDR >> 8); /* offset */
cbp->c_lowdma = 0x00;
cbp->c_lunhiaddr = (unit << 5);
cbp->c_errorbits = 0xff; /* make ready */
wdlwait = TRUE;
wdwait(); /* wait for i/o complete */
wdlwait = FALSE;
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
i = cbp->c_errorbits;
if (i & 0x7F) {
eprintf("\nformat error: %x\n", i);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
eprintf("%x ", cp[i]);
eprintf("\n");
++errors;
}
}
wdintr(id)
int id;
{
#ifdef NOINTERRUPTS
eprintf("wdintr: got a spurious interrupt !!!\n");
++errors;
#else
wdiflag++;
out(WDIO, 0); /* reset IEO on DMA chip */
#endif
}
wdopen()
{
eprintf("wdopen: \n");
}
wdread(sn)
long sn;
{
register int i;
register WDCMD *cbp;
register unsigned char *cp;
eprintf("%d \r", (int)sn);
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
cp[i] = 0;
cbp->c_opcode = CFREAD; /* read a sector */
cbp->c_blockcnt = 1;
cbp->c_highdma = (BUFPADDR >> 16);
cbp->c_middma = (BUFPADDR >> 8);
cbp->c_lowdma = 0x00;
cbp->c_lunhiaddr = (unit << 5) | (sn >> 16);
cbp->c_midaddr = sn >> 8;
cbp->c_lowaddr = sn;
cbp->c_errorbits = 0xff; /* make ready */
cp = pfix(WDS, (paddr_t) BUFPADDR);
wdblkinit(cp, 0x13); /* fill with known values */
wdwait(); /* wait for i/o complete */
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
i = cbp->c_errorbits;
if (i & 0x7F) {
eprintf("\nread error: block=%p, i=%x\n", sn, i);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
eprintf("%x ", cp[i]);
eprintf("\n");
++errors;
}
cp = pfix(WDS, (paddr_t)BUFPADDR);
if (wcheck(cp, sn)) {
++errors;
}
}
wdwrite(sn)
long sn;
{
register int i;
register WDCMD *cbp;
register unsigned char *cp;
eprintf("%d\r", (int)sn);
cp = pfix(WDS, (paddr_t)BUFPADDR); /* data area */
wfill(cp);
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
cp[i] = 0;
cbp->c_opcode = CFWRITE; /* write a sector */
cbp->c_blockcnt = 1;
cbp->c_highdma = (BUFPADDR >> 16);
cbp->c_middma = (BUFPADDR >> 8);
cbp->c_lowdma = 0x00;
cbp->c_lunhiaddr = (unit << 5) | (sn >> 16);
cbp->c_midaddr = sn >> 8;
cbp->c_lowaddr = sn;
cbp->c_errorbits = 0xff; /* make ready */
wdwait(); /* wait for i/o complete */
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
i = cbp->c_errorbits;
if (i & 0x7F) {
eprintf("\nwrite error: block=%p, i=%x\n", sn, i);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
eprintf("%x ", cp[i]);
eprintf("\n");
++errors;
}
}
wdblock()
{
eprintf("wdblock:\n");
}
wdlread(sn)
long sn;
{
register WDCMD *cbp;
register unsigned char *cp;
register int i, j;
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
cp[i] = 0;
cbp->c_opcode = CFREAD; /* read a sector */
cbp->c_blockcnt = NBLOCK;
cbp->c_highdma =(LONGBUFPADDR >> 16);
cbp->c_middma = (LONGBUFPADDR >> 8);
cbp->c_lowdma = 0x00;
cbp->c_lunhiaddr = (unit << 5) | (sn >> 16);
cbp->c_midaddr = sn >> 8;
cbp->c_lowaddr = sn;
cbp->c_errorbits = 0xff; /* make ready */
wdwait(); /* wait for i/o complete */
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
i = cbp->c_errorbits;
if (i & 0x7F) {
eprintf("\nread error: block=%p, i=%x\n", sn, i);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
eprintf("%x ", cp[i]);
eprintf("\n");
++errors;
}
cp = pfix(WDS, (paddr_t)LONGBUFPADDR);
for (j = 0; j < (int)NBLOCK; ++j) {
if (wcheck(cp, sn+j)) {
++errors;
out(0x700, 1);
}
cp += 512; /* next block */
}
}
wdcrdwr(sn)
long sn;
{
register WDCMD *cbp;
register unsigned char *cp;
register int i, j;
eprintf("%u\r", (int)sn);
cp = pfix(WDS, (paddr_t)LONGBUFPADDR);
for (j = 0; j < (int)NBLOCK; ++j) {
wfill(cp); /* fill 512 byte block */
cp += 512;
}
for (i = 0; i < 512; ++i)
*cp++ = 0x13; /* put in pattern */
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
cp[i] = 0;
cbp->c_opcode = CFWRITE;
cbp->c_blockcnt = NBLOCK;
cbp->c_highdma =(LONGBUFPADDR >> 16);
cbp->c_middma = (LONGBUFPADDR >> 8);
cbp->c_lowdma = 0x00;
cbp->c_lunhiaddr = (unit << 5) | (sn >> 16);
cbp->c_midaddr = sn >> 8;
cbp->c_lowaddr = sn;
cbp->c_errorbits = 0xff; /* make ready */
wdwait(); /* wait for i/o complete */
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
i = cbp->c_errorbits;
if (i & 0x7F) {
eprintf("\nwrite error: block=%p, i=%x\n", sn, i);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
eprintf("%x ", cp[i]);
eprintf("\n");
++errors;
}
cp = pfix(WDS, (paddr_t)LONGBUFPADDR);
for (i = 0; i < (int)NBLOCK; ++i) {
wdblkinit(cp, 0x13);
cp += 512;
}
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
cp[i] = 0;
cbp->c_opcode = CFREAD; /* read */
cbp->c_blockcnt = NBLOCK;
cbp->c_highdma =(LONGBUFPADDR >> 16);
cbp->c_middma = (LONGBUFPADDR >> 8);
cbp->c_lowdma = 0x00;
cbp->c_lunhiaddr = (unit << 5) | (sn >> 16);
cbp->c_midaddr = sn >> 8;
cbp->c_lowaddr = sn;
cbp->c_errorbits = 0xff; /* make ready */
wdwait(); /* wait for i/o complete */
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
i = cbp->c_errorbits;
if (i & 0x7F) {
eprintf("\nread error: block=%p, i=%x\n", sn, i);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
eprintf("%x ", cp[i]);
eprintf("\n");
++errors;
}
seedy -= NBLOCK;
cp = pfix(WDS, (paddr_t)LONGBUFPADDR);
for (j = 0; j < (int)NBLOCK; ++j) {
if (wcheck(cp, sn+j)) {
out(0x700, 1);
++errors;
}
cp += 512; /* next block */
}
for (i = 0; i < 512; ++i)
if (*cp++ != 0x13) {
eprintf("DMA wrote into memory block past buffer\007\n");
out(0x700, 1);
for (--cp, j = 0; i < 512; ++i, cp++)
if (*cp != 0x13)
eprintf("ofs=%d %x!=13; %s", i, *cp,
(++j % 4) ? "" : "\n");
break;
}
}
vret(vec)
int vec;
{
eprintf("\nbad int vec=0x%x\n", vec);
}
wdprwrite(sn)
long sn;
{
register int i;
register WDCMD *cbp;
register unsigned char *cp;
register int *ip;
eprintf("%d\r", (int)sn);
ip = (int *)pfix(WDS, (paddr_t)BUFPADDR); /* data area */
for (i = 0; i < 256; ++i)
*ip++ = rand(); /* generate next in pseudo-sequence */
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
cp[i] = 0;
cbp->c_opcode = CFWRITE; /* write a sector */
cbp->c_blockcnt = 1;
cbp->c_highdma = (BUFPADDR >> 16);
cbp->c_middma = (BUFPADDR >> 8);
cbp->c_lowdma = 0x00;
cbp->c_lunhiaddr = (unit << 5) | (sn >> 16);
cbp->c_midaddr = sn >> 8;
cbp->c_lowaddr = sn;
cbp->c_errorbits = 0xff; /* make ready */
wdwait(); /* wait for i/o complete */
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
i = cbp->c_errorbits;
if (i & 0x7F) {
eprintf("\nwrite error: block=%p, i=%x\n", sn, i);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
eprintf("%x ", cp[i]);
eprintf("\n");
++errors;
}
}
wdprread(sn)
long sn;
{
register int i;
register WDCMD *cbp;
register unsigned char *cp;
register int *ip;
register unsigned char *bp;
eprintf("%d \r", (int)sn);
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
cp[i] = 0;
cbp->c_opcode = CFREAD; /* read */
cbp->c_blockcnt = 1;
cbp->c_highdma = (BUFPADDR >> 16);
cbp->c_middma = (BUFPADDR >> 8);
cbp->c_lowdma = 0x00;
cbp->c_lunhiaddr = (unit << 5) | (sn >> 16);
cbp->c_midaddr = sn >> 8;
cbp->c_lowaddr = sn;
cbp->c_errorbits = 0xff; /* make ready */
wdwait(); /* wait for i/o complete */
cbp = (WDCMD *) pfix(WDS, (paddr_t)CMDBLKPADDR);
i = cbp->c_errorbits;
if (i & 0x7F) {
eprintf("\nread error: block=%p, i=%x\n", sn, i);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
eprintf("%x ", cp[i]);
eprintf("\n");
++errors;
}
for (ip = databuf, i = 0; i < 256; ++i)
*ip++ = rand();
cp = pfix(WDS, (paddr_t)BUFPADDR);
if (wdcompare(databuf, cp)) {
for (bp = databuf, i = 0; i < 512; ++i)
if (*cp++ != *bp++) {
eprintf("\nread data compare error block=%d,",(int)sn);
eprintf("disk 0x%x != 0x%x, offset=%d\n",
*--cp, *--bp, i);
++errors;
return;
}
}
}
wfill(spot)
register unsigned char *spot;
{
register unsigned int count;
for (count = 0; count < 512; ++count)
*spot++ = pattern[(seedy+count)&511];
++seedy;
}
wcheck(spot, bn)
register unsigned char *spot;
long bn;
{
register int count;
register int err = 0;
register int loopc;
for (count = 0; count < 512; ++count)
if (*spot++ != pattern[(seedy+count)&511]) {
out(0x700, 1);
eprintf("\ndata err %x != %x ofs=%u b=%u\n",
*--spot, pattern[(seedy+count)&511],
count, (int)bn);
eprintf("disk: ");
for (loopc = -5; loopc <= 5; ++loopc)
eprintf("%x ", spot[loopc]);
eprintf("\nreal: ");
for (loopc = count-5; loopc <= count+5; ++loopc)
eprintf("%x ", pattern[(seedy+loopc)&511]);
eprintf("\n");
++err;
break;
}
seedy++;
if (err)
out(0x700, 1);
return (err);
}
eprintf(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
{
if (errsup)
return;
printf(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);
}
/*
* clear out the command block given by the physical address 'cbpaddr'.
*/
cmdblkclear(cbpaddr)
paddr_t cbpaddr;
{
register int i;
register WDCMD *cbp;
register unsigned char *cp;
cbp = (WDCMD *) pfix(WDS, cbpaddr);
for (cp = cbp, i = 0; i < sizeof(WDCMD); ++i)
cp[i] = 0;
}