static char rcsid[] = "$Header: header.c,v 10.1 86/07/21 14:56:20 bog Exp $";

/************************************************************************\
**									**
**				Copyright 1986				**
**			VALID LOGIC SYSTEMS INCORPORATED		**
**									**
**	This listing contains confidential proprietary information	**
**	which is not to be disclosed to unauthorized persons without	**
**	written consent of an officer of Valid Logic Systems 		**
**	Incoroporated.							**
**									**
**	The copyright notice appearing above is included to provide	**
**	statutory protection in the event of unauthorized or 		**
**	unintentional public disclosure.				**
**									**
\************************************************************************/

/*
 * %W% %Y% %Q% %G%
 * $Header: rim.c,v 2.1 86/07/21 14:56:57 bog Exp $
 * $Log:	rim.c,v $
 * Revision 2.1  86/07/21  14:56:57  bog
 * Working Standalone MKFS using disk labels (bog).
 * 
 * Revision 2.0  86/06/24  13:46:38  bog
 * Checkin before debugging starts: code is in place but not running (bog)
 * 
 * Revision 800.0  85/10/22  12:55:30  root
 * Initial VALID checkin for 8.0 release
 * 
 * Revision 1.2  85/08/06  12:12:20  ed
 * Everything works, but needs to be cleaned up
 * 
 * Revision 1.1  85/06/21  15:34:24  ed
 * Got 'Boot' to come out on te screen
 * 
 * Revision 1.1  85/03/12  16:26:20  sbs
 * Initial revision
 * 
 *
 * Copyright (C) 1985 Valid Logic Systems, Inc.
 */

/****************************************************************************

                          Copyright  1983

               VALID  LOGIC  SYSTEMS  INCORPORATED

This listing contains confidential proprietary information which is not to
be disclosed to unauthorized persons without written consent of an officer
of Valid Logic Systems Incorporated.

The copyright notice appearing above is included to provide statutory
protection in the event of unauthorized or unintentional public disclosure.

*****************************************************************************/

#include "../h/param.h"
#include "../h/fs.h"
#include "../h/inode.h"
#include "../s32/vectors.h"
#include "../s32/cpu.h"
#include "../s32/setjmp.h"
#include "saio.h"
#include "sas32.h"
#include "../h/dk_types.h"
#include "rfreg.h"

u_short	rf45unit;		/* current rf45 unit */
u_short	rf44unit;		/* current rf44 unit */
u_long	pwrflag;
u_long rddebug = 0;
jmp_buf rf_fault;
int *nofault;
struct rf_scp	saverf_scp;	/* rf45 scp ptr */
struct rim_dkinfo *rf45dtable[NUMRFD];	/* rf45 disk table */
struct rim_dkinfo *rf44dtable[NUMRFD];	/* rf44 disk table */
struct rf_controller *controller; /* Generic controller */

char priam3450msg[] = "P3450";
char priam7050msg[] = "P7050";
char priam806msg[] = "P806";

/*
 * Note that the index of the last entry must gibe with
 * MAXDK in rfreg.h.
 */
