root/sys/arch/vax/boot/boot/tmscp.c
/*      $NetBSD: tmscp.c,v 1.9 2017/05/22 16:59:32 ragge Exp $ */
/*
 * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

 /* All bugs are subject to removal without further notice */

#define NRSP 0 /* Kludge */
#define NCMD 0 /* Kludge */

#include <sys/param.h>
#include <sys/disklabel.h>

#include <lib/libsa/stand.h>

#include "../include/pte.h"
#include <dev/mscp/mscp.h>
#include <dev/mscp/mscpreg.h>

#include "vaxstand.h"

static command(int,int);

/*
 * These routines for TMSCP tape standalone boot is very simple,
 * assuming a lots of thing like that we only working at one tape at
 * a time, no separate routines for uba driver etc..
 * This code is directly copied from ra disk driver.
 */

struct ra_softc {
        int udaddr;
        int ubaddr;
        int unit;
};

static volatile struct uda {
        struct  mscp_1ca uda_ca;           /* communications area */
        struct  mscp uda_rsp;     /* response packets */
        struct  mscp uda_cmd;     /* command packets */
} uda;

struct  udadevice {
        short udaip;
        short udasa;
};

static volatile struct uda *ubauda;
static volatile struct udadevice *udacsr;
static struct ra_softc ra_softc;
static int curblock;


tmscpopen(struct open_file *f, int adapt, int ctlr, int unit, int part)
{
        char *msg;
        extern u_int tmsaddr;
        volatile struct ra_softc *ra=&ra_softc;
        volatile u_int *nisse;
        unsigned short johan;
        int i,err;

        curblock = 0;
        if(adapt>nuba) return(EADAPT);
        if(ctlr>nuda) return(ECTLR);
        ra->udaddr=uioaddr[adapt]+tmsaddr;
        ra->ubaddr=(int)ubaaddr[adapt];
        ra->unit=unit;
        udacsr=(void*)ra->udaddr;
        nisse=((u_int *)ubaaddr[adapt]) + 512;
        nisse[494]=PG_V|(((u_int)&uda)>>9);
        nisse[495]=nisse[494]+1;
        ubauda=(void*)0x3dc00+(((u_int)(&uda))&0x1ff);

        /*
         * Init of this tmscp ctlr.
         */
        udacsr->udaip=0; /* Start init */
        while((udacsr->udasa&MP_STEP1) == 0);
        udacsr->udasa=0x8000;
        while((udacsr->udasa&MP_STEP2) == 0);
        johan=(((u_int)ubauda)&0xffff)+8;
        udacsr->udasa=johan;
        while((udacsr->udasa&MP_STEP3) == 0);
        udacsr->udasa=3;
        while((udacsr->udasa&MP_STEP4) == 0);
        udacsr->udasa=0x0001;

        uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref;
        uda.uda_ca.ca_cmddsc=(int)&ubauda->uda_cmd.mscp_cmdref;
        uda.uda_cmd.mscp_un.un_seq.seq_addr = (long *)&uda.uda_ca.ca_cmddsc;
        uda.uda_rsp.mscp_un.un_seq.seq_addr = (long *)&uda.uda_ca.ca_rspdsc;
        uda.uda_cmd.mscp_vcid = 1;
        uda.uda_cmd.mscp_un.un_sccc.sccc_ctlrflags = 0;

        command(M_OP_SETCTLRC, 0);
        uda.uda_cmd.mscp_unit=ra->unit;
        command(M_OP_ONLINE, 0);

        if (part) {
                uda.uda_cmd.mscp_un.un_seq.seq_buffer = part;
                command(M_OP_POS, 0);
                uda.uda_cmd.mscp_un.un_seq.seq_buffer = 0;
        }

        f->f_devdata=(void *)ra;
        return(0);
}

static
command(cmd, arg)
{
        volatile int hej;

        uda.uda_cmd.mscp_opcode = cmd;
        uda.uda_cmd.mscp_modifier = arg;

        uda.uda_cmd.mscp_msglen = MSCP_MSGLEN;
        uda.uda_rsp.mscp_msglen = MSCP_MSGLEN;

        uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT;
        uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT;
        hej = udacsr->udaip;
        while (uda.uda_ca.ca_rspdsc < 0) {
                if (uda.uda_ca.ca_cmdint)
                        uda.uda_ca.ca_cmdint = 0;
        }

}

tmscpstrategy(struct ra_softc *ra, int func, daddr_t dblk, u_int size, char *buf, u_int *rsize)
{
        u_int i,j,pfnum, mapnr, nsize, bn, cn, sn, tn;
        volatile struct udadevice *udadev=(void*)ra->udaddr;
        volatile u_int *ptmapp = (u_int *)ra->ubaddr + 512;
        volatile int hej;

        pfnum=(u_int)buf>>VAX_PGSHIFT;

        for(mapnr=0, nsize=size;(nsize+VAX_NBPG)>0;nsize-=VAX_NBPG)
                ptmapp[mapnr++]=PG_V|pfnum++;

        /*
         * First position tape. Remember where we are.
         */
        if (dblk < curblock) {
                uda.uda_cmd.mscp_seq.seq_bytecount = curblock - dblk;
                command(M_OP_POS, 12); /* 12 == step block backward */
        } else {
                uda.uda_cmd.mscp_seq.seq_bytecount = dblk - curblock;
                command(M_OP_POS, 4); /* 4 == step block forward */
        }
        curblock = size/512 + dblk;

        /*
         * Read in the number of blocks we need.
         * Why doesn't read of multiple blocks work?????
         */
        for (i = 0 ; i < size/512 ; i++) {
                uda.uda_cmd.mscp_seq.seq_lbn = 1;
                uda.uda_cmd.mscp_seq.seq_bytecount = 512;
                uda.uda_cmd.mscp_seq.seq_buffer =
                    (((u_int)buf) & 0x1ff) + i * 512;
                uda.uda_cmd.mscp_unit = ra->unit;
                command(M_OP_READ, 0);
        }

        *rsize=size;
        return 0;
}