#ifdef CD68K

/*
	@(#)rf.c	1.3	(8/17/84 13:09:47)
*/
#include <sys/config.h>
#include <sys/mmu.h>
#include "standalone.h"
#include "rf50.h"

/*
#define	DEBUG	1
*/

struct rf50_iopb rf50_iopb;
struct rf50_uinit rf50uib;

#define RF_TIMEOUT	0xffff
#define UNINITIALIZED	0
#define INITIALIZED	1

char rf_initstatus = UNINITIALIZED;	/* Device already opened? */

rferror()
{   register struct rf50_iopb *ip = &rf50_iopb;

    printf("\nrf: error 0x%x on dr:%d cyl:%d hd:%d sec:%d (status=0x%x)\n",
	   ip->rfsc_error,
	   ip->rfsc_unit,
	   ip->rfsc_cylinder,
	   ip->rfsc_head,
	   ip->rfsc_sector,
	   ip->rfsc_status);
}

rfinit(dp)
register DIOB *dp;
{
    register int i, drive;
    register struct rfo1_iopb *cip = (struct rfo1_iopb *) &rf50_iopb; 
    register struct rf50_uinit *uip = &rf50uib;

    drive = dp->diob_drv;
    if (iocheck(RFSMDADDR, -1) < 0)
    {
	printf("rf: controller does not exist!\n");
	return(1);
    }
    RFSMDADDR->rf50r1 = 0xff;		/* Reset Controller */
    i = 0x10000;
    while (i-- > 0)			/* Wait for RESET to settle down */
	;

    /* Build unit initialization block */
    uip->rfi_interl = dp->diob_dp1;         	/* +1 interleave factor */
    uip->rfi_type = dp->diob_dp2;		/* +0 drive type */
    uip->rfi_hds1 = 0;				/* +3 Heads vol 1*/
    uip->rfi_hds0 = dp->diob_dtc;       	/* +2 Heads vol 0*/
    uip->rfi_spt  = dp->diob_dbt;         	/* +5,4 sectors/track */
    uip->rfi_cpd  = dp->diob_dcd;       	/* +7,6 cyl/drive */
    uip->rfi_bps  = 512;			/* +9 bytes per sector */
    uip->rfi_res1 = 0;				/* +11 Reserved R1 */
    uip->rfi_res0 = 0;				/* +10 Reserved R0 */
    uip->rfi_res3 = 0;				/* +13 Reserved R3 */
    uip->rfi_res2 = 0;				/* +12 Reserved R2 */

    if (rfcmd(CONFIG, vtop(&rf50uib), drive,0,0,0,0))
	return (1);

#ifdef NOTDEF
    /* Build option parameter block */
    cip->rfo1_cmd    = COPT1;		/* Option One Command */
    cip->rfo1_ccntl  = CMDCTLNM;	/* normal command control */
    cip->rfo1_opcntl = STATSC_DI|STATCI_DI|PBPA_DIR|SYSGT_DI|
				DMACNT_ST|RTRCNT_ST;
    cip->rfo1_rtcnt  = 10;		/* Retry count for hardware */
    cip->rfo1_dmacnt = 512;		/* DMA count for hogging bus */
    cip->rfo1_gate = NOTFLAGGED;	/* Command gate */
    cip->rfo1_error = OK;		/* Error return */

    if (rfcmd(COPT1, 0, 0,0,0,0,0))
	return (1);
#endif

    if (rfcmd(CREZERO, 0, drive,0,0,0,0))
	return (1);

    rf_initstatus = INITIALIZED;	/* controller initialized */
    return (0);
}

rfio(dp)
register DIOB *dp;
{
    register int i, spt, spc, ablock;
    register int head, cylinder, sector;

    if (rf_initstatus == UNINITIALIZED)
	if (rfinit(dp))
		return (1);

    spt = dp->diob_dbt;
    spc = spt * dp->diob_dtc;
    ablock = dp->diob_fsb + dp->diob_fdb;
    head = (ablock % spc) / spt;
    cylinder = ablock / spc;
    sector = (ablock % spt) + 1;

    i = rfcmd(CREAD, vtop(dp->diob_buf), dp->diob_drv, head, cylinder, sector, dp->diob_nblks);

    return (0);
}

rfcmd(cmd, dmaddr, unit, head, cylinder, sector, seccnt)
{
    register struct rf50_iopb *ip;
    register int i;

#ifdef DEBUG
printf("rfcmd: cmd=%x, ",cmd);
#endif DEBUG
    ip = (struct rf50_iopb *) &rf50_iopb;
    ip->rfsc_gate = NOTFLAGGED;
    ip->rfsc_error = OK;
    if (cmd != COPT1)
    {
	ip->rfsc_cmd = cmd;
	ip->rfsc_unit = unit;
	ip->rfsc_head = head;
	ip->rfsc_ccntl = 0;
	ip->rfsc_diskcntl = 0;
	ip->rfsc_cylinder = cylinder;
	ip->rfsc_sector = sector;
	ip->rfsc_records = seccnt & 0xffff;
        ip->rfsc_lmem = dmaddr & 0xffff;
	ip->rfsc_hmem = (dmaddr >> 16) & 0x00ff;
	ip->rfsc_status = 0;
	ip->rfsc_lint =  0;
	ip->rfsc_hint = 0;
	ip->rfsc_res0 = 0;
	ip->rfsc_ehead = 0;
	ip->rfsc_ecyl = 0;
	ip->rfsc_esector = 0;
    }

    rfgo();		/* Actually issue the command (finally!) */

    /* Wait for command to be entered */
    i = 0xffff;
    while (!(ip->rfsc_gate & CMD_BUSY) && i--)
	;
    if (i <= 0) { printf("rf: Timeout - Command not entered)\n"); return (1); }

    /* Wait for command to be completed */
    i = 0xfffff;
    while (!(ip->rfsc_gate & CMD_DONE) && i--)
	;
    if (i <= 0) { printf("rf: Timeout - Command not completed)\n"); return (1);}

    if (ip->rfsc_error)
    {
	rferror();
	return (1);
    }
#ifdef DEBUG
printf("status=0x%x\n", ip->rfsc_status);
#endif DEBUG
    return (0);
}

/* rfgo - This is it, folks, the Real McCoy! */

rfgo()
{
    register struct rf50_iopb *ip;

    /* Point controller at iopb and start it up */
    ip = (struct rf50_iopb *) ((int) ((int)(vtop(&rf50_iopb))) & 0xFFFFFF);
    RFSMDADDR->rf50r4 = (char) ((int)((int)ip & 0xff));
    RFSMDADDR->rf50r5 = (char) ((int)(((int)ip >> 8) & 0xff));
    RFSMDADDR->rf50r6 = (char) ((int)(((int)ip >> 16) & 0xff));
    RFSMDADDR->rf50r7 = 0;
    RFSMDADDR->rf50r0 = GO;		/* *GO* !! */
}

#endif