struct rim_dkinfo dkinfo[] = {
  {
	PRIAM3450, 0, 5, 23, 525, 10, 512, 58880, 1, 9, 0xE, 2, 8, priam3450msg,
	/* Length,	Start Cyl */
/* 0 */	{ 525 * 23*5,	  0 },		/* All cylinders */
/* 1 */	{ 512 * 23*5,	  3 },		/* All usable cylinders */
/* 2 */	{   0,		  0 },
/* 3 */	{   0,		  0 },
/* 4 */	{   1 * 23*5,	  0 },		/* Disk diagnostic area */
/* 5 */	{   2 * 23*5,	  1 },		/* Primary boot-area */
/* 6 */	{ 169 * 23*5,	  3 },		/* rootdev */
/* 7 */	{   0,		  0 },
/* 8 */	{ 174 * 23*5,	172 },		/* LARGE swap */
/* 9 */	{  72 * 23*5,	172 },		/* small swap */
/* a */	{ 271 * 23*5,	244 },		/* LARGE /u0: goes with small swap */
/* b */	{ 169 * 23*5,	346 },		/* small /u0: goes with LARGE swap */
/* c */	{   0,		  0 },
/* d */	{   0,		  0 },
/* e */	{   0,		  0 },
/* f */	{   0,		  0 }
  },
  {
	/* Length,	Start Cyl */
	PRIAM7050,0, 5, 23, 1049, 40, 512, 58880, 1, 9, 0xE, 2, 8, priam7050msg,
/* 0 */	{ 1049 * 23*5,	  0 },		/* All cylinders */
/* 1 */	{ 1006 * 23*5,	  3 },		/* All usable cylinders */
/* 2 */	{    0,		  0 },
/* 3 */	{    0,	 	  0 },		
/* 4 */	{    1 * 23*5,	  0 },		/* Disk diagnostic area */
/* 5 */	{    2 * 23*5,	  1 },		/* Primary and Alternate boot-area */
/* 6 */	{  169 * 23*5,	  3 },		/* rootdev */
/* 7 */	{    0,		  0 },
/* 8 */	{  213 * 23*5,	172 },		/* LARGE swap */
/* 9 */	{   72 * 23*5,	172 },		/* small swap */
/* a */	{  765 * 23*5,	244 },		/* LARGE /u0: goes with small swap */
/* b */	{  624 * 23*5,	385 },		/* small /u0: goes with LARGE swap */
/* c */	{    0,		  0 },
/* d */	{  488 * 23*5,	521 },		/* tiny /u0: goes with HUGE swap */
/* e */	{  349 * 23*5,	172 },		/* HUGE swap */
/* f */	{    0,		  0 }
  },
  {
	/* Length,	Start Cyl */
	PRIAM806, 0, 11, 32, 850, 40, 512, 180224, 1, 0, 0x4, 8, 0, priam806msg,
/* 0 */	{ 850 * 32*11,	  0 },		/* All cylinders */
/* 1 */	{ 807 * 32*11,	  3 },		/* All usable cylinders */
/* 2 */	{   0,		  0 },
/* 3 */	{   1 * 32*11,	  2 },		/* Alternate boot area */
/* 4 */	{   1 * 32*11,	  0 },		/* Disk diagnostic area */
/* 5 */	{   1 * 32*11,	  1 },		/* Primary boot area */
/* 6 */	{  94 * 32*11,	  3 },		/* root */
/* 7 */	{  80 * 32*11,	134 },		/* /mnt:  tiny single-user rootdev */
/* 8 */	{   0,		  0 },
/* 9 */	{ 117 * 32*11,	 97 },		/* swap */
/* a */	{   0,		  0 },
/* b */	{ 596 * 32*11,	214 },		/* b */
/* c */	{   0,		  0 },
/* d */	{   0,		  0 },
/* e */	{   0,		  0 },
/* f */	{   0,		  0 }
  },
  {
	0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, (char *) 0
  },
};


/*
 * Rimfire 44/45 status messages
 */

char rfcstatustbl[] = "\20\7RFC\10RFE";

char rfdstatustbl[] = "\20\1N\2BE\3IC\4IP\5S1\6S2\7B\10C";

char rf45tstatustbl[] = "\20\2P\3FB\4R\5EOT\6LP\7OL\10FM";

/*
 * Note that OEA and DRA are not defined in the R44 manual.
 * They are included to be back-compat with GRM/1.7.
 */
char rf44tstatustbl[] = "\20\1OEA\2DRA\3W\4FM\5EOT\6C\7E\10R";

char rfmcstatus[] = "\20\1F\2BIE\3D\4EM\5P\6O\7C\10EX0\11RST\14BM\16ND\17IC\20EX1";

struct rf_controller rf45  = {
				0,
				&rf45unit,
				rf45dtable,
				"R45",
	(struct rf_device *) 	0xAC, 
	(struct rf_scp *) 	0x3FE6,
	(struct rf_scb *)	0xC80,
	(struct rf_ccb *)	0xC90,
	(union  rf_pb *)	0xCA0,
	(struct rf_dp *)	0xCA0,
	(struct rf_tp *)	0xD80,
	(u_char *)		0xCC0,
	(struct rf_rb *)	0x0,
	(struct rf_rb *)	0x0,
};

