Init
This commit is contained in:
278
sys/boot/lib/common/tm.c
Normal file
278
sys/boot/lib/common/tm.c
Normal file
@@ -0,0 +1,278 @@
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)tm.c 1.1 94/10/31 Copyr 1985 Sun Micro";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Standalone driver for Ciprico TapeMaster Multibus tape controller
|
||||
*/
|
||||
|
||||
#include <stand/saio.h>
|
||||
#include <sundev/tmreg.h>
|
||||
#include <mon/cpu.map.h>
|
||||
#include <mon/cpu.addrs.h>
|
||||
|
||||
/*
|
||||
* Standard addresses for this board
|
||||
*/
|
||||
#define NTMADDR 2
|
||||
unsigned long tmstd[] = { 0xA0, 0xA2 };
|
||||
|
||||
/*
|
||||
* Structure of our dma space
|
||||
*/
|
||||
#define MAXTMREC (20*1024) /* max size tape rec allowed */
|
||||
struct tmdma {
|
||||
struct tm_mbinfo tm_mbinfo; /* Multibus IOPB crap */
|
||||
char tmbuf[MAXTMREC];/* Block of data */
|
||||
};
|
||||
|
||||
#define MB_DMA_ADDR_MASK 0x000FFFFF /* Low meg */
|
||||
|
||||
/*
|
||||
* Driver definition
|
||||
*/
|
||||
struct devinfo tminfo = {
|
||||
sizeof(struct tmdevice), /* Size of device registers */
|
||||
sizeof(struct tmdma), /* DMA space required */
|
||||
0, /* Local variable space */
|
||||
NTMADDR, /* # of standard addresses */
|
||||
tmstd, /* Standard addr vector */
|
||||
MAP_MBIO, /* Map type of device regs */
|
||||
MAXTMREC, /* transfer size */
|
||||
};
|
||||
|
||||
/*
|
||||
* What facilities we export to the world
|
||||
*/
|
||||
int tmstrategy(), tmopen(), tmclose();
|
||||
extern int ttboot();
|
||||
extern int nullsys();
|
||||
|
||||
struct boottab mtdriver = {
|
||||
"mt", nullsys, ttboot, tmopen, tmclose, tmstrategy,
|
||||
"mt: TapeMaster 9-track tape", &tminfo,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Open a tape drive
|
||||
*/
|
||||
tmopen(sip)
|
||||
register struct saioreq *sip;
|
||||
{
|
||||
register skip;
|
||||
|
||||
if (tminit(sip) == -1)
|
||||
return (-1);
|
||||
tmcmd(sip, TM_REWINDX);
|
||||
skip = sip->si_boff;
|
||||
while (skip--) {
|
||||
sip->si_cc = 0;
|
||||
tmcmd(sip, TM_SEARCH);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
tmclose(sip)
|
||||
struct saioreq *sip;
|
||||
{
|
||||
|
||||
/*tmcmd(sip, TM_REWINDX);*/
|
||||
}
|
||||
|
||||
tmstrategy(sip, rw)
|
||||
register struct saioreq *sip;
|
||||
int rw;
|
||||
{
|
||||
int func = (rw == WRITE) ? TM_WRITE : TM_READ;
|
||||
|
||||
return tmcmd(sip, func);
|
||||
}
|
||||
|
||||
#define NOTZERO 1 /* don't care value-but not zero (clr inst botch) */
|
||||
#define ATTN(c) (((struct tmdevice *)c)->tmdev_attn=NOTZERO)
|
||||
#define RESET(c) (((struct tmdevice *)c)->tmdev_reset=NOTZERO)
|
||||
#define clrtpb(tp) bzero((caddr_t)(tp), sizeof *(tp));
|
||||
|
||||
tmcmd(sip, func)
|
||||
register struct saioreq *sip;
|
||||
{
|
||||
# define tmdmap ((struct tmdma *)sip->si_dmaaddr)
|
||||
# define tmb (&tmdmap->tm_mbinfo)
|
||||
register struct tmdevice *tmaddr =
|
||||
(struct tmdevice *)sip->si_devaddr;
|
||||
register struct tpb *tpb = &tmb->tmb_tpb;
|
||||
int count = 1;
|
||||
int size = 0;
|
||||
struct tmstat tms;
|
||||
int err;
|
||||
|
||||
switch (func) {
|
||||
|
||||
case TM_READ:
|
||||
size = sip->si_cc;
|
||||
break;
|
||||
|
||||
case TM_WRITE:
|
||||
size = sip->si_cc;
|
||||
swab((char *)sip->si_ma, tmdmap->tmbuf, size);
|
||||
break;
|
||||
}
|
||||
|
||||
clrtpb(tpb);
|
||||
tpb->tm_cmd = func &~ TM_DIRBIT;
|
||||
tpb->tm_ctl.tmc_rev = func & TM_DIRBIT;
|
||||
tpb->tm_ctl.tmc_width = 1;
|
||||
tpb->tm_ctl.tmc_speed = sip->si_unit & 010;
|
||||
tpb->tm_ctl.tmc_tape = sip->si_unit & 03;
|
||||
tpb->tm_rcount = count;
|
||||
tpb->tm_bsize = size;
|
||||
c68t86((long)tmdmap->tmbuf, &tpb->tm_baddr);
|
||||
tmb->tmb_ccb.tmccb_gate = TMG_CLOSED;
|
||||
|
||||
/* Start the command and wait for completion */
|
||||
ATTN(tmaddr);
|
||||
while (tmb->tmb_ccb.tmccb_gate == TMG_CLOSED)
|
||||
;
|
||||
|
||||
tms = tpb->tm_stat;
|
||||
err = tms.tms_error;
|
||||
|
||||
/*
|
||||
* An operation completed... record status
|
||||
*/
|
||||
if (err == E_EOT && tms.tms_load)
|
||||
err = E_NOERROR;
|
||||
/*
|
||||
* Check for errors.
|
||||
*/
|
||||
if (err != E_NOERROR && err != E_SHORTREC) {
|
||||
if (err == E_EOF || err == E_EOT)
|
||||
return (0);
|
||||
/* Note: TapeMaster does retries for us */
|
||||
printf("tm hard err %x\n", err);
|
||||
return (-1);
|
||||
}
|
||||
if (func == TM_READ)
|
||||
swab(tmdmap->tmbuf, sip->si_ma, tpb->tm_count);
|
||||
return (tpb->tm_count);
|
||||
# undef tmdma
|
||||
# undef tmb
|
||||
}
|
||||
|
||||
#define SPININIT 1000000
|
||||
/*
|
||||
* Initialize a controller
|
||||
* Reset it, set up SCP, SCB, and CCB,
|
||||
* and give it an attention.
|
||||
* Make sure its there by waiting for the gate to open
|
||||
* Once initialization is done, issue CONFIG just to be safe.
|
||||
*/
|
||||
tminit(sip)
|
||||
register struct saioreq *sip;
|
||||
{
|
||||
register struct tm_mbinfo *tmb =
|
||||
&((struct tmdma *)(sip->si_dmaaddr))->tm_mbinfo;
|
||||
register struct tmdevice *tmaddr =
|
||||
(struct tmdevice *)sip->si_devaddr;
|
||||
register struct tpb *tpb = &tmb->tmb_tpb;
|
||||
|
||||
bzero((caddr_t)tmb, sizeof (struct tm_mbinfo));
|
||||
RESET(tmaddr);
|
||||
|
||||
/* setup System Configuration Block */
|
||||
tmb->tmb_scb.tmscb_03 = tmb->tmb_scb.tmscb_03x = TMSCB_CONS;
|
||||
c68t86((long)&tmb->tmb_ccb, &tmb->tmb_scb.tmccb_ptr);
|
||||
|
||||
/* setup Channel Control Block */
|
||||
tmb->tmb_ccb.tmccb_gate = TMG_CLOSED;
|
||||
|
||||
{
|
||||
register struct tmscp *tmscp;
|
||||
char *temp;
|
||||
register int spin;
|
||||
int v1, v2;
|
||||
|
||||
/* Snatch the dma space that this screwy Intel device needs */
|
||||
/* get the virtual address */
|
||||
tmscp = (struct tmscp *)(DVMA_BASE + TM_SCPADDR);
|
||||
v1 = getpgmap((char *)tmscp);
|
||||
v2 = getpgmap((char *)tmb);
|
||||
if (v1 != v2) {
|
||||
/* get random page */
|
||||
temp = resalloc(RES_MAINMEM, sizeof (struct tmscp));
|
||||
/* point virt at new page */
|
||||
setpgmap((char *)tmscp, getpgmap(temp));
|
||||
}
|
||||
/* setup System Configuration Pointer */
|
||||
tmscp->tmscb_bus = tmscp->tmscb_busx = TMSCB_BUS16;
|
||||
c68t86((long)&tmb->tmb_scb, &tmscp->tmscb_ptr);
|
||||
|
||||
/* Start the TapeMaster and wait til it says "done" */
|
||||
ATTN(tmaddr);
|
||||
for (spin = SPININIT; tmb->tmb_ccb.tmccb_gate != TMG_OPEN; )
|
||||
if (--spin <= 0)
|
||||
break;
|
||||
if (v1 != v2) {
|
||||
/*
|
||||
* Give back the dma space this screwy Intel
|
||||
* device needs
|
||||
*/
|
||||
setpgmap((char *)tmscp, v1);
|
||||
}
|
||||
if (spin <= 0) {
|
||||
printf("tm: no response from ctlr %x\n", sip->si_ctlr);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish CCB, point it at TPB */
|
||||
tmb->tmb_ccb.tmccb_ccw = TMC_NORMAL;
|
||||
c68t86((long)tpb, &tmb->tmb_ccb.tmtpb_ptr);
|
||||
|
||||
/* Issue CONFIG command */
|
||||
clrtpb(tpb);
|
||||
tpb->tm_cmd = TM_CONFIG;
|
||||
tpb->tm_cmd2 = 0;
|
||||
tpb->tm_ctl.tmc_width = 1;
|
||||
|
||||
/* Get the gate */
|
||||
while (tmb->tmb_ccb.tmccb_gate != TMG_OPEN)
|
||||
;
|
||||
tmb->tmb_ccb.tmccb_gate = TMG_CLOSED;
|
||||
|
||||
/* Start the command and wait for completion */
|
||||
ATTN(tmaddr);
|
||||
while (tmb->tmb_ccb.tmccb_gate == TMG_CLOSED)
|
||||
;
|
||||
|
||||
/* Check and report errors */
|
||||
if (tpb->tm_stat.tms_error) {
|
||||
printf("tm: error %d during config of ctlr %x\n",
|
||||
tpb->tm_stat.tms_error, sip->si_ctlr);
|
||||
tpb->tm_stat.tms_error = 0;
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a 68000 address into a 8086 address
|
||||
* This involves translating a virtual address into a
|
||||
* physical multibus address and converting the 20 bit result
|
||||
* into a two word base and offset.
|
||||
*/
|
||||
static c68t86(a68, a86)
|
||||
long a68;
|
||||
ptr86_t *a86;
|
||||
{
|
||||
|
||||
a68 &= MB_DMA_ADDR_MASK;
|
||||
a86->a_offset = a68 & 0xFFFF;
|
||||
a86->a_base = (a68 & 0xF0000) >> 4;
|
||||
}
|
||||
Reference in New Issue
Block a user