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