struct rf_controller rf44  = {
				1,
				&rf44unit,
				rf44dtable,
				"R44",
	(struct rf_device *) 	0xAC,
	(struct rf_scp *) 	0x3FE6,
	(struct rf_scb *)	0xC80,
	(struct rf_ccb *)	0xC90,
	(union  rf_pb *)	0xCA0,
	(struct rf_dp *)	0xCA0,
	(struct rf_tp *)	0xD80,
	(u_char *)		0xCC0,
	(struct rf_rb *)	0xDA0,
	(struct rf_rb *)	0xDB0,
};

/*
 * Open Rimfire disk -- should be called at spl > 3
 */

rfopen (io)
register struct iob *io;
{
	register off = io->i_boff;
	register struct rf_controller *rf;
	register struct rim_dkinfo *rfdtable;
	static char rfopened = 0;

	if (rddebug)printf ("rimopen()\n");
	if (rfopened) return 1;
	rf = controller = &rf44;	/* Assume RF44 for now */
	rfinit();			/* Do RIMFIRE initializations */
	rf = controller;
	grabrfgate (controller);	/* Get the gate */
	rf->rf_ccb->ccb_gate = CCBGATE_OPEN;	/* Force it open */
	rf->rf_ccb->ccb_ccw  = CCBCCW_NORMAL;
	rf->rf_ccb->ccb_00   = 0;
	*rf -> rf_unit = io->i_unit;		/* Set the unit number */
	/* Reset drive */
	rfdcmd (controller, DPCMD_RESET, 0, 0, 0, 0, 0, 0);
	spinup(io);		/* Spin up all the drives */
	rfopened ++;
	return 1;
}

rdopen (io)
register struct iob *io;
{
	register off = io->i_boff;
	register struct rf_controller *rf;
	register struct rim_dkinfo *rfdtable;
	static char badmsg[] = "Rim: bad unit";

	if (!rfopen (io))
		return 1;
		
	/*
	 *	Figure out the partition number.
	 *	If off < 0, pretend it is an absolute offset
	 */
	rf = controller;
	*rf -> rf_unit = io->i_unit;		/* Set the unit number */
	rfdtable = rf->rf_dtable[*rf->rf_unit];	/* Optimize pointer ops */
	if (off < 0) {				/* Absolute offset */
		io->i_boff = -off;		/* Make it positive */
		if (io->i_boff>=(rfdtable->numcyl*	/* Figure out if it */
		    (rfdtable->bpc/rfdtable->bps)))	/* beyond the end of */
			_stop(badmsg);			/* the disk */
	} else if (off >= DK_NSIZES)		/* Must be a partition num */
		_stop (badmsg);			/* Too big */
	else
	/* Replace with the block offset of the start of the partition */
		io->i_boff = rfdtable->sizes[io->i_boff].sz_cyloff *
			(rfdtable->bpc / rfdtable->bps);
	return 0;
}


/*
 * rdstrategy -- read/write disk; use the struct iob
 */
