|
|
1.1 root 1:
2: /*
3: * Cypher tape driver
4: *
5: */
6:
7: #include "pte.h"
8: #include "cy.h"
9: #include "cyconf.h"
10:
11: struct scp *SCP; /* Pointer System configuration block */
12: struct scb scblk; /* System conf. block */
13: struct ccb ccblk; /* Channel control block */
14: struct tpb tpb; /* Tape parameter block */
15: struct tpb tpb1; /* Tape parameter block (spare) */
16: long cmd_done; /* 1 : cmd completed without error */
17: /* 2 : cmd error */
18:
19: long CYattn; /* Virtual address of Cypher I/O attention address */
20: long tm_bsiz = 0;
21: extern long unused, Multi, Berr;
22:
23: tape()
24: { register long r12;
25: long oldvec;
26:
27: m_cy(); /* Map Tape master space */
28:
29: /* Set handler for tape master interrupt */
30: asm("movab cyhdlr,r12");
31: set_handler(CYVEC,&oldvec,r12);
32:
33: cy_reset(); /* Reset Tape master */
34: return(cy_setup()); /* Set up structures and initailize Tape master */
35: }
36:
37:
38: long tm_cnt;
39:
40: /* Routine to sent a command to Tape master
41: return -1 if error
42: return return count of TPB if sucessful
43: */
44: sent_tm()
45: { register long cntr, rtn_cnt;
46:
47: tm_cnt = 0;
48: ccblk.gate = (char)GATE_CLOSED; /* Close gate */
49: cy_attn(); /* Execute command */
50: cntr = RETRY;
51: cmd_done = 0;
52: if (Multi) return;
53: while (!cmd_done) { /* Wait for completion interrupt */
54: DELAY(0x5000);
55: if (--cntr == 0) {
56: writes("sent_tm no interrupt respond\n");
57: return(-1); /* Time out */
58: }
59: }
60: if (cmd_done == 2) return(-1); /* Command has error */
61: return(tm_cnt);
62: }
63:
64: /* Tape master completion interrupt handler
65: */
66: tm_hdlr()
67: {
68: if (chk_cstat())
69: cmd_done = 2; /* completion error */
70: else cmd_done = 1; /* completion without error */
71: tm_cnt = gt_bcnt(); /* Get return count from TPB */
72: clr_tint(); /* Clear tape master interrupt */
73: }
74:
75:
76: /* Routine to ACK on tape master completion interrupt
77: Sent out a NOOP command without interrupt on completion
78: */
79: clr_tint()
80: {
81: while (g_open()==0) /* Gate close */
82: { tm_init();
83: error("Received interrupt but gate closed.\n");
84: }
85: ccblk.gate = GATE_CLOSED;
86: ccblk.ccw = 0x9; /* Clear tape master interrupt */
87: set_g3(&tpb,NOOP,0,0,0); /* No Interrupt on completion please */
88: cy_attn();
89: DELAY(0x1500); /* wait for completion */
90: while (g_open()==0) /* Gate close */
91: { tm_init();
92: error("Cannot clear interrupt\n");
93: return(0);
94: }
95: ccblk.ccw = 0x11;
96: return(1);
97: }
98:
99:
100: /* Check status of command previously issued
101: If all are OK return 0
102: else return Status byte.
103: */
104: chk_cstat()
105: {
106: register long *r12, cstat;
107:
108: r12 = (long *)&tpb.status[1];
109: uncache(r12);
110: /* Cmd status without retry bit */
111: cstat = (long)tpb.status[1];
112: if ((cstat & 0xc0) != 0xc0)
113: { writes("Cy hard error ");
114: writeh(cstat & 0xff); writec('\n');
115: return(cstat); }
116: return(0);
117: }
118:
119: /* Check status of drive after received command
120: completion interrupt. If all are OK return 0
121: else return Status byte.
122: */
123: chk_dstat()
124: { register long *r12, tstat;
125:
126: r12 = (long *)&tpb.status[0];
127: uncache(r12);
128: tstat = tpb.status[0];
129: if ( (tstat & 0x48) != 0x48)
130: { writes("drive error ");
131: writeh(tstat & 0xff);
132: return(tstat); }
133: return(0);
134: }
135:
136: /* Routine to get return_count field of TPB after
137: receive command completion interrupt
138: */
139: gt_bcnt()
140: { register long *r12, tmp1, tmp2;
141:
142: r12 = (long *)&tpb.count;
143: uncache(r12);
144: tmp1 = (long)((tpb.count & (short)0xff)<<8);
145: tmp2 = (long)((tpb.count & (short)0xff00)>>8);
146: return(tmp1|tmp2);
147: }
148:
149:
150: /* Routine to issue a GO command to tape master
151: also known as Channel attention interrupt
152: */
153: cy_attn()
154: { register long r12;
155:
156: r12 = CYattn; /* R12 = Cypher attention address */
157: asm("movob $0xff,(r12)");
158: }
159:
160: /* Routine to reset Tape master controller
161: */
162: cy_reset()
163: { register long r12;
164:
165: r12 = CYattn + 1; /* R12 = Cypher attention address */
166: asm("movob $0xff,(r12)");
167: DELAY(100);
168: if (!Berr) { writes("\nTape controller is at "); writeh(TBASE); }
169: }
170:
171:
172: /* Map channel attention address of Tape master
173: */
174: m_cy()
175: { register long r12;
176: long phys_pg, pte, old_pte, which1;
177:
178: /* physical page of Tape master in IO space */
179: phys_pg = ((TBASE+IOBASE) >> PGSHIFT) & 0x3fffff;
180: pte = phys_pg | PG_KW | PG_V | PG_NC;
181: fix_pte(SBR,unused,&old_pte,pte);
182: CYattn = (unused << PGSHIFT); /* Virtual address of CY attn address */
183: asm("mfpr $SLR,r12");
184: r12++;
185: asm("mtpr r12,$SLR");
186: unused++; /* Next unused PTE in system map */
187: }
188:
189: /* Set up all structures for Tape master
190: and initialize Tape master
191: */
192: cy_setup()
193: {
194: register long cntr;
195:
196: SCP = (struct scp *)SCP_ADR; /* absolute - for setup */
197:
198: /* Initialize the system configuration pointer */
199: SCP->sysbus = 1; /* system width = 16 bits. */
200: set_pointer(&scblk.sysblk,(char *)SCP->pt_scb);
201:
202: /* Initialize the system configuration block. */
203: scblk.sysblk = 0x3; /* fixed value */
204: scblk.nu2 = 0; /* not used */
205: set_pointer(&ccblk.ccw,(char *)scblk.pt_ccb);
206:
207: /* Initialize the channel control block. */
208: ccblk.ccw = 0x11; /* normal interrupts */
209: set_pointer(&tpb,(char *)ccblk.pt_tpb);
210:
211: ccblk.gate = GATE_CLOSED;
212: cy_attn(); /* 1st attention : initilization Cypher */
213: cntr = RETRY;
214: while (ccblk.gate == GATE_CLOSED) {
215: DELAY(0x400); /* wait for completion */
216: if (--cntr == 0) {
217: writes("Init : Cypher time out\n");
218: return(0); } /* Time out */
219: }
220: return(1);
221: }
222:
223:
224: /*
225: * Set a TAPEMASTER 20_bit pointer (first parameter), into the
226: * 4 bytes array pointed by the second parameter.
227: */
228: set_pointer(pointer,dest)
229: long pointer;
230: char *dest;
231: {
232: *dest++ = pointer & 0xff; /* low byte - offset */
233: *dest++ = (pointer >> 8) & 0xff; /* high byte - offset */
234: *dest++ = 0;
235: *dest = (pointer & 0xf0000) >> 12; /* base */
236: }
237:
238:
239:
240: g_open()
241: { register long *r12, cntr;
242:
243: r12 = (long *)&ccblk.gate;
244: cntr = RETRY;
245: while (ccblk.gate!=0) {
246: uncache(r12);
247: DELAY(0x500); /* wait for completion */
248: if (--cntr == 0) {
249: writes("g_open time out\n");
250: return(0);
251: }
252: }
253: return(1);
254: }
255:
256: error(msg)
257: char *msg;
258: {
259: writes(msg);
260: }
261:
262:
263:
264: /* Set Tape Parameter Block
265: Input :
266: cmd = Opcode
267: bufsiz = Block size
268: bufadr = System buffer address
269: int = interrupt on completion or not
270: */
271:
272: set_g3(tpblk,cmd,bufsiz,bufadr,intr)
273: struct tpb *tpblk;
274: long cmd, bufsiz, intr;
275: char *bufadr;
276: { char *cptr;
277:
278: tpblk->cmd = cmd; /* Command */
279: tpblk->control[1] = 0x80 | CW_100ips; /* 16_bit system bus */
280: tpblk->control[0] = (0|(intr << 5)); /* Bank=0,Drive=0,interrupt */
281: tpblk->count = 0; /* Return count = 0 */
282:
283: cptr = (char *)&tpblk->size; /* Set buffer size */
284: *cptr++ = (char)(bufsiz & 0xff);
285: *cptr = (char)((bufsiz & 0xff00)>>8);
286: tpblk->rec_over = 0;
287:
288: /* Set system buffer address */
289: set_pointer((long)(bufadr),(char *)tpblk->pt_data);
290: tpblk->status[0] = tpblk->status[1] = 0;
291: }
292:
293:
294:
295:
296: /* *************************************
297: Routine to Read/Write Cypher tape
298: return 0 if cannot complete operation
299: *************************************
300: */
301: long tape_op(cmd,buf_adr,buf_siz)
302: long cmd, buf_siz;
303: char *buf_adr;
304: { char *cptr;
305: register long cnt, stat, tmp1, tmp2;
306:
307: switch (cmd) {
308: case READ_TA : { writec('.'); break; }
309: case WRIT_TA : { writec(','); break; }
310: case REWD_TA : { writec('*'); break; }
311: }
312: set_g3(&tpb,cmd,buf_siz,buf_adr,1); /* Set up command block */
313: while (g_open()==0) { /* Gate closed !! */
314: tm_init(); /* Init controller */
315: writes("\ntape_op : Can not open gate !!\n");
316: return(0);
317: }
318: return(sent_tm());
319: }
320:
321: /* Rewind tapemaster
322: */
323: tm_rew()
324: { char tstat;
325:
326: if (tape_op(REWD_TA,0,0) == -1) return(0);
327: tstat = tpb.status[0];
328: if ( (tstat & 0x20) != 0x20) return(0);
329: return(1);
330: }
331:
332:
333: /* Routine to initialize tape master
334: */
335: tm_init()
336: { register long cntr;
337:
338: cy_reset();
339: if (!g_open()) return(0);
340: ccblk.gate = GATE_CLOSED;
341: cy_attn(); /* 1st attention : initilization Cypher */
342: cntr = RETRY;
343: while (ccblk.gate == GATE_CLOSED) {
344: DELAY(2000); /* wait for completion */
345: if (--cntr == 0) {
346: writes("Init : Cypher time out\n");
347: return(0); } /* Time out */
348: }
349: return(1);
350: }
351:
352: cyhandler()
353: { long dummy;
354:
355: asm(".align 2");
356: asm("cyhdlr:");
357: asm("svpctx");
358: tm_hdlr();
359: asm("ldpctx");
360: asm("rei");
361: dummy = 0;
362: }
363:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.