home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Guide
/
c-cplusplus-interactive-guide.iso
/
c_ref
/
csource3
/
181_01
/
disk1_c.lst
< prev
next >
Wrap
File List
|
1986-01-09
|
11KB
|
416 lines
Reprinted from: Micro/Systems Journal, Volume 1. No. 2. May/June 1985
Article Title: "C & Godbout Disk-1 Controller"
Author: Edward Heyman
-----------------------------------------------------------------
Copy of back issue may be obtained for $4.50 (foreign $6) from:
Subscriptions are: $20/yr & $35/2yrs ; published bi-monthly
Micro/Systems Journal
Box 1192
Mountainside NJ 07092
-----------------------------------------------------------------
Copyright 1986
Micro/Systems Journal, Box 1192, Mountainside NJ 07092
This software is released into the public domain for
non-commercial use only.
-----------------------------------------------------------------
LISTING 1
/* reads the 8272 status port untill the chip is ready for a command */
/* byte, must be done before each command byte is sent to the 8272 */
int cmdstat()
{
char c;
while ( (c = inp(fdcstat)) < 0x80);
return(TRUE);
}
LISTING 2
/* print value of 8272 status register 0's bits */
st0(byte)
char byte;
{
char drive,hd,nr,ec,se,ic;
drive = byte & 3; /* drive number */
hd = (byte >> 2) & 1; /* head address ie; 0 or 1 */
nr = (byte >> 3) & 1; /* not ready if 1 */
ec = (byte >> 4) & 1; /* equipment check */
se = (byte >> 5) & 1; /* seek end */
ic = (byte >> 6) & 3; /* interrupt code, does not */
/* work as per 8272 data sheet for read and write commands */
/* since Godbout did not implement the terminal count line */
printf("\n ST0> %s %u %s %u %s %u %s %u %s %u %s %u \n",
"drive = ",drive,
" head = ",hd," nr = ",nr," ec = ",ec," se = ",se," ic = ",ic);
}/* st0 */
LISTING 3
/* prompt for and return drive number */
/* drive may be entered as 'a','b','A','B','0' or '1' */
char getdrive()
{
char drive;
printf("\nEnter drive designation ");
do
{
drive = getchar();
if( (drive == 'A') || (drive == 'B') )
drive -= 'A';
else if( (drive == 'a') || (drive == 'b') )
drive -= 'a';
else if( (drive == '0') || (drive == '1') )
drive -= '0';
else
{
putchar('\b');
putchar(' ');
putchar('\b');
}
}
while(drive != 0 && drive != 1);
return(drive);
} /*getdrive*/
LISTING 4
/* RECAL.C */
/* program for testing routines recal() and senseintstat() */
#include bdscio.h
#include cdisk.h
main()
{
char drive;
int temp;
while(TRUE) {
drive = getdrive();
printf("\n drive = %u \n",drive);
recal(drive);
}/*while*/
}/*main*/
senseintstat(bytes)
char bytes[];
/* reads and returns the 8272 status register 0 */
/* and the current cylinder number */
{
cmdstat(); /* wait till ready for command byte */
outp(fdcdata,c_rsts); /* send command byte */
resultstat(); /* wait till ready for result byte */
bytes[0] = inp(fdcdata); /* get status register 0 */
st0(bytes[0]); /* print Status Register 0 */
resultstat(); /* wait till ready for result byte */
bytes[1] = inp(fdcdata); /* get cylinder number */
printf("\ncylinder = %u\n",bytes[1]);
}/* senseint stat */
int recal(drive)
char drive;
/* move the head to cylinder zero, return TRUE if successful */
/* print error message if unsuccessful */
{
int k; /* try counter */
char bytes[8]; /* array to hold results */
for(k=0; k < 3; K++)
{
cmdstat(); /* wait till ready for command byte */
outp(fdcdata,c_reca); /* send command byte */
cmdstat(); /* wait till ready for command byte */
outp(fdcdata,drive); /* end of 8272 recalibrate command phase*/
intstat(); /* wait till execution phase complete */
senseintstat(bytes); /* check if recal ok */
/* check for satisfactory completion and at cylinder 0 */
if( ((bytes[0] & no_err) == 0x00 ) && (bytes[1] == 0)) return(TRUE);
}/* or */
printf("\nRecal error drive %c ",drive+'A');
if ( (bytes[0] & ds_err) != drive ) printf("incorrect drive select\n");
if ( (bytes[0] & nr_err) != 0 ) printf("not ready\n");
if ( (bytes[0] & eq_err) != 0 ) printf("equipment error\n");
return(FALSE);
}/* recal */
LISTING 5
/* CDISK.H */
#define TRUE 1
#define FALSE 0
/* the following sets the conditional compile in setdma() so that the */
/* tpa(transient program area is in page 0 for CPM 2.2 and page 1 for */
/* CPM 3. If you are using with CPM 2.2 or a non-banked CPM 3 set to */
/* FALSE */
#define CPM3 TRUE
/* DISK1 PORTS */
#define fdport 0xc0 /* base address of disk controller */
#define fdcstat fdport /* 8272 status port */
#define fdcdata fdport + 1 /* 8272 command and results data port */
#define fdma fdport + 2 /* Disk1 DMA port (write) */
#define ints fdport + 2 /* Disk1 interrupt status port (read) */
/* 8272 COMMAND CODES */
#define c_rtk 0x02 /* read a track */
#define c_spec 0x03 /* specify */
#define c_dsts 0x04 /* sense drive status */
#define c_wrat 0x05 /* write data */
#define c_rdat 0x06 /* read data */
#define c_reca 0x07 /* recalibrate */
#define c_rsts 0x08 /* sense interrupt status */
#define c_rdid 0x0A /* read ID */
#define c_form 0x0D /* format */
#define c_seek 0x0F /* seek */
8272 ERROR MASKS
#define ds_err 0x03 /* incorrect disk select */
#define nr_err 0x08 /* not ready error */
#define eq_err 0x10 /* equipment error */
#define no_err 0xc0 /* no error */
/* GLOBAL VARIABLES */
/* globals have the form variable[drive] where drive is 0..3 */
char mt[4]; /* two side operation = 1, one side = 0 */
char mfm[4]; /* double density = 1, single density = 0 */
char sk[4]; /* skip (not used) always 0 */
char bps[4]; /* bytes per sector 0,1,2,3 for Godbout format */
char eot[4]; /* final sector number of track */
char gpl[4]; /* gap length */
char dtl[4]; /* data length */
int x,y; /* cursor coordinates used by iolib.c */
LISTING 6
/* Getresult() routine reads the results from a read,write,format or */
/* readid command returns TRUE for a good read or write */
int getresult(bytes)
char bytes[];
{
int k; /* byte counter */
for (k = 0 ; k < 7 ; ) {
resultstat(); /* wait till ready for result byte */
bytes[k++] = inp(fdcdata); /* read result byte */
}
return((bytes[1] == 0x80)); /* return TRUE if end of cylinder */
}/* getresult */
LISTING 7
/* DENSITY.C */
/* program to return number of sides, density and format of a disk */
#include bdscio.h
#include cdisk.h
main(argc,argv)
char **argv;
{
char cyl,hds,drive;
char bytes[8];
int i;
printf("\ndensity version 1.3\n");
drive = getdrive(); /* request drive */
hds= 0; /* select head 0 */
cyl = 2; /* select cylinder 2 */
dseek(drive,cyl); /* position head */
getmt(drive); /* find number of sides */
readid(drive,hds,bytes); /* find density and format */
printf("\ndrive %c is ",(drive+'A'));
if (mt[drive]) printf("Double Sided, ");
else printf("Single sided, ");
switch (n[drive]) {
case 0 : printf("Single density with 128 Byte sectors\n");
break;
case 1 : printf("Double density with 256 Byte sectors\n");
break;
case 2 : printf("Double density with 512 Byte sectors\n");
break;
case 3 : printf("Double density with 1024 Byte sectors\n");
} /* switch */
} /* density */
LISTING 8
/* segment of setparam() code */
else /* double density */
switch (n[drive]) {
case 1 : gpl[drive] = 0x0e; /* gap length */
eot[drive] = 0x1a; /* last sector on track */
dtl[drive] = 0xff; /* no meaning in dd */
break;
case 2 : gpl[drive] = 0x1b; /* gap length */
eot[drive] = 0x0f; /* last sector on track */
dtl[drive] = 0xff; /* no meaning in dd */
break;
case 3 : gpl[drive] = 0x