rdstrategy(io)
register struct iob *io;
{
	u_int	rw = io -> i_flgs & F_RDDATA;	/* read/write flag */
	register struct rf_controller *rf = controller;
	register struct rim_dkinfo *rfdtable;
	register bno = io->i_bn;
	register u_long	startaddr = (u_long) io -> i_ma;
	register u_long	records;
	register u_char	page;
	register u_short cylinder;
	register u_char head;
	register u_short sector;


	orStatusReg(V_GREENLED);	/* Turn on LED during disk op */
	*rf -> rf_unit = io -> i_unit;	/* Set up the unit number */
	rfdtable = rf->rf_dtable[*rf->rf_unit];	/* Optimize pointer ops */
	if (rddebug)printf ("rimstrategy(%d, %d, %d, %d)\n", bno,
	    rfdtable->bpc/rfdtable->bps, rfdtable->spt, rfdtable->bps);
	/*
	 *	Figure out cylinder, head, starting sector, and number of
	 *	records for this operation. This is figured out using the
	 *	paramters for the disk being transferred from in 'rfdtable'.
	 *
	 *	{Blocks per cylinder} = Bytes per cylinder} / 
	 *		{Bytes per sector}
	 *
	 *	cylinder = {block number} / {Blocks per cylinder}
	 *
	 *	head = {block number} % {Blocks per cylinder} /
	 *		{Sectors per track}
	 *
	 *	{starting sector} = ({block number} % {Sectors per track}) + 1
	 *
	 *	{# records} = ({transfer count} + {Bytes per sector} - 1)
	 *		/ {Bytes per sector}
	 */
	cylinder = bno / (rfdtable->bpc / rfdtable->bps);
	head = (bno % (rfdtable->bpc / rfdtable->bps))
	    / rfdtable->spt;
	sector = (bno % rfdtable->spt) + 1;
	records = (io -> i_cc + rfdtable->bps - 1) / rfdtable->bps;
	page = rfpage(startaddr);	/* Figure out which 20 bit page */
	if (rddebug)
		printf("%s cyl %d,head %d,sect %d,cnt %d,addr %x,page %d\n",
		rw?"Reading":"Writing", cylinder, head, sector, records,
		startaddr, page);
	/*
	 *	Do the operation and wait for completion 
	 */
	if (rw)
		rfdcmd(controller, DPCMD_READ, page, head, cylinder, 
	  	  sector, records, startaddr);
	else
		rfdcmd(controller, DPCMD_WRITE, page, head, cylinder, 
	  	  sector, records, startaddr);
	xorStatusReg(V_GREENLED);	/* Turn off LED after transfer */
	if (rfdstatus (0) > 1)		/* Check for error */
		return -1;		/* Return -1 on error */
	else return io->i_cc;		/* Completed OK, Return count */
}

	
spinup(io)
register struct iob *io;
{
	int	i;
	register struct rf_controller *rf = controller;

	if (rddebug)printf ("spinup()\n");
	for (i = 0; i < NUMRFD; i++)
	{
		*rf -> rf_unit = i;
		rfdcmd (rf, DPCMD_STATUS, rfpage (io->i_ma), 0, 0, 0, 0,
			 io->i_ma);
		if (rf->rf_dp->dp_cst & CST_DONE)
			if (rf->rf_dp->dp_dst & DPDST_NOTRDY)
			{
				rfdcmd (rf, DPCMD_LOAD, rfpage (io->i_ma),
					0, 0, 0, 0, io->i_ma);
				pause();
			}
	}
}

/*
 *  Pause while spinning disks up . . . we need to do this to prevent
 *  multiple spin ups from drawing too much current!
 */

#define WAITTIME	71430
pause()
{
	int 	i, j=25;

	if (rddebug)printf ("pause()\n");
	while (j--)
	{
		for (i=0; i++ < WAITTIME;)
			;
	}
}

#ifndef	SA_ADVANCED
rdioctl ()
{
	if (rddebug)printf ("rimioctl()\n");
}

#else	SA_ADVANCED

