|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)tm.c 1.1 86/02/03 Copyr 1985 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: /*
10: * Standalone driver for Ciprico TapeMaster Multibus tape controller
11: */
12:
13: #include "saio.h"
14: #include "../sundev/tmreg.h"
15: #include "../mon/cpu.map.h"
16: #include "../mon/cpu.addrs.h"
17:
18: /*
19: * Standard addresses for this board
20: */
21: #define NTMADDR 2
22: unsigned long tmstd[] = { 0xA0, 0xA2 };
23:
24: /*
25: * Structure of our dma space
26: */
27: #define MAXTMREC (20*1024) /* max size tape rec allowed */
28: struct tmdma {
29: struct tm_mbinfo tm_mbinfo; /* Multibus IOPB crap */
30: char tmbuf[MAXTMREC];/* Block of data */
31: };
32:
33: #define MB_DMA_ADDR_MASK 0x000FFFFF /* Low meg */
34:
35: /*
36: * Driver definition
37: */
38: struct devinfo tminfo = {
39: sizeof(struct tmdevice), /* Size of device registers */
40: sizeof(struct tmdma), /* DMA space required */
41: 0, /* Local variable space */
42: NTMADDR, /* # of standard addresses */
43: tmstd, /* Standard addr vector */
44: MAP_MBIO, /* Map type of device regs */
45: MAXTMREC, /* transfer size */
46: };
47:
48: /*
49: * What facilities we export to the world
50: */
51: int tmstrategy(), tmopen(), tmclose();
52: extern int ttboot();
53: extern int nullsys();
54:
55: struct boottab mtdriver = {
56: "mt", nullsys, ttboot, tmopen, tmclose, tmstrategy,
57: "mt: TapeMaster 9-track tape", &tminfo,
58: };
59:
60:
61: /*
62: * Open a tape drive
63: */
64: tmopen(sip)
65: register struct saioreq *sip;
66: {
67: register skip;
68:
69: if (tminit(sip) == -1)
70: return (-1);
71: tmcmd(sip, TM_REWINDX);
72: skip = sip->si_boff;
73: while (skip--) {
74: sip->si_cc = 0;
75: tmcmd(sip, TM_SEARCH);
76: }
77: return (0);
78: }
79:
80: tmclose(sip)
81: struct saioreq *sip;
82: {
83:
84: tmcmd(sip, TM_REWINDX);
85: }
86:
87: tmstrategy(sip, rw)
88: register struct saioreq *sip;
89: int rw;
90: {
91: int func = (rw == WRITE) ? TM_WRITE : TM_READ;
92:
93: return tmcmd(sip, func);
94: }
95:
96: #define NOTZERO 1 /* don't care value-but not zero (clr inst botch) */
97: #define ATTN(c) (((struct tmdevice *)c)->tmdev_attn=NOTZERO)
98: #define RESET(c) (((struct tmdevice *)c)->tmdev_reset=NOTZERO)
99: #define clrtpb(tp) bzero((caddr_t)(tp), sizeof *(tp));
100:
101: tmcmd(sip, func)
102: register struct saioreq *sip;
103: {
104: # define tmdmap ((struct tmdma *)sip->si_dmaaddr)
105: # define tmb (&tmdmap->tm_mbinfo)
106: register struct tmdevice *tmaddr =
107: (struct tmdevice *)sip->si_devaddr;
108: register struct tpb *tpb = &tmb->tmb_tpb;
109: int count = 1;
110: int size = 0;
111: struct tmstat tms;
112: int err;
113:
114: switch (func) {
115:
116: case TM_READ:
117: size = sip->si_cc;
118: break;
119:
120: case TM_WRITE:
121: size = sip->si_cc;
122: swab((char *)sip->si_ma, tmdmap->tmbuf, size);
123: break;
124: }
125:
126: clrtpb(tpb);
127: tpb->tm_cmd = func &~ TM_DIRBIT;
128: tpb->tm_ctl.tmc_rev = func & TM_DIRBIT;
129: tpb->tm_ctl.tmc_width = 1;
130: tpb->tm_ctl.tmc_speed = sip->si_unit & 08;
131: tpb->tm_ctl.tmc_tape = sip->si_unit & 03;
132: tpb->tm_rcount = count;
133: tpb->tm_bsize = size;
134: c68t86((long)tmdmap->tmbuf, &tpb->tm_baddr);
135: tmb->tmb_ccb.tmccb_gate = TMG_CLOSED;
136:
137: /* Start the command and wait for completion */
138: ATTN(tmaddr);
139: while (tmb->tmb_ccb.tmccb_gate == TMG_CLOSED)
140: ;
141:
142: tms = tpb->tm_stat;
143: err = tms.tms_error;
144:
145: /*
146: * An operation completed... record status
147: */
148: if (err == E_EOT && tms.tms_load)
149: err = E_NOERROR;
150: /*
151: * Check for errors.
152: */
153: if (err != E_NOERROR && err != E_SHORTREC) {
154: if (err == E_EOF || err == E_EOT)
155: return (0);
156: /* Note: TapeMaster does retries for us */
157: printf("tm hard err %x\n", err);
158: return (-1);
159: }
160: if (func == TM_READ)
161: swab(tmdmap->tmbuf, sip->si_ma, tpb->tm_count);
162: return (tpb->tm_count);
163: # undef tmdma
164: # undef tmb
165: }
166:
167: #define SPININIT 1000000
168: /*
169: * Initialize a controller
170: * Reset it, set up SCP, SCB, and CCB,
171: * and give it an attention.
172: * Make sure its there by waiting for the gate to open
173: * Once initialization is done, issue CONFIG just to be safe.
174: */
175: tminit(sip)
176: register struct saioreq *sip;
177: {
178: register struct tm_mbinfo *tmb =
179: &((struct tmdma *)(sip->si_dmaaddr))->tm_mbinfo;
180: register struct tmdevice *tmaddr =
181: (struct tmdevice *)sip->si_devaddr;
182: register struct tpb *tpb = &tmb->tmb_tpb;
183:
184: bzero((caddr_t)tmb, sizeof (struct tm_mbinfo));
185: RESET(tmaddr);
186:
187: /* setup System Configuration Block */
188: tmb->tmb_scb.tmscb_03 = tmb->tmb_scb.tmscb_03x = TMSCB_CONS;
189: c68t86((long)&tmb->tmb_ccb, &tmb->tmb_scb.tmccb_ptr);
190:
191: /* setup Channel Control Block */
192: tmb->tmb_ccb.tmccb_gate = TMG_CLOSED;
193:
194: {
195: register struct tmscp *tmscp;
196: char *temp;
197: register int spin;
198: int virtstart;
199:
200: /* Snatch the dma space that this screwy Intel device needs */
201: /* get the virtual address */
202: tmscp = (struct tmscp *)(DVMA_BASE + TM_SCPADDR);
203: virtstart = getpgmap((char *)tmscp);
204: /* get random page */
205: temp = resalloc(RES_MAINMEM, sizeof (struct tmscp));
206: /* point virt at new page */
207: setpgmap((char *)tmscp, getpgmap(temp));
208:
209: /* setup System Configuration Pointer */
210: tmscp->tmscb_bus = tmscp->tmscb_busx = TMSCB_BUS16;
211: c68t86((long)&tmb->tmb_scb, &tmscp->tmscb_ptr);
212:
213: /* Start the TapeMaster and wait til it says "done" */
214: ATTN(tmaddr);
215: for (spin = SPININIT; tmb->tmb_ccb.tmccb_gate != TMG_OPEN; )
216: if (--spin <= 0)
217: break;
218:
219: /* Give back the dma space this screwy Intel device needs */
220: setpgmap((char *)tmscp, virtstart);
221:
222: if (spin <= 0) {
223: printf("tm: no response from ctlr %x\n", sip->si_ctlr);
224: return (-1);
225: }
226: }
227:
228: /* Finish CCB, point it at TPB */
229: tmb->tmb_ccb.tmccb_ccw = TMC_NORMAL;
230: c68t86((long)tpb, &tmb->tmb_ccb.tmtpb_ptr);
231:
232: /* Issue CONFIG command */
233: clrtpb(tpb);
234: tpb->tm_cmd = TM_CONFIG;
235: tpb->tm_cmd2 = 0;
236: tpb->tm_ctl.tmc_width = 1;
237:
238: /* Get the gate */
239: while (tmb->tmb_ccb.tmccb_gate != TMG_OPEN)
240: ;
241: tmb->tmb_ccb.tmccb_gate = TMG_CLOSED;
242:
243: /* Start the command and wait for completion */
244: ATTN(tmaddr);
245: while (tmb->tmb_ccb.tmccb_gate == TMG_CLOSED)
246: ;
247:
248: /* Check and report errors */
249: if (tpb->tm_stat.tms_error) {
250: printf("tm: error %d during config of ctlr %x\n",
251: tpb->tm_stat.tms_error, sip->si_ctlr);
252: tpb->tm_stat.tms_error = 0;
253: return (-1);
254: }
255: return (0);
256: }
257:
258: /*
259: * Convert a 68000 address into a 8086 address
260: * This involves translating a virtual address into a
261: * physical multibus address and converting the 20 bit result
262: * into a two word base and offset.
263: */
264: static c68t86(a68, a86)
265: long a68;
266: ptr86_t *a86;
267: {
268:
269: a68 &= MB_DMA_ADDR_MASK;
270: a86->a_offset = a68 & 0xFFFF;
271: a86->a_base = (a68 & 0xF0000) >> 4;
272: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.