/* $NetBSD: ra.c,v 1.20.2.1 2018/03/24 18:06:51 snj 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 1 /* Kludge */ #define NCMD 1 /* Kludge */ #include #include #include #include #include "../include/pte.h" #include "../include/rpb.h" #include #include #include #include #include "vaxstand.h" static void command(int, int); /* * These routines for RA disk standalone boot is wery simple, * assuming a lots of thing like that we only working at one ra disk * a time, no separate routines for uba driver etc.. * This code is foolish and should need a cleanup. * But it works :) */ static volatile struct uda { struct mscp_1ca uda_ca; /* communications area */ struct mscp uda_rsp; /* response packets */ struct mscp uda_cmd; /* command packets */ } uda; static struct disklabel ralabel; static char io_buf[DEV_BSIZE]; static int dpart, dunit, is_tmscp, curblock; static volatile u_short *ra_ip, *ra_sa, *ra_sw; int raopen(struct open_file *f, int adapt, int ctlr, int unit, int part) { static volatile struct uda *ubauda; unsigned short johan, johan2; size_t i; int err; char *msg; #ifdef DEV_DEBUG printf("raopen: adapter %d ctlr %d unit %d part %d\n", adapt, ctlr, unit, part); printf("raopen: csrbase %x nexaddr %x\n", csrbase, nexaddr); #endif memset(&ralabel, 0, sizeof(struct disklabel)); memset((void *)&uda, 0, sizeof(struct uda)); if (bootrpb.devtyp == BDEV_TK) is_tmscp = 1; dunit = unit; dpart = part; if (ctlr < 0) ctlr = 0; curblock = 0; if (csrbase) { /* On a uda-alike adapter */ if (askname == 0) { csrbase = bootrpb.csrphy; dunit = bootrpb.unit; nexaddr = bootrpb.adpphy; } else csrbase += (ctlr ? 000334 : 012150); ra_ip = (u_short *)csrbase; ra_sa = ra_sw = (u_short *)csrbase + 1; ubauda = (struct uda *)ubmap(494, (int)&uda, sizeof(struct uda)); johan = (((u_int)ubauda) & 0xffff) + 8; johan2 = (((u_int)ubauda) >> 16) & 077; *ra_ip = 0; /* Start init */ bootrpb.csrphy = csrbase; } else { paddr_t kdaddr; volatile int *w; volatile int i = 10000; if (askname == 0) { nexaddr = bootrpb.csrphy; dunit = bootrpb.unit; } else { nexaddr = (bootrpb.csrphy & ~(BI_NODESIZE - 1)) + KDB_IP; bootrpb.csrphy = nexaddr; } kdaddr = nexaddr & ~(BI_NODESIZE - 1); ra_ip = (u_short *)(kdaddr + KDB_IP); ra_sa = (u_short *)(kdaddr + KDB_SA); ra_sw = (u_short *)(kdaddr + KDB_SW); johan = ((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff; johan2 = (((u_int)&uda.uda_ca.ca_rspdsc) & 0xffff0000) >> 16; w = (int *)(kdaddr + BIREG_VAXBICSR); *w = *w | BICSR_NRST; while (i--) /* Need delay??? */ ; w = (int *)(kdaddr + BIREG_BER); *w = ~(BIBER_MBZ|BIBER_NMR|BIBER_UPEN);/* ??? */ ubauda = &uda; } #ifdef DEV_DEBUG printf("start init\n"); #endif /* Init of this uda */ while ((*ra_sa & MP_STEP1) == 0) ; #ifdef DEV_DEBUG printf("MP_STEP1..."); #endif *ra_sw = 0x8000; while ((*ra_sa & MP_STEP2) == 0) ; #ifdef DEV_DEBUG printf("MP_STEP2..."); #endif *ra_sw = johan; while ((*ra_sa & MP_STEP3) == 0) ; #ifdef DEV_DEBUG printf("MP_STEP3..."); #endif *ra_sw = johan2; while ((*ra_sa & MP_STEP4) == 0) ; #ifdef DEV_DEBUG printf("MP_STEP4\n"); #endif *ra_sw = 0x0001; uda.uda_ca.ca_rspdsc = (int)&ubauda->uda_rsp.mscp_cmdref; uda.uda_ca.ca_cmddsc = (int)&ubauda->uda_cmd.mscp_cmdref; if (is_tmscp) { 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 = dunit; command(M_OP_ONLINE, 0); if (is_tmscp) { if (part) { #ifdef DEV_DEBUG printf("Repos of tape..."); #endif 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; #ifdef DEV_DEBUG printf("Done!\n"); #endif } return 0; } #ifdef DEV_DEBUG printf("reading disklabel\n"); #endif err = rastrategy(0, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); if(err){ printf("reading disklabel: %s\n",strerror(err)); return 0; } #ifdef DEV_DEBUG printf("getting disklabel\n"); #endif msg = getdisklabel(io_buf+LABELOFFSET, &ralabel); if (msg) printf("getdisklabel: %s\n", msg); return(0); } static void command(int cmd, int arg) { volatile short hej; int to; igen: 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; #ifdef DEV_DEBUG printf("sending cmd %x...", cmd); #endif hej = *ra_ip; __USE(hej); to = 10000000; while (uda.uda_ca.ca_rspdsc < 0) { // if (uda.uda_ca.ca_cmdint) // uda.uda_ca.ca_cmdint = 0; if (--to < 0) { #ifdef DEV_DEBUG printf("timing out, retry\n"); #endif goto igen; } } #ifdef DEV_DEBUG printf("sent.\n"); #endif } int rastrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize) { #ifdef DEV_DEBUG printf("rastrategy: buf %p is_tmscp %d\n", buf, is_tmscp); #endif uda.uda_cmd.mscp_seq.seq_buffer = ubmap(0, (int)buf, size); if (is_tmscp) { int i; /* * 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 = dunit; command(M_OP_READ, 0); } } else { uda.uda_cmd.mscp_seq.seq_lbn = dblk + ralabel.d_partitions[dpart].p_offset; uda.uda_cmd.mscp_seq.seq_bytecount = size; uda.uda_cmd.mscp_unit = dunit; #ifdef DEV_DEBUG printf("rastrategy: blk 0x%lx count %lx unit %x\n", uda.uda_cmd.mscp_seq.seq_lbn, size, dunit); #endif #ifdef notdef if (func == F_WRITE) command(M_OP_WRITE, 0); else #endif command(M_OP_READ, 0); } *rsize = size; return 0; }