rdioctl(io, cmd, opt)
register struct iob	*io;
register int		cmd, opt;
{

	if (rddebug)
		printf("rddioctl(0x%x, 0x%x, 0x%x)\n", io, cmd, opt);

	switch (cmd)
	{
		default:
			printf("Command 0x%x not implemented\n",cmd);
			break;
		case SAIOGPARM:	/* get the disk's parameters */
		{
			register model_t	*mp = (model_t *) opt;
			register int		i;
			register struct rim_dkinfo *rdi =
				controller->rf_dtable[io->i_unit];

			if (rddebug) printf("Cmd SAIOGPARM\n");
			mp->m_nCyl = rdi->numcyl;
			mp->m_nHead = rdi->numhead;
			mp->m_nSectors = rdi->spt;
			mp->m_aCyl = rdi->numalt;
			mp->m_Interleave = 3;
			mp->m_Gap1 = mp->m_Gap2 = mp->m_Grouping = 
			mp->m_Skew = mp->m_Cache = mp->m_ZeroLat = 
			mp->m_DiskType = mp->m_Gap3 = mp->m_BufStep = 
			mp->m_StepWidth = mp->m_StepInt = mp->m_HeadLoad =
			mp->m_SeekTime = mp->m_RedWrite = mp->m_Precomp = 0;
			for (i=0; i < DK_NSIZES; i++) {
				mp->m_PartSizes[i].sz_nblk =
					rdi->sizes[i].sz_nblk;
				mp->m_PartSizes[i].sz_cyloff =
					rdi->sizes[i].sz_cyloff;
			}
			break;
		}
#ifdef	LATER
		case SAIOSPARM:	/* set the disk's parameters */
		{
			register model_t	*mp = (model_t *) opt;
			register int		i;

			if (idebug) printf("Cmd SAIOSPARM\n");
			id->id_ncyl = mp->m_nCyl;
			id->id_nhead = mp->m_nHead;
			id->id_nsec = mp->m_nSectors;
			id->id_nsecpercyl = id->id_nsec * id->id_nhead;
			id->id_acyl = mp->m_aCyl;
			id->id_gap1 = mp->m_Gap1;
			id->id_gap2 = mp->m_Gap2;
			id->id_intrlv = mp->m_Interleave;
			id->id_group = mp->m_Grouping;
			id->id_skew = mp->m_Skew;
			id->id_cache = mp->m_Cache;
			id->id_zerolatency = mp->m_ZeroLat;
			id->id_drivedesc = mp->m_DiskType;
			id->id_gap3 = mp->m_Gap3;
			id->id_bufstep;	mp->m_BufStep;
			id->id_stepwidth = mp->m_StepWidth;
			id->id_stepinter = mp->m_StepInt;
			id->id_headloadtime = mp->m_HeadLoad;
			id->id_seektime = mp->m_SeekTime;
			id->id_redwrite = mp->m_RedWrite;
			id->id_precomp = mp->m_Precomp;
			for (i=0; i < DK_NSIZES; i++) {
				id->id_sizes[i].sz_nblk =
					mp->m_PartSizes[i].sz_nblk;
				id->id_sizes[i].sz_cyloff =
					mp->m_PartSizes[i].sz_cyloff;
			}
			return (!iscmd(ic,id->id_unit,IPCMD_INIT,0,0,0,0,is_uib));
		}
		case SAIORLAB:	/* read the disk label */
			if (idebug) printf("Cmd SAIORLAB\n");
			return (!idreadlabel(ic, id->id_unit, opt));
		case SAIOWLAB:	/* write the disk label */
			if (idebug) printf("Cmd SAIOWLAB\n");
			return (!idwritelabel(ic, id->id_unit, opt));
		case SAIOFMTTRK:	/* format a specified track */
			if (idebug) printf("Cmd SAIOFMTTRK\n");
			return (!idfmttrk(ic, id->id_unit, opt));
		case SAIOFMTDSK:	/* format the whole disk */
			if (idebug) printf("Cmd SAIOFMTDISK\n");
			return (!idfmtdsk(ic, id->id_unit, opt));
		case SAIOMAP:	/* map spcified bad track */
			if (idebug) printf("Cmd SAIOMAP\n");
			return (!idmaptrk(ic, id->id_unit, opt));
		case SAIOMAPLST:	/* map out bad tracks in list */
			if (idebug) printf("Cmd SAIOMAPLST\n");
			return (!idmaplst(ic, id->id_unit, opt));
#endif	LATER
		case SAIODEBUG:	/* toggle debug flag */
		{
			if (rddebug) printf("Cmd SAIODEBUG\n");
			rddebug = !rddebug;
			break;
		}
	}
	return 0;
}
#endif	SA_ADVANCED
/*

/*
 * rfinit -- Initialize a Rimfire controller
 */

rfinit()
{
	register struct rf_controller *rf = controller;
	u_short unit;
	register value;

	if (rddebug) printf ("rfinit()\n");
	*rf->rf_unit = 0;
	saverf_scp = *rf->rf_scp;	/* Save the sys config ptr */

	/*
	 * Set up a new sys config ptr
	 */
	rf->rf_scp->scp_bus  = SCPBUS_16;
	rfsetaddr(rf->rf_scp->scp_addr, rf->rf_scb);

	rf->rf_scb->scb_03   = 0x03;
	rfsetaddr(rf->rf_scb->scb_addr, rf->rf_ccb);

	rf->rf_ccb->ccb_gate = CCBGATE_CLOSED;
	rf->rf_ccb->ccb_ccw  = CCBCCW_NORMAL;
	rf->rf_ccb->ccb_00   = 0;
	rfsetaddr(rf->rf_ccb->ccb_addr, rf->rf_pb);

	/*
	 * Issue the Rimfire attention
	 */
	issuerfattn(rf);
	waitrfgate(rf);


	/*
	 * Restore the saved system config ptr
	 */
	*rf->rf_scp = saverf_scp;

	/*
	 * Now configure the puppy
	 */
	for (unit = 0; unit < NUMRFD; unit++) {
		*rf->rf_unit = unit;
		(rf->rf_dtable)[unit] = &(dkinfo[MAXDK]);
	}
	*rf->rf_unit = 0;
	rfconfig(rf);				/* For the RF */
/* 
** Now it is safe to read the controller I.D.:
** What flavor of rimfire do we have?
*/
	switch (value = rf_what_controller(rf)) {
		case RIM44_ID: 
		    break;
		case RIM45A_ID:
		case RIM45_ID: 
		    rf->rf_cst = 0;
		    rf->rf_unit = &rf45unit;
		    rf->rf_dtable = rf45dtable;
		    rf->rf_name = "RF45";
		    break;
		default:
		    printf("..Unidentified controller 0x%x\n", value);
		    return 1;
	}

	rfdtype(rf);				/* Get the disk types */
	rfconfig(rf);				/* For the disks */
	*rf->rf_unit = 0;

#ifdef LATER
	if (rf->rf_cst)
		rftrst();
#endif
	if (rddebug)
		printf ("exiting rfinit\n");
}

/*
 * rfdocmd -- Do a generic Rimfire command
 */
rfdocmd(rf)
	register struct rf_controller	*rf;
{
	if (rddebug)printf ("rfdocmd()\n");
	if (!grabrfgate(rf))
		return(0);
	issuerfattn(rf);
	waitrfgate(rf);
}

/*
 * grabrfgate -- Grab the Rimfire gate.  Abort if someone else has closed
 * 		 it and print a message.
 */
grabrfgate(rf)
	register struct rf_controller	*rf;
{
	register struct rf_ccb *ccb =	rf->rf_ccb; 
	
	if (rddebug) printf ("grabrfgate()\n");
	if (ccb->ccb_gate == CCBGATE_CLOSED) {
		printf("Rimfire gate closed\n");
		return(0);
	} else 
		ccb->ccb_gate = CCBGATE_CLOSED;
	return(1);
}

/*
 * waitrfgate -- Wait for the Rimfire gate to open
 */
waitrfgate(rf)
	register struct rf_controller	*rf;
{
	register struct rf_ccb *ccb = 	rf->rf_ccb;
	register i = 65535000;

	if (rddebug)printf("waitrfgate()\n");
	while (i-- && ccb->ccb_gate == CCBGATE_CLOSED);
	if (ccb->ccb_gate == CCBGATE_CLOSED)
		_stop("waitrfgate: Rimfire gate closed\n");
}

/*
 * issuerfattn -- Issue a Rimfire attention.
 *			NEED TO HANDLE BUS ERRORS!!!!
 */
issuerfattn(rf)
	register struct rf_controller 	*rf;
{
	register char	*rfioaddr;
	register int	i;
	extern char 	*makeioaddr();
	extern u_long	rf_ign;
	register u_long attenaddr = (u_long)&rf->rf_device->rf_atten;
	register int *savefault;

	rfioaddr = makeioaddr(attenaddr);
	if (rddebug)printf("issuerfattn(%x, %x)\n", attenaddr, rfioaddr);

	savefault = nofault;
	nofault = rf_fault;
	if (!setjmp (nofault))
		*rfioaddr = 0;
	else {
		/*
	 	 * Open the Rimfire gate as if the attn had succeeded
		 */
		rf->rf_ccb->ccb_gate = CCBGATE_OPEN;
		return;
	}
	nofault = savefault;	
	/*
	 * Check if pwrflag is equal to the mystic number 0x636D6773
	 */
	if (pwrflag == 0x636D6773)
		return;
	else {
		pwrflag = 0x636D6773;
		/*
		 * Approx. 32 second wait here for disk spin up
		printf("\r\nPower up loop...");
		pause(0x1);
		 */
	}
}

/*
 * rfdcmd -- execute one disk command
 */
rfdcmd(rf, command, page, head, cylinder, sector, records, address)
	register struct rf_controller	*rf;
	u_short		command;
	u_char		page;
	u_char		head;
	u_short		cylinder;
	u_short		sector;
	u_short 	records;
	u_long		address;
{
	register struct rf_dp *rf_dpb	= rf->rf_dp;
	register u_short control;

	if (rddebug)printf ("rfdcmd()\n");
	rfsetaddr(rf->rf_ccb->ccb_addr, rf->rf_dp);
	rf_dpb->dp_cmd		= command;
	rf_dpb->dp_page		= page;
	rf_dpb->dp_head		= head;
	control = 
	(*rf->rf_unit & CTL_DS) | CTL_16BIT | CTL_INTERLEAVE;
	rf_dpb->dp_ctl		= control;
	rf_dpb->dp_cyl		= cylinder;
	rf_dpb->dp_sec		= sector;
	rf_dpb->dp_nsec		= records;
	rf_dpb->dp_link		= 0;
	rfsetaddr(rf_dpb->dp_addr, address);

	rfdocmd(rf);
}


/*
 * rfdtype -- figures out the disk type of all units
 */
rfdtype(rf)
	register struct rf_controller *rf;
{
	register u_short modelnum;
	register struct rim_dkinfo *dkptr;
	register struct rim_dkinfo **rfdtable = rf->rf_dtable; 

	if (rddebug)printf ("rfdtype()\n");
	for (*rf->rf_unit = 0; *rf->rf_unit < NUMRFD; (*rf->rf_unit)++) {
		*(u_long *)rf->rf_dr = 0;
		rfdcmd(rf, DPCMD_INTERR, 0, 0, 0, 1, 0x300, rf->rf_dr);
		modelnum = * (u_long *) rf->rf_dr;
		for (dkptr = dkinfo; dkptr->name; dkptr++) {
			if (modelnum ==  dkptr->modelnum) {
				rfdtable[*rf->rf_unit] = dkptr;
				goto next;
			}
		}
		rfdtable[*rf->rf_unit] = dkptr;
	next:
		;
	}
}

/*
 * rfconfig -- Configure a Rimfire Controller
 */
rfconfig(rf)
	struct rf_controller	*rf;
{
	register struct rf_dr *dr = (struct rf_dr *) rf->rf_dr;
	register short unit;
	
	if (rddebug)printf ("rfconfig()\n");
	/*
	 * Loop through the dtable comparing against known disks in
	 * the disk table.  When we match, configure the drive.
	 */
#ifdef NOTYET
	/*
	 * Put in general stuff for rf44
	 */
#else NOTYET
	for (unit = 0; unit < NUMRFD; unit++) {
		register struct rim_dkinfo *dkptr = (rf->rf_dtable)[unit];

		dr->dr_type = dkptr->type;
		dr->dr_nhead = dkptr->numhead - 1;
		dr->dr_nsec = dkptr->spt;
		dr->dr_ncyl = dkptr->numcyl - 1;
		dr->dr_secsize = dkptr->bps;
		dr++;
	}
	rfdcmd(rf, DPCMD_CONFIG, 0, 0, 0, 1, 0, rf->rf_dr);
#endif NOTYET
		
}

/*
 * rfdstatus -- print out Rimfire disk status
 */
rfdstatus(print)
	int print;
{
	register struct rf_dp	*rf_dp = controller->rf_dp;
	register u_char	i;
	register short	j;
	register u_char k;
	register u_char   cst = rf_dp->dp_cst;
	register u_char   dst = rf_dp->dp_dst;

	if (rddebug)printf ("rfdstatus()\n");
	k = cst & CST_ERROR;
	if (k) print = 1;

	if (print) 
		printf("Disk status = %b %b", cst, rfcstatustbl, dst,
			rfdstatustbl);

	if (print && k)
		printf(" ERR %x", k);
	if (print) putchar ('\n');

	return(k);
}

rf_what_controller(rf)
register struct rf_controller *rf;
{
    rfdcmd(rf, DPCMD_NOPID, 0, 0, 0, 0, 0, 0);
    return (long)(rf->rf_dp->dp_dst);
}
