|
|
1.1 root 1: /*
2: ** Author: John R. Franks
3: ** Date: 16-Aug-85
4: **
5: ** This driver is used to control a Tapemaster tape controller. The
6: ** Tapemaster controller is a particularly unreasonable controller to work
7: ** with.
8: **
9: ** We implement both a block device and a raw device with this driver.
10: ** (of course) Each device has it's own special requirement as defined below.
11: **
12: ** The block device handles files which consist of a series of 1k byte
13: ** blocks. It can be read or written to like any random access device, except,
14: ** you can not read past the last position written to on tape. The reason
15: ** for this is entirly mechanical. Tape drive positioning is not accurate
16: ** enough to guarantee that we will not write over a portion of a following
17: ** record on the tape. I.e. If we had five known blocks on a tape and we
18: ** rewrote the fourth block on the tape, then the fifth block probably
19: ** had it's leading gap or the beginning of it's data overwritten. Clearly
20: ** the data can not be trusted, so, we just make it a rule that writting
21: ** to the tape in any form also defines the end of volume.
22: **
23: ** The block device will seek automatically to the next block number if
24: ** the tape is mispositioned before the read is done.
25: **
26: ** In general the block device should not be used except maybe to
27: ** read an exact disk image off of it.
28: **
29: ** The raw device is responsible for large reads and writes, and all
30: ** ioctl control commands. Each command has to keep the tape in a consistant
31: ** state so that they will not be messed up by the sequence of user requests.
32: ** As an example: if a user back spaces after a write an end of volume record
33: ** will be written before the spacing occurs so that we will be able to
34: ** find the end of the file subsequent read operatons.
35: **
36: ** The raw device also has the same restrictions on writes as the block
37: ** device.
38: **
39: ** The ioctls supported by the system are:
40: **
41: ** internal name value comments
42: ** DO_W_FM 0 Write a file mark to tape
43: ** DO_SFMF 1 search for a file mark in the forward direction
44: ** DO_SFMB 2 search fo a file mark in the backward direction.
45: ** DO_SPF 3 space forward one record
46: ** DO_SPB 4 space backward one record
47: ** DO_RWTA 5 rewind and wait
48: ** DO_RWUN 6 rewind and unload tape
49: ** DO_STAT 7 get drive status
50: ** DO_RWOV 8 rewind overlapped
51: ** DO_WAIT 9 wait for rewind to complete
52: */
53:
54: /* Includes */
55:
56: #include "cy.h"
57: #if NCY > 0
58: int cydebug = 0;
59: #include "../h/param.h"
60: #include "../h/systm.h"
61: #include "../machine/mtpr.h"
62: #include "../h/vm.h"
63: #include "../h/buf.h"
64: #include "../machine/pte.h"
65: #include "../h/file.h"
66: #include "../h/dir.h"
67: #include "../h/user.h"
68: #include "../h/proc.h"
69: #include "../h/signal.h"
70:
71: #include "../h/uio.h"
72: #include "../h/ioctl.h"
73: #include "../h/mtio.h"
74: #include "../h/errno.h"
75: #include "../h/cmap.h"
76: #include "../vba/vbavar.h"
77: #include "../vba/cipher.h"
78:
79:
80: /* Definitions */
81:
82: #define MAXCONTROLLERS 4
83: #define MAX_BLOCKSIZE (TBUFSIZ*NBPG)
84: #define NUM_UNIT (NCY * 4)
85:
86: #define TRUE 1
87: #define FALSE 0
88: #define NOERROR 0
89: #define RETRY 1
90: #define EXTEND 2
91: #define FATAL 3
92:
93: #define MAINTAIN_POSITION 0
94: #define DONT_MAINTAIN_POSITION 1
95:
96: #define PROCESSED 0x80000000
97: #define SLEEPING 0x80000000
98: #define b_cmd av_back /* only unused word in request */
99:
100:
101: /*
102: ** ioctl command offset definitions. (so we can issue ioctls internally)
103: */
104:
105: #define DO_W_FM 0
106: #define DO_SFMF 1
107: #define DO_SFMB 2
108: #define DO_SPF 3
109: #define DO_SPB 4
110: #define DO_RWTA 5
111: #define DO_RWUN 6
112: #define DO_STAT 7
113: #define DO_RWOV 8
114: #define DO_WAIT 9
115: #define DO_WEOV 10
116: #define DO_RRD 11
117: #define DO_RWT 12
118: #define DO_BRD 13
119: #define DO_BWT 14
120:
121: /*
122: ** Declarations for ioctl subroutines (needed for jump table below.
123: */
124:
125: extern int cywrite_filemark(), cysearch_fm_forw(), cysearch_fm_back();
126: extern int cy_space_forw(), cy_space_back(), cyrewind_tape_ta();
127: extern int cyrewind_tape_unl(), cydrive_status(), cyrewind_tape_ov();
128: extern int cyraw_read(), cyraw_write(), cybuf_read(), cybuf_write();
129: extern int cywait_until_ready(), cywrite_0_fm(), cywrite_1_fm();
130: extern int cywrite_2_fm(), cyno_op(), cywrite_eov();
131:
132: /*
133: ** Jump table for ioctl functions (used in cystart).
134: */
135:
136: static int (*cmd_tbl[15])() = {
137: cywrite_filemark, cysearch_fm_forw, cysearch_fm_back, cy_space_forw,
138: cy_space_back, cyrewind_tape_ta, cyrewind_tape_unl, cydrive_status,
139: cyrewind_tape_ov, cywait_until_ready, cywrite_eov, cyraw_read,
140: cyraw_write, cybuf_read, cybuf_write
141: };
142:
143: /* Variables */
144:
145: /* Autoconfigure entry point definitions */
146:
147: extern int cyprobe(), cyslave(), cyattach(), cydgo();
148:
149: /* physio routines */
150:
151: extern unsigned cyminsize();
152:
153: /* Define driver structures for UNIX */
154:
155: extern char cy0utl[];
156: #if NCY > 0
157: extern char cy1utl[];
158: #endif
159:
160: static fmt_scp *scp_ptrs[MAXCONTROLLERS] = {
161: (fmt_scp *)0xc0000c06, (fmt_scp *)0xc0000c16,
162: };
163:
164: struct vba_ctlr *cyminfo[NCY];
165:
166: struct vba_device *cydinfo[NUM_UNIT];
167:
168: struct vba_driver cydriver =
169: {
170: cyprobe, cyslave, cyattach, cydgo, (long *)scp_ptrs,
171: "cipher", cydinfo, "", cyminfo
172: };
173:
174: /* Define data structures for controllers */
175:
176: typedef struct {
177: struct pte *map;
178: char *utl;
179: int (*interupt_path)();
180: label_t environ; /* Environment variable for longjmps */
181: struct buf *my_request;
182: struct buf *wakeup_request;
183: short bs; /* buffer size */
184: fmt_ccb ccb; /* Channel control blocks */
185: fmt_scb scb; /* System configuration blocks */
186: fmt_tpb tpb; /* Tape parameter blocks */
187: fmt_tpb last; /* Tape parameter blocks */
188: fmt_tpb noop; /* Tape parameter blocks */
189: long rawbuf[MAX_BLOCKSIZE/sizeof(long)+1];
190: } ctlr_tab;
191:
192: extern int cy_normal_path();
193:
194: ctlr_tab ctlr_info[NCY] = {
195: {CY0map, cy0utl, cy_normal_path}
196: #if NCY > 1
197: ,{CY1map, cy1utl, cy_normal_path}
198: #if NCY > 2
199: error /* Only 2 controllers can be used at this time */
200: #endif
201: #endif
202: };
203:
204: /* information needed for each drive */
205:
206: typedef struct {
207: int (*cleanup)();
208: struct buf u_queue;
209: struct buf rawbp;
210: long blkno;
211: long file_number;
212: short last_control;
213: short last_status;
214: short last_resid;
215: unsigned long bad_count;
216: unsigned control_proto: 16;
217: unsigned error_count : 8;
218: unsigned open : 1;
219: unsigned eof : 1;
220: unsigned bot : 1;
221: unsigned eot : 1;
222: char *message;
223: }unit_tab;
224:
225: unit_tab unit_info[NUM_UNIT];
226:
1.1.1.2 ! root 227: static char *long_block_msg =
! 228: "\ncy%d: Block contained %d bytes: not %d bytes.\n";
1.1 root 229:
230: /*
231: ** Cyprobe checks to see if a controller is present on the VERSAbus.
232: ** An attempt is made to read from the controller's first register, if
233: ** a buss error does not occur then the controller is assumed to be
234: ** there.
235: **
236: ** If the controller responds to the read request, then we go ahead
237: ** and initialize the controller for UNIX's use. If no problems were
238: ** reported during system initialization, then we return TRUE to the
239: ** system to indicate that the controller is there and everything is OK.
240: */
241:
242: cyprobe(ctlr_vaddr)
243: register caddr_t ctlr_vaddr;
244: {
245: static int ctlr = -1;
246:
247: ctlr++;
248: if (!badcyaddr(ctlr_vaddr + 1))
249: return cy_init_controller(ctlr_vaddr, ctlr, 1);
250: return FALSE;
251: }
252:
253:
254: /*
255: ** Cy_init_controller is called to initialize the controller after the
256: ** controller is reset or during Autoconfigure. All of the system control
257: ** blocks are initialized and the controller is asked to configure itself
258: ** for later use.
259: **
260: ** If the print value is true cy_first_TM_attention will anounce
261: ** the type of controller we are (Tapemasher) and will print the size
262: ** of the internal controller buffer.
263: */
264:
265: cy_init_controller(ctlr_vaddr, ctlr, print)
266: register caddr_t ctlr_vaddr;
267: register int ctlr;
268: register int print;
269: {
270: cy_init_sys_config_ptr(ctlr);
271: cy_init_sys_config_blk(ctlr);
272: cy_init_channel_control_blk(ctlr);
273: return cy_first_TM_attention(ctlr_vaddr, ctlr, print);
274: }
275:
276:
277: /*
278: ** Cyslave checks to see if a drive is attached to a controller.
279: ** There are no signals, on the serial buses from the tape drive to the
280: ** controller, to indicate that a drive is physically present on the
281: ** buss. We can only tell that a drive is there if a tape is loaded
282: ** on the drive and the drive is placed online.
283: **
284: ** Since it would be ridiculus to force system operators to load
285: ** tapes on every tape drive on the system before every boot operation,
286: ** we simply indicate that the drive is there every time we are asked.
287: **
288: ** In theory the system should be configured according to the
289: ** hardware configuration anyway and should not present a problem.
290: */
291:
292: cyslave(vba_device_info, ctlr_vaddr)
293: register struct vba_device *vba_device_info;
294: register caddr_t ctlr_vaddr;
295: {
296: /*
297: * assume tape is connected because there is
298: * no way on earth to tell if the drive is connected or not.
299: */
300: return TRUE;
301: }
302:
303:
304: /*
305: ** cyattach is used to add a drive to our internal tables.
306: */
307:
308: cyattach(dev_info)
309: struct vba_device *dev_info;
310: {
311: register unit_tab *u_info = &unit_info[dev_info->ui_unit];
312: register struct buf *ctlr_queue = &dev_info->ui_mi->um_tab;
313: register struct buf *unit_queue = ctlr_queue->b_forw;
314: register struct buf *start_queue = unit_queue;
315:
316: /* Add unit to controllers queue */
317: if(ctlr_queue->b_forw == NULL) {
318: ctlr_queue->b_forw = &u_info->u_queue;
319: u_info->u_queue.b_forw = &u_info->u_queue;
320: }
321: else {
322: while(unit_queue->b_forw != start_queue)
323: unit_queue = unit_queue->b_forw;
324: u_info->u_queue.b_forw = start_queue;
325: unit_queue->b_forw = &u_info->u_queue;
326: }
327: u_info->cleanup = cyno_op;
328: u_info->last_status = 0;
329: u_info->last_control = 0;
330: u_info->file_number = 0;
331: u_info->bad_count = 0;
332: u_info->blkno = 0;
333: u_info->open = FALSE;
334: u_info->bot = TRUE;
335: u_info->eot = FALSE;
336: u_info->eof = FALSE;
337: u_info->message = NULL;
338: }
339:
340:
341: /*
342: ** Historic routine left over from VAX port but the definition is still
343: ** hanging around.
344: */
345:
346: cydgo()
347: {
348: }
349:
350: /*
351: ** cy_init_sys_config_ptr initializes the Tapemaster system configuration
352: ** pointer. The Tapemaster controller requires it's own system pointer
353: ** in low memory. The absolute addresses are 0xc06 for controller #1, and
354: ** 0xc16 for controller #2. (The space definitions are in locore.s if you
355: ** want to add anther controller to the system. (good luck))
356: **
357: ** This routine sets the correct page to give kernel write access,
358: ** loads in the appropriate values, and then resets the page to kernel read
359: ** only access to prevent other routines from stepping all over the scp
360: ** and causing obscure tape problems.
361: **
362: ** The format of the system configuration pointer is as follows:
363: **
364: ** 8 bits 8 bits 32 bits (20 that count)
365: ** +----------+----------+----------------+
366: ** | bus size | unused | Pointer to scb |
367: ** +----------+----------+----------------+
368: */
369:
370: cy_init_sys_config_ptr(ctlr)
371: register int ctlr;
372: {
373: register int *pte_ptr;
374: register fmt_scp *SCP = scp_ptrs[ctlr];
375:
376: /* Set the page to kernel write access */
377: pte_ptr = (int *)vtopte(0, btop(SCP));
378: *pte_ptr &= ~PG_PROT; /* clear all protection bits */
379: *pte_ptr |= PG_KW /* allow kernal writes */;
380: mtpr(SCP, TBIS);
381: /* load the correct values in the scp */
382: SCP->bus_size = _16_BITS;
383: load_mbus_addr(&ctlr_info[ctlr].scb, SCP->scb_ptr);
384: /* Give read only privialages to the kernel */
385: *pte_ptr &= ~PG_PROT; /* clear all protection bits */
386: *pte_ptr |= PG_KR; /* allow only kernal */
387: mtpr(SCP, TBIS);
388: }
389:
390:
391: /*
392: ** cy_init_sys_config_blk loads the appropriate values into the
393: ** system configuration block for the Tapemaster controller.
394: **
395: ** This data structure does not contain any useful information
396: ** for us. The only possible use for this block is for a
397: ** consistancy check by the controller itself using the fixed value.
398: ** but that could have been done elsewhere. However the controller will
399: ** not run without it so we maintain this structure here.....
400: **
401: ** The format of the system configuration block is as follows:
402: **
403: ** 8 bits 8 bits 32 bits (20 that count)
404: ** +-----------+----------+----------------+
405: ** | must be 3 | unused | Pointer to ccb |
406: ** +-----------+----------+----------------+
407: */
408:
409: cy_init_sys_config_blk(ctlr)
410: register int ctlr;
411: {
412: register fmt_scb *SCB = &ctlr_info[ctlr].scb;
413:
414: SCB->fixed_value = 0x3;
415: /* set pointer to the channel control block */
416: load_mbus_addr(&ctlr_info[ctlr].ccb, SCB->ccb_ptr);
417: }
418:
419:
420: /*
421: ** Cy_init_channel_control_blk is used to load the initial values into
422: ** the ccb structures for the controller.
423: **
424: ** The format of the channel control block is as follows:
425: **
426: ** 8 bits 8 bits 32 bits (20 that count)
427: ** +-----------+----------+----------------+
428: ** | CCW | gate | Pointer to tpb |
429: ** +-----------+----------+----------------+
430: **
431: ** the CCW field is used to control interupt operations. If the field is
432: ** equal to 11(hex) then interupts are enabled, if it contains a 9(hex) then
433: ** the Tapemaster controller is instructed to stop interupting (it will
434: ** flood the system with interupts until it is instructed to stop!)
435: **
436: ** The gate field is used to syncronize the processor operations and
437: ** the controller. We close it when an operation is started,
438: ** It is opened by the controller when the operation is done.
439: */
440:
441: cy_init_channel_control_blk(ctlr)
442: register int ctlr;
443: {
444: register fmt_ccb *CCB = &ctlr_info[ctlr].ccb;
445:
446: CCB->ccw = CLEAR_INTERUPT;
447: CCB->gate = GATE_OPEN;
448: /* set pointer to the tape parameter block */
449: load_mbus_addr(&ctlr_info[ctlr].tpb, CCB->tpb_ptr);
450: }
451:
452:
453: /*
454: ** Cy_first_TM_attention is used to issue the very first command
455: ** after boot or after the controller is reset. This case is special
456: ** since we 1) should not interupt duing this sequence, 2) really need
457: ** to issue two commands, and 3) we need to get the controller's internal
458: ** buffer size for future reference.
459: **
460: ** The print flag is used so that we only print out the greeting
461: ** message during Autoconfigure time. (it would be obnoxious if it
462: ** printed every time the drive times out.)
463: **
464: ** The first NOOP command is issued to get the drive's attention.
465: ** The tpb is never even looked during the first attention.
466: **
467: ** The second command actually configures the controller and returns
468: ** the internal buffersize for buffered I/O.
469: */
470:
471: cy_first_TM_attention(ctlr_vaddr, ctlr, print)
472: register caddr_t ctlr_vaddr;
473: register int ctlr, print;
474: {
475: register ctlr_tab *c_info = &ctlr_info[ctlr];
476:
477: /* set command to be CONFIGURE */
478: c_info->tpb.cmd = NO_OP;
479: c_info->tpb.control = CW_16bits;
480: c_info->ccb.gate = GATE_CLOSED;
481: CY_ATTENTION(ctlr_vaddr); /* execute! */
482: if(cywait(&c_info->ccb) || (c_info->tpb.status & CS_ERm)) {
483: printf("Tapemaster controller time-out during initialization!\n");
484: return FALSE;
485: }
486: c_info->tpb.cmd = CONFIG;
487: c_info->tpb.control = CW_16bits;
488: c_info->ccb.gate = GATE_CLOSED;
489: CY_ATTENTION(ctlr_vaddr); /* execute! */
490: if(cywait(&c_info->ccb) || (c_info->tpb.status & CS_ERm)) {
491: cyprint_err("Tapemaster configuration failure",
492: 0, c_info->tpb.status);
493: return FALSE;
494: }
495: uncache(&c_info->tpb.count);
496: c_info->bs = MULTIBUS_SHORT(c_info->tpb.count);
497: if(print)
498: printf("Tapemaster with %dkb buffer: controller #",
499: c_info->bs/1024);
500: return TRUE;
501: }
502:
503:
504: /*
505: ** Cyopen is called every time a process opens the tape for reading
506: ** or writting. Tape drives are single access in that only one process
507: ** can have the drive open at any one time. It is responsibility of
508: ** cyopen to keep track of whether the drive is already open and to
509: ** refuse access to everybody else on the system.
510: **
511: ** The other functions of cyopen are to make sure a tape is mounted
512: ** and the drive is on-line, If the drive is currently rewinding we
513: ** should wait for it to complete before returning, if the drive is
514: ** at load point then our internal file pointers are reset, and to
515: ** set up a proto-type control word for use during later tape operations.
516: **
517: ** The control proto-type is set up in open to save time later on.
518: ** It contains all the invariant information the controller needs to
519: ** access a drive. This information includes the unpacked unit number,
520: ** (See the UNIT macro below), the drive speed/density (always set at the
521: ** drive), the buss width (always 16 bit) and the interupts emnable bit
522: ** (always enabled).
523: */
524:
525: /* macro to pack the unit number into Tapemaster format */
526: #define UNIT(d) (((cydinfo[CYUNIT(d)]->ui_slave & 1) << 11) | \
527: ((cydinfo[CYUNIT(d)]->ui_slave & 2) << 9) | \
528: ((cydinfo[CYUNIT(d)]->ui_slave & 4) >> 2))
529:
530: cyopen(dev, flag)
531: register int flag;
532: register dev_t dev;
533: {
534: register int status, unit = CYUNIT(dev);
535: register unit_tab *u_info = &unit_info[unit];
536:
537: if (!(status = cyvalid_drive(unit))) {
538: u_info->control_proto = UNIT(dev) | CW_INTR | CW_16bits;
539: u_info->blkno = 0;
540: u_info->bad_count = 0;
541: u_info->eof = FALSE;
542: u_info->open = TRUE;
543: if(status = cy_open_error(dev,flag))
544: u_info->open = FALSE;
545: }
546: return status;
547: }
548:
549:
550: /*
551: ** cyvalid_drive is called to make sure a drive is attached to
552: ** to the system and, if it is, if it is already open by another process.
553: ** If the drive is already open busy status is returned, if it is not
554: ** attached to the system then non-existant device is returned, otherwise,
555: ** zero is returned to indicate no error.
556: */
557:
558: cyvalid_drive(unit)
559: register int unit;
560: {
561: /* if unit is less than maximum possible unit */
562: if (unit < NUM_UNIT)
563: /* if the drive is attached */
564: if (cydinfo[unit])
565: /* if drive is not already open */
566: if(!unit_info[unit].open)
567: return NOERROR;
568: else
569: return EBUSY;
570: return ENXIO;
571: }
572:
573:
574: /*
575: ** Cy_open_error is called by open after verifing that the drive
576: ** is eligable to be opened. The hardware status is checked and if
577: ** any errors are found (i.e. not online, write protected when opened for
578: ** writes, and opening past the end of tape marker) then the error number
579: ** is returned.
580: **
581: ** As part of the sequence we must wait around if the drive is online
582: ** and rewinding until the rewind is done or the operator takes the drive
583: ** offline. During the wait we poll the drive every 5 seconds until
584: ** either of the above conditions are met.
585: */
586:
587: cy_open_error(dev,flag)
588: register int flag;
589: register dev_t dev;
590: {
591: register int unit = CYUNIT(dev);
592: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
593: register ctlr_tab *c_info = &ctlr_info[cydinfo[unit]->ui_ctlr];
594:
595: cycmd(dev, DO_WAIT, 1);
596: if(!(u_info->last_status & CS_OL))
597: return ENXIO;
598: if((flag & FWRITE) && (u_info->last_status & CS_P)) {
1.1.1.2 ! root 599: uprintf("\ncy%d: Tape is write protected!\n", unit);
1.1 root 600: return ENXIO;
601: }
602: if(u_info->last_status & CS_LP) {
603: u_info->file_number = 0;
604: u_info->bot = TRUE;
605: u_info->eof = u_info->eot = FALSE;
606: }
607: return NOERROR;
608: }
609:
610:
611: /*
612: ** Cyclose is called every time a process closes a tape file, exits,
613: ** or is otherwise removed for the run queue. We take this oportunity to
614: ** mark the drive closed, write end of volume records (two tape marks), and
615: ** rewind the tape (if requested that we do so).
616: **
617: ** Take note that we write the end of volume records by spacing backwards.
618: ** This is done because the all the commands keep track of the necessary
619: ** special cases. It just so happens that spacing back after a write will
620: ** generate an end of volume record before spacing back. After the space back
621: ** is called we space forward to position ourselfs between the two filemarks
622: ** in anticipation of further writes to tape.
623: **
624: ** Also, the rewind logic takes care of end of volume records so if
625: ** we just issue a overlapped rewind request if we were opened using
626: ** the rewinding special file.
627: */
628:
629: cyclose(dev, flag)
630: register dev_t dev;
631: register flag;
632: {
633: register int unit = CYUNIT(dev);
634: register unit_tab *u_info = &unit_info[unit];
635:
636: if(u_info->last_status & CS_OL)
637: if((flag & FWRITE) && (minor(dev) & T_NOREWIND))
638: cycmd(dev, DO_WEOV, 1);
639: else if(!(minor(dev) & T_NOREWIND))
640: cycmd(dev, DO_RWOV, 1);
641: if(u_info->bad_count != 0) {
642: u_info->bad_count *= 889;
1.1.1.2 ! root 643: uprintf("\ncy%d: Warning - %d.%dcm of tape were used for recovering bad spots.\n", unit, u_info->bad_count/100, u_info->bad_count%100);
1.1 root 644: u_info->bad_count = 0;
645: }
646: u_info->open = 0;
647: }
648:
649:
650: /*
651: ** Cycmd is used intrernally to implement all the ioctl functions
652: ** that are needed by the driver. We duplicate the code in physio
653: ** that is used for syncronizing the processes (sleep / wakeup) so
654: ** that we can treat our internal command requests exactly like
655: ** regular reads and writes. They get put on the controller queue,
656: ** start processes them and iodone is called to wake us up on completion.
657: **
658: ** We don't call physio directly because it expects data to be moved
659: ** and has a lot more overhead than we really need.
660: */
661:
662: cycmd(dev, command, count)
663: register dev_t dev;
664: register long command;
665: register int count;
666: {
667: register int unit = CYUNIT(dev);
668: register unit_tab *u_info = &unit_info[unit];
669: register unsigned short error;
670: register int priority = spl3();
671:
672: while (u_info->rawbp.b_flags & B_BUSY) {
673: u_info->rawbp.b_flags |= B_WANTED;
674: sleep(&u_info->rawbp, PRIBIO+1);
675: }
676: splx(priority);
677:
678: /* load the request queue element */
679: u_info->rawbp.b_error = 0;
680: u_info->rawbp.b_dev = dev;
681: u_info->rawbp.b_cmd = (struct buf *)command;
682: u_info->rawbp.b_bcount = count;
683: u_info->rawbp.b_flags = B_PHYS | B_BUSY;
684: queue_request(&u_info->rawbp, &u_info->u_queue, cydinfo[unit]->ui_mi);
685:
686: /* wait for operation to complete */
687: while(!(u_info->rawbp.b_flags & B_DONE))
688: sleep(&u_info->rawbp, PRIBIO);
689: u_info->rawbp.b_flags &= ~(B_PHYS | B_BUSY);
690: if(u_info->rawbp.b_flags & B_WANTED)
691: wakeup (&u_info->rawbp);
692: return geterror(&u_info->rawbp);
693: }
694:
695: /*
696: ** Check the validity of the request and then place
697: ** the request on the controller's request queue if it is ok.
698: **
699: ** Take note that the only validity check is the block size.
700: ** all other checking, such as, drive number, online, controller attached,
701: ** is done in the open routine.
702: **
703: ** If the drive dropped offline this will be notced int the
704: ** start / interupt routine (depending on when it dropped offline).
705: */
706:
707: cystrategy(request)
708: register struct buf *request;
709: {
710: register int unit = CYUNIT(request->b_dev);
711: register unit_tab *u_info = &unit_info[unit];
712: register struct buf *unit_queue;
713:
714: /* check the validity of the request */
715: if (request->b_bcount <= MAX_BLOCKSIZE) {
716: /* place request on queue and start it if everything is ok */
717: unit_queue = &u_info->u_queue;
718: buf_setup(request, MAX_BLOCKSIZE);
719: if(request->b_flags & B_PHYS)
720: if(request->b_flags & B_READ)
721: request->b_cmd = (struct buf *)DO_RRD;
722: else
723: request->b_cmd = (struct buf *)DO_RWT;
724: else
725: if(request->b_flags & B_READ)
726: request->b_cmd = (struct buf *)DO_BRD;
727: else {
728: request->b_cmd = (struct buf *)DO_BWT;
729:
730: }
731: queue_request(request, unit_queue, cydinfo[unit]->ui_mi);
732: return;
733: }
1.1.1.2 ! root 734: uprintf("\ncy%d: Maximum block size is %dk!\n", unit, MAX_BLOCKSIZE/1024);
1.1 root 735: request->b_error = EIO;
736: request->b_resid = request->b_bcount;
737: request->b_flags |= B_ERROR;
738: iodone(request);
739: }
740:
741:
742: /*
743: ** The routines below are used to handle a unit's request queue.
744: ** The queue is a linked list of buf structures. The linkage is as follows:
745: **
746: ** +------------------------------------------------+
747: ** | v
748: ** | +-----------+ +-----------+ +-----------+
749: ** | | av_forw |------>| av_forw |--~ ~-->| av_forw |-->NULL
750: ** | +-----------+ +-----------+ +-----------+
751: ** +-| av_back | | ......... | | ......... |
752: ** +-----------+ +-----------+ +-----------+
753: ** | ......... | First queue Last queue
754: ** +-----------+ element element
755: ** head of unit queue
756: ** (unit_tab[unit].queue)
757: */
758:
759: /*
760: ** Queue_request places a queue element on the end of a unit's
761: ** request queue.
762: */
763:
764: queue_request(request, unit_queue, vba_ctlr_info)
765: register struct buf *request;
766: register struct buf *unit_queue;
767: struct vba_ctlr *vba_ctlr_info;
768: {
769: register int priority = spl3();
770:
771: request->av_forw = NULL;
772: if (unit_queue->av_forw == NULL)
773: unit_queue->av_forw = request;
774: else
775: unit_queue->av_back->av_forw = request;
776: unit_queue->av_back = request;
777: cystart(vba_ctlr_info, request, priority);
778: }
779:
780:
781: /*
782: ** Dequeue_request removes the first element in a unit's request queue.
783: */
784:
785: dequeue_request(unit_queue)
786: register struct buf *unit_queue;
787: {
788: register int priority = spl3();
789:
790: if ((unit_queue->av_forw = unit_queue->av_forw->av_forw) == NULL)
791: unit_queue->av_back = NULL;
792: splx(priority);
793: }
794:
795:
796: /*
797: ** Cystart is called once for every request that is placed on a
798: ** controller's queue. Start is responsible for fetching requests for
799: ** a controller queue, starting the operation, and waiting for completion,
800: ** and releasing the buf structure back to UNIX or cycmd, before fetching
801: ** the next request.
802: **
803: ** The controller's queue looks like this:
804: **
805: ** +---------------------------------------+
806: ** | |
807: ** +-----------+ | +-----------+ +-----------+ |
808: ** | b_forw |---+-->| b_forw |--~ ~-->| b_forw |--+
809: ** +-----------+ +-----------+ +-----------+
810: ** | b_back | | ......... | | ......... |
811: ** +-----------+ +-----------+ +-----------+
812: ** | ......... | First unit queue Last unit queue
813: ** +-----------+ element element
814: ** head of controller queue
815: ** (cyminfo[ctlr].um_tab)
816: **
817: ** To access the unit queues we simply get the controller's unit queue
818: ** pointer and if anything is on the unit queue that we are pointing to
819: ** we start that command, otherwise we get the next pointer and go on.
820: ** we know to stop looking when we have gone through the entire list
821: ** without starting any activity. We know we are at the end of the
822: ** queue when the next pointer equals the original pointer int the queue.
823: **
824: ** To provind a fair scheduling policy we simply repoint the controller's
825: ** queue pointer to the next unit queue every time a command is started.
826: **
827: ** If the controller is currently busy then we just return so that the
828: ** calling routine can go to sleep until we are finished processing the
829: ** request.
830: **
831: ** Each buf structure has an index into a jump table loaded into
832: ** it by strategy or cycmd depending on where the buff originated.
833: ** this index is loaded so that start processing can continue without
834: ** much delay, and so that each operation can have it's unique requirements
835: ** satisfied in a clear and consistent manor.
836: **
837: ** Each and every routine that is called by start is responsible for
838: ** proper tape positioning, writting end of file marks correctly, error
839: ** recovery, and whatever else may unique about the particular operation.
840: ** Each routine calls cyexecute whenever it actually wants to issue a
841: ** command to the controller. Each routine is also responsible for releasing
842: ** the request when is is done with it.
843: */
844:
845: cystart(vba_ctlr_info, request, priority)
846: register struct vba_ctlr *vba_ctlr_info;
847: register struct buf *request;
848: {
849: struct buf *cyget_next();
850: extern int cystart_timeout();
851: register int unit = CYUNIT(request->b_dev);
852: register int ctlr = vba_ctlr_info->um_ctlr;
853: register struct buf *next, *ctlr_queue = &vba_ctlr_info->um_tab;
854: register unit_tab *u_info = &unit_info[unit];
855: register ctlr_tab *c_info = &ctlr_info[ctlr];
856:
857: if(ctlr_queue->b_active & SLEEPING) {
858: untimeout(cystart_timeout, ctlr_queue);
859: cystart_timeout(ctlr_queue);
860: }
861: if(ctlr_queue->b_active) {
862: sleep(request, PRIBIO-1);
863: if(request->b_flags & PROCESSED) {
864: if(u_info->message != NULL) {
1.1.1.2 ! root 865: uprintf("\ncy%d: %s!\n", unit, u_info->message);
1.1 root 866: u_info->message = NULL;
867: }
868: request->b_flags &= ~PROCESSED;
869: iodone(request);
870: return;
871: }
872: }
873: ctlr_queue->b_active = TRUE;
874: splx(priority);
875: c_info->my_request = request;
876: cydo_my_command(ctlr, ctlr_queue, c_info);
877: if(u_info->message != NULL) {
1.1.1.2 ! root 878: uprintf("\ncy%d: %s!\n", unit, u_info->message);
1.1 root 879: u_info->message = NULL;
880: }
881: request->b_flags &= ~PROCESSED;
882: iodone(request);
883: if((next = cyget_next(ctlr_queue)) != NULL)
884: wakeup(next);
885: else
886: ctlr_queue->b_active = FALSE;
887: }
888:
889:
890: /*
891: ** Cystart_timeout wakes up the start routine after it's 3
892: ** second wait time is up or when a new command enters the queue.
893: **
894: ** The timer is used to give up the processor while all drives
895: ** on the queue are rewinding and we need to wait for them to be dome.
896: ** Without this feature we would hog the processor polling for the drives
897: ** to be done.
898: */
899:
900: cystart_timeout(ctlr_queue)
901: register struct buf *ctlr_queue;
902: {
903: ctlr_queue->b_active &= ~SLEEPING;
904: wakeup(ctlr_queue);
905: }
906:
907:
908: /*
909: ** Cydo_my command scans the request queues once for a
910: ** particular controller and calls the appropriate processing routine
911: ** each time we find a request that can be started.
912: **
913: ** We return TRUE if a command is executed during this round. IF either
914: ** the queue is empty or all commands on the queue are waiting for the drives
915: ** to rewind we return FALSE.
916: */
917:
918: cydo_my_command(ctlr, ctlr_queue, c_info)
919: register struct buf *ctlr_queue;
920: register ctlr_tab *c_info;
921: {
922: struct buf *cyget_next();
923: register struct buf *unit_queue, *next;
924:
925: while((next = cyget_next(ctlr_queue)) != NULL) {
926: if(ctlr_queue->b_forw->b_active & SLEEPING) {
927: ctlr_queue->b_active |= SLEEPING;
928: timeout(cystart_timeout, ctlr_queue, 1*60);
929: sleep(ctlr_queue, PRIBIO);
930: continue;
931: }
932: if(setjmp(&ctlr_info[ctlr].environ))
933: cydone(ctlr_queue);
934: else {
935: register int cmd=(int)(next->b_cmd);
936:
937: (*cmd_tbl[cmd])(next, ctlr_queue);
938: }
939: if(next->b_flags & PROCESSED)
940: if(c_info->my_request != next)
941: wakeup(next);
942: else
943: return;
944: }
945: }
946:
947:
948: struct buf *cyget_next(ctlr_queue)
949: register struct buf *ctlr_queue;
950: {
951: register struct buf *request, *unit_queue, *next = NULL;
952:
953: ctlr_queue->b_forw = ctlr_queue->b_forw->b_forw;
954: unit_queue = ctlr_queue->b_forw;
955: do {
956: if((request = unit_queue->av_forw) != NULL)
957: if(!(unit_queue->b_active & SLEEPING)) {
958: ctlr_queue->b_forw = unit_queue;
959: return request;
960: }
961: else
962: next = unit_queue;
963: unit_queue = unit_queue->b_forw;
964: } while(unit_queue != ctlr_queue->b_forw);
965: if(next != NULL) {
966: ctlr_queue->b_forw = next;
967: return next->av_forw;
968: }
969: return NULL;
970: }
971:
972:
973: /*
974: ** Cydone is called by each routine that is thorugh processing a
975: ** user request. It removes the request from our queues, counts down
976: ** the number of active requests that we have in our queues and releases
977: ** the request back to UNIX.
978: */
979:
980: cydone(ctlr_queue)
981: register struct buf *ctlr_queue;
982: {
983: register struct buf *unit_queue = ctlr_queue->b_forw;
984: register struct buf *request = unit_queue->av_forw;
985: register int unit = CYUNIT(request->b_dev);
986: register ctlr_tab *c_info = &ctlr_info[cydinfo[unit]->ui_ctlr];
987:
988: unit_queue->av_forw->b_flags |= PROCESSED;
989: dequeue_request(unit_queue);
990: }
991:
992:
993: /*
994: ** All the routines between here and Cyintr are used to process the
995: ** individual commands (read, write, rewind, ...) that can possibly be
996: ** generated by the system.
997: **
998: ** Each command is responsible for a few things. 1) Each has to keep
999: ** track of special cases that are related to the individual command and
1000: ** the previous commands sequence, 2) each is required to call iodone when
1001: ** command is actually finished, 3) it must use cyexecute to actually
1002: ** start the controller, and 4) they are required to keep the tape in
1003: ** a consistant state so that other commands will not be messed up.
1004: /*
1005: */
1006:
1007: /*
1008: ** cyraw_read handles the read requests from the raw device (cyread).
1009: **
1010: ** The special cases are:
1011: ** 1) we can not read after a write. (writting defines end of file)
1012: ** 2) reading past end of file returns 0 bytes;
1013: */
1014:
1015: cyraw_read(request, ctlr_queue)
1016: register struct buf *request;
1017: register struct buf *ctlr_queue;
1018: {
1019: register int unit = CYUNIT(request->b_dev);
1020: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1021: register int ctlr = cydinfo[unit]->ui_ctlr;
1022: register ctlr_tab *c_info = &ctlr_info[ctlr];
1.1.1.2 ! root 1023: register int addr, lock_flag, command, bytes;
! 1024:
! 1025: if(u_info->cleanup != cyno_op) {
1.1 root 1026: request->b_resid = request->b_bcount;
1027: request->b_error = ENXIO, request->b_flags |= B_ERROR;
1.1.1.2 ! root 1028: longjmp(&c_info->environ);
! 1029: }
! 1030: if(u_info->eof){
! 1031: u_info->blkno = 0;
! 1032: u_info->file_number++;
1.1 root 1033: }
1.1.1.2 ! root 1034:
1.1 root 1035: if(request->b_bcount > c_info->bs)
1036: command = READ_TA, lock_flag = CW_LOCK;
1037: else
1038: command = READ_BU, lock_flag = 0;
1039: u_info->blkno++;
1040: addr = get_ioadr(request,c_info->rawbuf,c_info->map,c_info->utl);
1041: cyexecute(command, request->b_bcount, addr, lock_flag, unit, 10, FALSE);
1042: end_transfer(request, c_info->rawbuf, c_info->map, c_info->utl);
1.1.1.2 ! root 1043: if((bytes = MULTIBUS_SHORT(c_info->tpb.rec_over)) > request->b_bcount) {
! 1044: uprintf(long_block_msg, unit, bytes, request->b_bcount);
! 1045: request->b_error = ENXIO, request->b_flags |= B_ERROR;
! 1046: longjmp(&c_info->environ);
! 1047: }
1.1 root 1048: cydone(ctlr_queue);
1049: }
1050:
1051:
1052: /*
1053: ** cyraw_write handles the write requests from the raw device.
1054: **
1055: ** The special cases are:
1056: ** 1) we don't allow writes after end of tape is reached.
1057: */
1058:
1059: cyraw_write(request, ctlr_queue)
1060: register struct buf *request;
1061: register struct buf *ctlr_queue;
1062: {
1063: register int unit = CYUNIT(request->b_dev);
1064: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1065: register int ctlr = cydinfo[unit]->ui_ctlr;
1066: register ctlr_tab *c_info = &ctlr_info[ctlr];
1067: register int addr, lock_flag, command;
1068:
1069: if(u_info->eot) {
1070: request->b_resid = request->b_bcount;
1071: request->b_error = ENXIO, request->b_flags |= B_ERROR;
1072: longjmp(&c_info->environ);
1073: }
1074: u_info->cleanup = cywrite_2_fm;
1075: if(request->b_bcount > c_info->bs)
1076: command = WRIT_TA, lock_flag = CW_LOCK;
1077: else
1078: command = WRIT_BU, lock_flag = 0;
1079: u_info->blkno++;
1080: addr = get_ioadr(request,c_info->rawbuf,c_info->map,c_info->utl);
1081: cyexecute(command, request->b_bcount, addr, lock_flag, unit, 10, FALSE);
1082: end_transfer(request, c_info->rawbuf, c_info->map, c_info->utl);
1083: cydone(ctlr_queue);
1084: }
1085:
1086:
1087: /*
1088: ** cywrite_filemark processes the ioctl to write filemarks to tape.
1089: */
1090:
1091: cywrite_filemark(request, ctlr_queue)
1092: register struct buf *request;
1093: register struct buf *ctlr_queue;
1094: {
1095: register int unit = CYUNIT(request->b_dev);
1096: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1097: register int ctlr = cydinfo[unit]->ui_ctlr;
1098: register ctlr_tab *c_info = &ctlr_info[ctlr];
1099:
1100: if(request->b_bcount) {
1101: request->b_bcount--;
1102: if(u_info->cleanup == cywrite_1_fm)
1103: u_info->cleanup = cywrite_0_fm;
1104: if((u_info->cleanup==cywrite_2_fm)||(u_info->cleanup==cyno_op))
1105: u_info->cleanup = cywrite_1_fm;
1106: u_info->file_number++;
1107: u_info->eof = TRUE;
1108: u_info->blkno = 0;
1109: cyexecute(WRIT_FM, (short)1, 0, 0, unit, 10, FALSE);
1110: return;
1111: }
1112: cydone(ctlr_queue);
1113: }
1114:
1115:
1116: /*
1117: ** cysearch_fm_forw is the ioctl to search for a filemark in the
1118: ** forward direction on tape.
1119: **
1120: ** Since only one device can be active on a given controller at any
1121: ** given instant in time, we try to be nice and let onther devices on
1122: ** this controller be scheduled after we space over each record. This will
1123: ** at least give the apperance of overlapped operations on the controller.
1124: **
1125: ** The special cases are:
1126: ** 1) if the last command was a write the we can't search.
1127: */
1128:
1129: cysearch_fm_forw(request, ctlr_queue)
1130: register struct buf *request;
1131: register struct buf *ctlr_queue;
1132: {
1133: register int unit = CYUNIT(request->b_dev);
1134: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1135: register int ctlr = cydinfo[unit]->ui_ctlr;
1136: register ctlr_tab *c_info = &ctlr_info[ctlr];
1137:
1138: if((u_info->cleanup != cyno_op) || u_info->eot) {
1139: request->b_resid = request->b_bcount;
1140: request->b_error = ENXIO, request->b_flags |= B_ERROR;
1141: longjmp(&c_info->environ);
1142: }
1143: if(request->b_bcount && !u_info->eot) {
1144: if(!u_info->eot) {
1145: u_info->blkno++;
1146: cyexecute(SPAC_FM, 1, 0, 0, unit, 5, FALSE);
1147: if(!(u_info->eof || u_info->eot))
1148: return;
1149: }
1150: request->b_bcount--;
1151: u_info->eof = FALSE;
1152: if(!u_info->eot) {
1153: u_info->file_number++;
1154: u_info->blkno = 0;
1155: return;
1156: }
1157: }
1158: if(u_info->eot) {
1159: request->b_resid = request->b_bcount;
1160: request->b_flags |= B_ERROR, request->b_error = ENXIO;
1161: }
1162: cydone(ctlr_queue);
1163: }
1164:
1165:
1166: /*
1167: ** cysearch_fm_back is the ioctl to search for a filemark in the
1168: ** reverse direction on tape.
1169: **
1170: ** Since only one device can be active on a given controller at any
1171: ** given instant in time, we try to be nice and let onther devices on
1172: ** this controller be scheduled after we space over each record. This will
1173: ** at least give the apperance of overlapped operations on the controller.
1174: **
1175: ** The special cases are:
1176: ** 1) can't search past begining of tape.
1177: ** 2) if the lasr operation was a write data then we need to add
1178: ** an end of volume record before we start searching.
1179: */
1180:
1181: cysearch_fm_back(request, ctlr_queue)
1182: register struct buf *request;
1183: register struct buf *ctlr_queue;
1184: {
1185: register int unit = CYUNIT(request->b_dev);
1186: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1187: register int ctlr = cydinfo[unit]->ui_ctlr;
1188: register ctlr_tab *c_info = &ctlr_info[ctlr];
1189:
1190: if(!u_info->bot) {
1191: (*u_info->cleanup)(unit, MAINTAIN_POSITION);
1192: if(u_info->blkno == 0)
1193: request->b_bcount++;
1194: u_info->blkno = 0xffffffff;
1195: if(request->b_bcount && !u_info->bot) {
1196: cyexecute(SPAC_FM, 1, 0, CW_REV, unit, 6, FALSE);
1197: if(u_info->eof) {
1198: u_info->eof = FALSE;
1199: u_info->file_number--;
1200: request->b_bcount--;
1201: }
1202: return;
1203: }
1204: if(u_info->bot) {
1205: u_info->file_number = 0;
1206: if(request->b_bcount) {
1207: request->b_resid = request->b_bcount;
1208: request->b_error = ENXIO;
1209: request->b_flags |= B_ERROR;
1210: }
1211: }
1212: else {
1213: request->b_cmd = (struct buf *)DO_SFMF;
1214: request->b_bcount = 1;
1215: return;
1216: }
1217: }
1218: u_info->blkno = 0;
1219: u_info->eof = FALSE;
1220: cydone(ctlr_queue);
1221: }
1222:
1223:
1224: /*
1225: ** cy_space_forw is used to search forward a given number of records on
1226: ** tape.
1227: **
1228: ** Since only one device can be active on a given controller at any
1229: ** given instant in time, we try to be nice and let onther devices on
1230: ** this controller be scheduled after we space over each record. This will
1231: ** at least give the apperance of overlapped operations on the controller.
1232: **
1233: ** The special cases are:
1234: ** 1) we can't space over a filemark.
1235: ** 2) if the last command was a write data or filemark we can't space forward.
1236: */
1237:
1238: cy_space_forw(request, ctlr_queue)
1239: register struct buf *request;
1240: register struct buf *ctlr_queue;
1241: {
1242: register int unit = CYUNIT(request->b_dev);
1243: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1244: register int ctlr = cydinfo[unit]->ui_ctlr;
1245: register ctlr_tab *c_info = &ctlr_info[ctlr];
1246:
1247: if((u_info->cleanup != cyno_op) || u_info->eof) {
1248: request->b_resid = request->b_bcount;
1249: request->b_error = ENXIO, request->b_flags |= B_ERROR;
1250: longjmp(&c_info->environ);
1251: }
1252: if(request->b_bcount) {
1253: u_info->blkno++;
1254: cyexecute(SPAC_FM, 1, 0, 0, unit, 10, FALSE);
1255: if(!u_info->eof && request->b_bcount) {
1256: request->b_bcount--;
1257: return;
1258: }
1259: }
1260: if(u_info->eof) {
1261: request->b_resid = request->b_bcount;
1262: request->b_error = ENXIO, request->b_flags |= B_ERROR;
1263: }
1264: cydone(ctlr_queue);
1265: }
1266:
1267:
1268: /*
1269: ** Cy_space_back spaces backward a given number of records.
1270: **
1271: ** Since only one device can be active on a given controller at any
1272: ** given instant in time, we try to be nice and let onther devices on
1273: ** this controller be scheduled after we space over each record. This will
1274: ** at least give the apperance of overlapped operations on the controller.
1275: **
1276: ** The special cases are:
1277: ** 1) we can't space over a filemark.
1278: ** 2) we can't space past the beginning of tape.
1279: ** 3) if the last operation was a write data then we need to add
1280: ** an end of volume record before we start searching.
1281: */
1282:
1283: cy_space_back(request, ctlr_queue)
1284: register struct buf *request;
1285: register struct buf *ctlr_queue;
1286: {
1287: register int unit = CYUNIT(request->b_dev);
1288: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1289: register int ctlr = cydinfo[unit]->ui_ctlr;
1290: register ctlr_tab *c_info = &ctlr_info[ctlr];
1291:
1292: if(!u_info->bot) {
1293: (*u_info->cleanup)(unit, MAINTAIN_POSITION);
1294: if(request->b_bcount+1 && !u_info->bot && !u_info->eof) {
1295: request->b_bcount--;
1296: u_info->blkno--;
1297: cyexecute(SPACE, 1, 0, CW_REV, unit, 15, FALSE);
1298: return;
1299: }
1300: if(!u_info->bot) {
1301: request->b_bcount = 1;
1302: cy_space_forw(request);
1303: }
1304: u_info->eof = FALSE;
1305: }
1306: cydone(ctlr_queue);
1307: }
1308:
1309:
1310: /*
1311: ** cyrewind_tape_ta does a waiting rewind to of the tape.
1312: **
1313: ** An overlapped rewind is issued and then we change the command type to
1314: ** a wait for ready ioctl. Wait for ready contains the logic to poll
1315: ** without blocking anything in the system, until the drive becomes ready or
1316: ** drops off line whichever comes first.
1317: */
1318:
1319: cyrewind_tape_ta(request, ctlr_queue)
1320: register struct buf *request;
1321: register struct buf *ctlr_queue;
1322: {
1323: cyrewind_tape(request, REWD_OV);
1324: request->b_cmd = (struct buf *)DO_WAIT;
1325: }
1326:
1327:
1328: /*
1329: ** cyrewind_tape_unl does an overlapped rewind and then unloads the
1330: ** tape after the tape completes the rewind. This feature is handled by
1331: ** the individual tape drive and in some cases can not unload a tape. In
1332: ** this case it acts exactly like an overlapped rewind.
1333: */
1334:
1335: cyrewind_tape_unl(request, ctlr_queue)
1336: register struct buf *request;
1337: register struct buf *ctlr_queue;
1338: {
1339: cyrewind_tape(request, OFF_UNL);
1340: cydone(ctlr_queue);
1341: }
1342:
1343:
1344: /*
1345: ** cyrewind_tape_ov is used to do overlapped rewinds on the system.
1346: ** Close is a classic example of where an overlapped rewind is needed.
1347: ** It would be stupid in that case to force the user to wait around
1348: ** (up to 5 minutes) until the tape has finished rewind.
1349: */
1350:
1351: cyrewind_tape_ov(request, ctlr_queue)
1352: register struct buf *request;
1353: register struct buf *ctlr_queue;
1354: {
1355: cyrewind_tape(request, REWD_OV);
1356: cydone(ctlr_queue);
1357: }
1358:
1359: /*
1360: ** cyrewind tape is the common code for all rewind commands.
1361: **
1362: ** The special cases are:
1363: ** 3) if the last operation was a write data then we need to add
1364: ** an end of volume record before we start searching.
1365: */
1366:
1367: cyrewind_tape(request, command)
1368: register struct buf *request;
1369: long command;
1370: {
1371: register int unit = CYUNIT(request->b_dev);
1372: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1373: register int ctlr = cydinfo[unit]->ui_ctlr;
1374: register ctlr_tab *c_info = &ctlr_info[ctlr];
1375: register int time = (command == REWD_OV) ? 10 : 10*60;
1376:
1377: (*u_info->cleanup)(unit, DONT_MAINTAIN_POSITION);
1378: u_info->blkno = 0;
1379: u_info->eof = FALSE;
1380: u_info->bot = TRUE;
1381: u_info->eot = FALSE;
1382: u_info->file_number = 0;
1383: request->b_resid = 0;
1384: u_info->cleanup = cyno_op;
1385: cyexecute(command, 0, 0, 0, unit, time, FALSE);
1386: }
1387:
1388:
1389: /*
1390: ** Cywait_until_ready is used to wait for rewinds to complete.
1391: ** We check the status and if the tape is still rewinding we re-enter ourself
1392: ** on the activity queue to give other requests a chance to execute before we
1393: ** check the status again. One other thing is that we only want to check
1394: ** the status every five seconds. so we set a timer for five seconds and
1395: ** check the time left every time we enter this routine. If there is still
1396: ** time left then we simply reinsert ourself on the queue again and wait
1397: ** until next time ..
1398: */
1399:
1400:
1401: cywait_until_ready(request, ctlr_queue)
1402: register struct buf *request;
1403: register struct buf *ctlr_queue;
1404: {
1405: extern int cywait_timeout();
1406: register int unit = CYUNIT(request->b_dev);
1407: register int ctlr = cydinfo[unit]->ui_ctlr;
1408: register unit_tab *u_info = &unit_info[unit];
1409:
1410: cyexecute(DRIVE_S, 0, 0, 0, unit, 10, FALSE);
1411: if((!(u_info->last_status & CS_OL)) || (u_info->last_status & CS_RDY)) {
1412: cydone(ctlr_queue);
1413: return;
1414: }
1415: ctlr_queue->b_forw->b_active |= SLEEPING;
1416: timeout(cywait_timeout, ctlr_queue->b_forw, 2*60);
1417: }
1418:
1419:
1420: /*
1421: ** cywait_timeout resets the timing flag for nice_wait after 3 seconds
1422: ** is up. This makes this drive eligible for scheduling again.
1423: */
1424:
1425: cywait_timeout(unit_queue)
1426: struct buf *unit_queue;
1427: {
1428: unit_queue->b_active &= ~SLEEPING;
1429: }
1430:
1431:
1432: /*
1433: ** cydrive_status is used to process the status ioctl request.
1434: ** it depends entirly on the interupt routines to load the last_XXX
1435: ** registers in unit_info[].
1436: */
1437:
1438: cydrive_status(request, ctlr_queue)
1439: register struct buf *request;
1440: register struct buf *ctlr_queue;
1441: {
1442: register int unit = CYUNIT(request->b_dev);
1443: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1444: register int ctlr = cydinfo[unit]->ui_ctlr;
1445: register ctlr_tab *c_info = &ctlr_info[ctlr];
1446:
1447: cyexecute(DRIVE_S, 0, 0, 0, unit, 10, FALSE);
1448: cydone(ctlr_queue);
1449: }
1450:
1451:
1452: /*
1453: ** cybuf_read handles the read requests from the block device.
1454: **
1455: ** The special cases are:
1456: ** 1) we can not read after a write. (writting defines end of file)
1457: ** 2) reading past end of file returns 0 bytes;
1458: ** 3) if we are mispositioned we have to seek to the correct block.
1459: ** 4) we can hit end of tape while seeking.
1460: ** 5) we want to be nice to other processes while seeking so we
1461: ** break the request up into smaller requests.
1462: ** 6) returns error if the block was larger than requested.
1463: */
1464:
1465: cybuf_read(request, ctlr_queue)
1466: register struct buf *request;
1467: register struct buf *ctlr_queue;
1468: {
1469: register int unit = CYUNIT(request->b_dev);
1470: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1471: register int ctlr = cydinfo[unit]->ui_ctlr;
1472: register ctlr_tab *c_info = &ctlr_info[ctlr];
1.1.1.2 ! root 1473: register int addr, command, bus_lock, bytes;
1.1 root 1474:
1.1.1.2 ! root 1475: if(u_info->cleanup != cyno_op) {
! 1476: request->b_error = ENXIO, request->b_flags |= B_ERROR;
! 1477: request->b_resid = request->b_bcount;
! 1478: longjmp(&c_info->environ);
! 1479: }
1.1 root 1480: if(cyseek(request, ctlr_queue)) {
1481: if(request->b_bcount > c_info->bs)
1482: command = READ_TA, bus_lock = CW_LOCK;
1483: else
1484: command = READ_BU, bus_lock = 0;
1485: u_info->blkno++;
1486: addr=get_ioadr(request,c_info->rawbuf,c_info->map,c_info->utl);
1487: cyexecute(command,request->b_bcount,addr,bus_lock,unit,8,FALSE);
1488: end_transfer(request, c_info->rawbuf, c_info->map, c_info->utl);
1.1.1.2 ! root 1489: if((bytes=MULTIBUS_SHORT(c_info->tpb.rec_over))>request->b_bcount) {
! 1490: uprintf(long_block_msg,unit,bytes,request->b_bcount);
! 1491: request->b_error = ENXIO, request->b_flags |= B_ERROR;
! 1492: longjmp(&c_info->environ);
! 1493: }
1.1 root 1494: cydone(ctlr_queue);
1495: }
1496: }
1497:
1498:
1499: /*
1500: ** cybuf_write handles the write requests from the block device.
1501: **
1502: ** The special cases are:
1503: ** 1) if we are mispositioned we have to seek to the correct block.
1504: ** 2) we can hit end of tape while seeking.
1505: ** 3) we want to be nice to other processes while seeking so we
1506: ** break the request up into smaller requests.
1507: ** 4) we don't allow writes after end of tape is reached.
1508: */
1509:
1510: cybuf_write(request, ctlr_queue)
1511: register struct buf *request;
1512: register struct buf *ctlr_queue;
1513: {
1514: register int unit = CYUNIT(request->b_dev);
1515: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1516: register int ctlr = cydinfo[unit]->ui_ctlr;
1517: register ctlr_tab *c_info = &ctlr_info[ctlr];
1518: register int addr, command, bus_lock;
1519:
1520: if(u_info->eot && (request->b_blkno >= u_info->blkno)) {
1521: request->b_error = ENXIO, request->b_flags |= B_ERROR;
1522: request->b_resid = request->b_bcount;
1523: longjmp(&c_info->environ);
1524: }
1525: if(cyseek(request, ctlr_queue)) {
1526: u_info->cleanup = cywrite_2_fm;
1527: u_info->blkno++;
1528: if(request->b_bcount > c_info->bs)
1529: command = WRIT_TA, bus_lock |= CW_LOCK;
1530: else
1531: command = WRIT_BU, bus_lock = 0;
1532: addr=get_ioadr(request,c_info->rawbuf,c_info->map,c_info->utl);
1533: load_mbus_addr((char *)addr, &c_info->tpb.data_ptr);
1534: cyexecute(command,request->b_bcount,addr,bus_lock,unit,5,FALSE);
1535: end_transfer(request, c_info->rawbuf, c_info->map, c_info->utl);
1536: cydone(ctlr_queue);
1537: }
1538: }
1539:
1540:
1541: /*
1542: ** cyseek is used by the block device to position the tape correctly
1543: ** before each read or write request.
1544: **
1545: ** The special cases are:
1546: ** 1) we can hit end of tape while seeking.
1547: ** 2) we want to be nice to other processes while seeking so we
1548: ** break the request up into smaller requests.
1549: */
1550:
1551: cyseek(request, ctlr_queue)
1552: register struct buf *request;
1553: register struct buf *ctlr_queue;
1554: {
1555: register int unit = CYUNIT(request->b_dev);
1556: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1557: register int ctlr = cydinfo[unit]->ui_ctlr;
1558: register ctlr_tab *c_info = &ctlr_info[ctlr];
1559:
1560: if(request->b_blkno < u_info->blkno) {
1561: register int count;
1562:
1563: (*u_info->cleanup)(unit, MAINTAIN_POSITION);
1564: count = ((request->b_blkno+1) == u_info->blkno) ? 2 : 1;
1565: u_info->blkno -= count;
1566: cyexecute(SPAC_FM, 1, 0, CW_REV, unit, 10, FALSE);
1567: if(!u_info->eof)
1568: return FALSE;
1569: u_info->eof = FALSE;
1570: request->b_blkno = u_info->blkno + 1;
1571: }
1572: if(request->b_blkno > u_info->blkno) {
1573: if((u_info->cleanup != cyno_op) || u_info->eof || u_info->eot) {
1574: request->b_resid = request->b_bcount;
1575: request->b_error = ENXIO, request->b_flags |= B_ERROR;
1576: longjmp(&c_info->environ);
1577: }
1578: u_info->blkno++;
1579: cyexecute(SPAC_FM, 1, 0, 0, unit, 10, FALSE);
1580: return FALSE;
1581: }
1582: return TRUE;
1583: }
1584:
1585:
1586: /*
1587: */
1588:
1589: cywrite_eov(request, ctlr_queue)
1590: register struct buf *request;
1591: register struct buf *ctlr_queue;
1592: {
1593: extern int cyno_op();
1594: register int unit = CYUNIT(request->b_dev);
1595: register unit_tab *u_info = &unit_info[CYUNIT(unit)];
1596:
1597: if(u_info->cleanup != cyno_op) {
1598: (*u_info->cleanup)(unit, DONT_MAINTAIN_POSITION);
1599: cyexecute(SPACE, 2, 0, CW_REV, unit, 10, FALSE);
1600: cyexecute(SPACE, 1, 0, 0, unit, 10, FALSE);
1601: unit_info[unit].cleanup = cyno_op;
1602: u_info->blkno = 0;
1603: }
1604: cydone(ctlr_queue);
1605: }
1606:
1607:
1608: /*
1609: ** Do nothing
1610: */
1611:
1612: cyno_op(unit, action)
1613: int unit, action;
1614: {
1615: }
1616:
1617:
1618: /*
1619: ** Write 0 file marks to tape
1620: */
1621:
1622: cywrite_0_fm(unit, action)
1623: int unit, action;
1624: {
1625: unit_info[unit].cleanup = cyno_op;
1626: }
1627:
1628:
1629: /*
1630: ** Write 1 file mark to tape
1631: */
1632:
1633: cywrite_1_fm(unit, action)
1634: int unit, action;
1635: {
1636: cyexecute(WRIT_FM, 1, 0, 0, unit, 5, FALSE);
1637: if(action == MAINTAIN_POSITION) {
1638: cyexecute(SPACE, 2, 0, CW_REV, unit, 10, FALSE);
1639: cyexecute(SPACE, 1, 0, 0, unit, 10, FALSE);
1640: }
1641: unit_info[unit].cleanup = cyno_op;
1642: }
1643:
1644:
1645: /*
1646: ** Write 2 file marks to tape
1647: */
1648:
1649: cywrite_2_fm(unit, action)
1650: int unit, action;
1651: {
1652: cyexecute(WRIT_FM, 1, 0, 0, unit, 5, FALSE);
1653: cyexecute(WRIT_FM, 1, 0, 0, unit, 5, FALSE);
1654: if(action == MAINTAIN_POSITION) {
1655: cyexecute(SPACE, 3, 0, CW_REV, unit, 10, FALSE);
1656: cyexecute(SPACE, 1, 0, 0, unit, 2, FALSE);
1657: }
1658: unit_info[unit].cleanup = cyno_op;
1659: }
1660:
1661:
1662: /*
1663: ** Cyexecute is used to start all commands to the controller. We
1664: ** do all common code here before starting.
1665: */
1666:
1667: cyexecute(command, count, addr, control_flags, unit, time, interupt_routine)
1668: register int command;
1669: int count, addr, control_flags, unit, time, interupt_routine;
1670: {
1671: extern int cytimeout();
1672: extern int cy_normal_path();
1673: register int priority;
1674: register int ctlr = cydinfo[unit]->ui_ctlr;
1675: register unit_tab *u_info = &unit_info[unit];
1676: register ctlr_tab *c_info = &ctlr_info[ctlr];
1677: register struct buf *request = u_info->u_queue.av_forw;
1678:
1679: c_info->tpb.cmd = command;
1680: c_info->tpb.control = u_info->control_proto | control_flags;
1681: c_info->tpb.status = c_info->tpb.count = (short)0;
1682: load_mbus_addr((char *)addr, &c_info->tpb.data_ptr);
1683: switch(command) {
1684: case READ_BU :
1685: case READ_TA :
1686: case WRIT_BU :
1687: case WRIT_TA :
1688: c_info->tpb.size = MULTIBUS_SHORT((short)count);
1689: c_info->tpb.rec_over = (short)0;
1690: break;
1691: default:
1692: c_info->tpb.size = (short)0;
1693: c_info->tpb.rec_over = MULTIBUS_SHORT((short)count);
1694: break;
1695: }
1696: load_mbus_addr((char *)0, c_info->tpb.link_ptr);
1697: if(!interupt_routine)
1698: c_info->last = c_info->tpb;
1699: /*
1700: gag! but it the last possible moment to wait
1701: for this controller to get out of it's own way.....
1702: */
1703: uncache(&c_info->ccb.gate);
1704: while(c_info->ccb.gate == GATE_CLOSED)
1705: uncache(&c_info->ccb.gate);
1706: load_mbus_addr(&c_info->tpb, c_info->ccb.tpb_ptr);
1707: c_info->ccb.ccw = NORMAL_INTERUPT;
1708: c_info->ccb.gate = GATE_CLOSED;
1709: if(!interupt_routine)
1710: c_info->interupt_path = cy_normal_path;
1711: timeout(cytimeout, ctlr, time*60);
1712: priority = spl3();
1713: CY_ATTENTION(cyminfo[ctlr]->um_addr);
1714: if(!interupt_routine) {
1715: sleep(c_info, PRIBIO+3);
1716: splx(priority);
1717: if(request->b_flags & B_ERROR) {
1718: if((command == READ_BU) || (command == READ_TA) ||
1719: (command == WRIT_BU) || (command == WRIT_TA))
1720: end_transfer(request, c_info->rawbuf,
1721: c_info->map,c_info->utl);
1722: longjmp(&c_info->environ);
1723: }
1724: return;
1725: }
1726: splx(priority);
1727: }
1728:
1729:
1730: /*
1731: ** cytimeout is the interupt timeout routine. We assume that a
1732: ** particular command has gone astray, so we completely reset the controller,
1733: ** and call the interupt routine to help us clean up. Before the interupt
1734: ** routine is called we jam a controller timeout value in the status register
1735: ** to fake out the calling routines.
1736: */
1737:
1738: cytimeout(ctlr)
1739: register int ctlr;
1740: {
1741: register int priority = spl3();
1742: register char *ctlr_vaddr = cyminfo[ctlr]->um_addr;
1743: register int tmp_stat;
1744:
1745: uncache(&ctlr_info[ctlr].tpb.status);
1746: tmp_stat = ctlr_info[ctlr].tpb.status;
1747: CY_RESET(ctlr_vaddr);
1748: cy_init_controller(ctlr_vaddr, ctlr, 0);
1749: splx(priority);
1750: ctlr_info[ctlr].tpb = ctlr_info[ctlr].last;
1751: ctlr_info[ctlr].tpb.status = (tmp_stat & ~CS_ERm) | CS_OL | ER_TIMOUT;
1752: cyintr(ctlr);
1753: }
1754:
1755: /*
1756: ** Cyintr is the interupt routine for the Tapemaster controller.
1757: **
1758: ** Due to controller problems, the first thing we have to do is turn
1759: ** off the Tapemaster interupting mechanism. If we don't we will be flooded
1760: ** with bogus interupts and the system will spend all it's time processing
1761: ** them. To Turn the interupts off we issue a NOOP command with the 'turn
1762: ** off interupts' code in the ccb.
1763: **
1764: ** take note that since this command TURNS OFF the interupts it
1765: ** itself CANNOT interupt... This means that polling must be done
1766: ** at sometime to make sure that tis command is completed. The polling
1767: ** is done before the next command is issued to reduce polling (halting
1768: ** UNIX) time.
1769: **
1770: ** After we turn off interupts we uncache all the values in the tpb
1771: ** and call the correct processing routine. This routine can be for normal
1772: ** interupts or for interupts generated during a retry operation.
1773: */
1774:
1775: cyintr(ctlr)
1776: register int ctlr;
1777: {
1778: extern int cytimeout();
1779: register ctlr_tab *c_info = &ctlr_info[ctlr];
1780:
1781: untimeout(cytimeout, ctlr);
1782: /* turn off interupts for the stupid controller */
1783: c_info->ccb.ccw = CLEAR_INTERUPT;
1784: c_info->noop.cmd = NO_OP;
1785: c_info->noop.control = (short)0;
1786: load_mbus_addr(&c_info->noop, c_info->ccb.tpb_ptr);
1787: c_info->ccb.gate = GATE_CLOSED;
1788: CY_ATTENTION(cyminfo[ctlr]->um_addr);
1789: uncache_tpb(c_info);
1790: (*c_info->interupt_path)(ctlr);
1791: }
1792:
1793:
1794: /*
1795: ** This is the portion of the interupt routine that processes all
1796: ** normal cases i.e. non retry cases. We check the operations status
1797: ** if it is retryable we set the interupt path to the retry routines and
1798: ** start the backward spaceing. when the spacing is done the retry logic
1799: ** will be called and this routine will be skipped entirely.
1800: **
1801: ** If the command is ok or not retryable we set the status accordingly
1802: ** and wakeup cyexecute to continue processing.
1803: */
1804:
1805: cy_normal_path(ctlr)
1806: register int ctlr;
1807: {
1808: extern int cy_retry_path();
1809: extern int cy_extended_gap_path();
1810: register int error;
1811: register struct buf *ctlr_queue = &cyminfo[ctlr]->um_tab;
1812: register struct buf *unit_queue = ctlr_queue->b_forw;
1813: register struct buf *request = unit_queue->av_forw;
1814: register int unit = CYUNIT(request->b_dev);
1815: register unit_tab *u_info = &unit_info[unit];
1816: register ctlr_tab *c_info = &ctlr_info[ctlr];
1817:
1818: if (error = cydecode_error(unit, c_info->tpb.status)) {
1819: if(error != FATAL) {
1820: if (error == RETRY)
1821: c_info->interupt_path = cy_retry_path;
1822: else
1823: c_info->interupt_path = cy_extended_gap_path;
1824: cyexecute(SPACE, 2, 0, CW_REV, unit, 5, TRUE);
1825: return;
1826: }
1827: }
1828: request->b_resid=request->b_bcount-MULTIBUS_SHORT(c_info->tpb.count);
1829: u_info->error_count = 0;
1830: u_info->last_resid = request->b_resid;
1831: u_info->last_status = c_info->tpb.status;
1832: u_info->last_control = c_info->tpb.control;
1833: if (error == FATAL)
1834: request->b_flags |= B_ERROR, request->b_error = EIO;
1835: wakeup(c_info);
1836: }
1837:
1838:
1839: /*
1840: ** Cy_retry_path finishes up the retry sequence for the tape.
1841: ** If we were going in the reverse direction it means that we have to
1842: ** space forward to correctly position ourselfs in back of the tape gap
1843: ** instead of in front of it. If we were going forward it means that
1844: ** we are positioned correctly and we can actually restart the instruction
1845: ** that failed before.
1846: */
1847:
1848: cy_retry_path(ctlr)
1849: register int ctlr;
1850: {
1851: extern int cy_do_again_path();
1852: register struct buf *ctlr_queue = &cyminfo[ctlr]->um_tab;
1853: register struct buf *unit_queue = ctlr_queue->b_forw;
1854: register struct buf *request = unit_queue->av_forw;
1855: register int unit = CYUNIT(request->b_dev);
1856: register unit_tab *u_info = &unit_info[unit];
1857: register ctlr_tab *c_info = &ctlr_info[ctlr];
1858:
1859: if(!(c_info->tpb.status & CS_OL)) {
1860: c_info->interupt_path = cy_normal_path;
1861: cy_normal_path(ctlr);
1862: return;
1863: }
1864: if(c_info->tpb.control & CW_REV) {
1865: if(!(c_info->tpb.status & CS_LP)) {
1866: c_info->interupt_path = cy_do_again_path;
1867: cyexecute(SPACE, 1, 0, 0, unit, 5, TRUE);
1868: return;
1869: }
1870: cy_do_again_path(ctlr);
1871: }
1872: }
1873:
1874:
1875: /*
1876: **
1877: */
1878:
1879: cy_extended_gap_path(ctlr)
1880: register int ctlr;
1881: {
1882: extern int cy_do_again_path();
1883: register ctlr_tab *c_info = &ctlr_info[ctlr];
1884: register struct buf *ctlr_queue = &cyminfo[ctlr]->um_tab;
1885: register struct buf *unit_queue = ctlr_queue->b_forw;
1886: register struct buf *request = unit_queue->av_forw;
1887: register int unit = CYUNIT(request->b_dev);
1888:
1889: if(!(c_info->tpb.status & CS_OL)) {
1890: c_info->interupt_path = cy_normal_path;
1891: cy_normal_path(ctlr);
1892: return;
1893: }
1894: if(c_info->tpb.control & CW_REV) {
1895: if(!(c_info->tpb.status & CS_LP)) {
1896: cyexecute(SPACE, 1, 0, 0, unit, 5, TRUE);
1897: return;
1898: }
1899: }
1900: c_info->interupt_path = cy_do_again_path;
1901: cyexecute(ERASE_F, unit_info[unit].error_count, 0, 0, unit, 5, TRUE);
1902: }
1903:
1904:
1905: /*
1906: **
1907: */
1908:
1909: cy_do_again_path(ctlr)
1910: register int ctlr;
1911: {
1912: extern int cy_normal_path();
1913: register ctlr_tab *c_info = &ctlr_info[ctlr];
1914:
1915: if(!(c_info->tpb.status & CS_OL)) {
1916: c_info->interupt_path = cy_normal_path;
1917: cy_normal_path(ctlr);
1918: return;
1919: }
1920: c_info->tpb = c_info->last;
1921: uncache(&c_info->ccb.gate);
1922: while(c_info->ccb.gate == GATE_CLOSED)
1923: uncache(&c_info->ccb.gate);
1924: load_mbus_addr(&c_info->tpb, c_info->ccb.tpb_ptr);
1925: c_info->ccb.ccw = NORMAL_INTERUPT;
1926: c_info->ccb.gate = GATE_CLOSED;
1927: c_info->interupt_path = cy_normal_path;
1928: CY_ATTENTION(cyminfo[ctlr]->um_addr);
1929: }
1930:
1931:
1932: /*
1933: ** for each longword in the tpb we call uncache to purge it from
1934: ** the cache. This is done so that we can correctly access tpb data
1935: ** that was placed there by the controller.
1936: */
1937:
1938: uncache_tpb(c_info)
1939: ctlr_tab *c_info;
1940: {
1941: register long *ptr = (long *)&c_info->tpb;
1942: register int i;
1943:
1944: for(i=0; i<((sizeof(fmt_tpb)+sizeof(long)-1)/sizeof(long)); i++)
1945: uncache(ptr++);
1946: }
1947:
1948:
1949: /*
1950: ** Cyprint_error is the common printing routine for all messages
1951: ** that need to print the tape status along with it. This is so we
1952: ** we can save space, have consistant messages, and we can send the messages
1953: ** to the correct places.
1954: */
1955:
1956: cyprint_err(message, unit, status)
1957: register char *message;
1958: register int unit, status;
1959: {
1960: status &= 0xffff;
1.1.1.2 ! root 1961: printf("\ncy%d: %s! Status = %x\n", unit, message, status);
1.1 root 1962: }
1963:
1964: /*
1965: ** Decode the error to determine whether the previous command was
1966: ** ok, retryable, or fatal and return the value. If it was a hardware
1967: ** problem we print the message to the console, otherwise we print it
1968: ** to the user's terminal later when execute returns.
1969: */
1970:
1971: cydecode_error(unit, status)
1972: register int unit, status;
1973: {
1974: register unit_tab *u_info = &unit_info[unit];
1975: register ctlr_tab *c_info = &ctlr_info[cydinfo[unit]->ui_ctlr];
1976: int ctlr = cydinfo[unit]->ui_ctlr;
1977:
1978: if(!(status & CS_OL) && (c_info->tpb.cmd != OFF_UNL)) {
1979: u_info->message = "Drive is not on-line";
1980: cyprint_err(u_info->message, unit, status);
1981: return FATAL;
1982: }
1983: u_info->bot = ((status & CS_LP) != 0);
1984: u_info->eof = ((status & CS_FM) != 0);
1985: switch(status & CS_ERm) {
1986: case ER_EOT:
1987: if(c_info->tpb.control & CW_REV) {
1988: u_info->bot = TRUE;
1989: u_info->eot = FALSE;
1990: }
1991: else if(!u_info->eot){
1992: u_info->message = "End of tape";
1993: u_info->bot = FALSE;
1994: u_info->eot = TRUE;
1995: }
1996: case 0 :
1997: case ER_FM:
1998: case ER_NOSTRM:
1999: return NOERROR;
2000: case ER_TIMOUT:
2001: case ER_TIMOUT1:
2002: case ER_TIMOUT2:
2003: case ER_TIMOUT3:
2004: case ER_TIMOUT4:
2005: u_info->message = "Drive timed out during transfer";
2006: cyprint_err(u_info->message, unit, status);
2007: return FATAL;
2008: case ER_NEX:
2009: u_info->message =
2010: "Controller referenced non-existant system memory";
2011: cyprint_err(u_info->message, unit, status);
2012: return FATAL;
2013: case ER_DIAG:
2014: case ER_JUMPER:
2015: u_info->message = "Controller diagnostics failed";
2016: cyprint_err(u_info->message, unit, status);
2017: return FATAL;
2018: case ER_STROBE:
2019: if (c_info->tpb.cmd == READ_BU) {
2020: c_info->last.cmd = READ_TA;
2021: return RETRY;
2022: }
2023: if(c_info->tpb.cmd == READ_TA)
2024: return NOERROR;
2025: u_info->message = "Unsatisfactory media found";
2026: return FATAL;
2027: case ER_FIFO:
2028: case ER_NOTRDY:
2029: u_info->error_count = 1;
2030: return RETRY;
2031: case ER_PROT:
2032: u_info->message = "Tape is write protected";
2033: return FATAL;
2034: case ER_CHKSUM:
2035: u_info->message = "Checksum error in controller proms";
2036: cyprint_err(u_info->message, unit, status);
2037: return FATAL;
2038: case ER_HARD:
2039: u_info->error_count++;
2040: if((c_info->tpb.cmd == WRIT_TA) ||
2041: (c_info->tpb.cmd == WRIT_BU) ||
2042: (c_info->tpb.cmd == WRIT_FM)) {
2043: u_info->bad_count++;
2044: return EXTEND;
2045: }
2046: u_info->message = "Unrecoverable media error during read";
2047: return FATAL;
2048: case ER_PARITY:
2049: if(++u_info->error_count < 8)
2050: return RETRY;
2051: u_info->message = "Unrecoverable tape parity error";
2052: return FATAL;
2053: case ER_BLANK:
1.1.1.2 ! root 2054: u_info->message = "Blank tape found (data expected)";
1.1 root 2055: return FATAL;
2056: case ER_HDWERR:
2057: default:
2058: u_info->message = "Unrecoverble hardware error";
2059: cyprint_err(u_info->message, unit, status);
2060: return FATAL;
2061: }
2062: }
2063:
2064:
2065: /*
2066: ** Raw read interface to unix. Since all the checking is done at a
2067: ** lower level we don't check anything here and we simply return the results.
2068: */
2069:
2070: cyread(dev, uio)
2071: register dev_t dev;
2072: register struct uio *uio;
2073: {
2074: register int unit = CYUNIT(dev);
2075: register unit_tab *u_info = &unit_info[unit];
2076:
2077: return physio(cystrategy, &u_info->rawbp, dev, B_READ, cyminsize, uio);
2078: }
2079:
2080:
2081: /*
2082: ** Raw write interface to unix. Since all the checking is done at a
2083: ** lower level we don't check anything here and we simply return the results.
2084: */
2085:
2086: cywrite(dev, uio)
2087: register dev_t dev;
2088: register struct uio *uio;
2089: {
2090: register int unit = CYUNIT(dev);
2091: register unit_tab *u_info = &unit_info[unit];
2092:
2093: return physio(cystrategy,&u_info->rawbp, dev, B_WRITE, cyminsize, uio);
2094: }
2095:
2096: /*
2097: ** Cyioctl is called by UNIX every time an ioctl call is made by a user
2098: ** program. We don't really do much here except call cycmd to process the
2099: ** ioctl command. We don't decode the ioctl type here because our internal
2100: ** jump table accessed by start is ordered by the ioctl number passes here.
2101: **
2102: ** The only special processing is in the status command. This is because
2103: ** we actually return various data to the user's program with only that
2104: ** command.
2105: */
2106:
2107: cyioctl(dev, command, data, flag)
2108: register dev_t dev;
2109: register int command;
2110: register struct mtop *data;
2111: register int flag;
2112: {
2113: if(command == MTIOCTOP)
2114: if((unsigned)(data->mt_op <= DO_WAIT))
2115: return cycmd(dev, data->mt_op, data->mt_count);
2116: else
2117: return EIO;
2118: else if(command == MTIOCGET) {
2119: register unit_tab *u_info = &unit_info[CYUNIT(dev)];
2120:
2121: ((struct mtget *)data)->mt_type = MT_ISCY;
2122: ((struct mtget *)data)->mt_dsreg = u_info->last_control;
2123: ((struct mtget *)data)->mt_erreg = u_info->last_status;
2124: ((struct mtget *)data)->mt_resid = u_info->last_resid;
2125: ((struct mtget *)data)->mt_fileno = u_info->file_number;
2126: ((struct mtget *)data)->mt_blkno = u_info->blkno;
2127: cycmd(dev, DO_STAT, 1);
2128: return NOERROR;
2129: }
2130: return ENXIO;
2131: }
2132:
2133: /*
2134: ** Cydump is called during a system crash to dump all of main memory.
2135: ** We don't do any special checking here except we will exit early if
2136: ** an i/o error occurs. The other point is we poll for completion of each
2137: ** command since we don't want to do any special processing, we are
2138: ** the only process running anyway, and possibly the cpu interupt's
2139: ** were not working anyway. (what if sombody stepped on low core?)
2140: */
2141:
2142: cydump(dev)
2143: register dev_t dev;
2144: {
2145: register int unit = CYUNIT(dev);
2146: register int ctlr = cydinfo[unit]->ui_ctlr;
2147: register unit_tab *u_info = &unit_info[unit];
2148: register ctlr_tab *c_info = &ctlr_info[ctlr];
2149: register int blk_siz;
2150: register int num = maxfree;
2151: register int start = 0x800;
2152:
2153: if ((unit >= NCY) || cydinfo[unit])
2154: return(ENXIO);
2155: u_info->control_proto = CW_LOCK | CW_25ips | CW_16bits;
2156: if (cywait(&c_info->ccb))
2157: return(EFAULT);
2158: while (num > 0) {
2159: blk_siz = num > TBUFSIZ ? TBUFSIZ : num;
2160: bcopy(start*NBPG, c_info->rawbuf, blk_siz*NBPG);
2161: c_info->tpb.cmd = WRIT_TA;
2162: c_info->tpb.control = u_info->control_proto;
2163: c_info->tpb.status = 0;
2164: c_info->tpb.size = MULTIBUS_SHORT(blk_siz*NBPG);
2165: load_mbus_addr((char *)0, c_info->tpb.link_ptr);
2166: load_mbus_addr(c_info->rawbuf,&(c_info->tpb.data_ptr));
2167: load_mbus_addr(&c_info->tpb, c_info->ccb.tpb_ptr);
2168: c_info->ccb.gate = GATE_CLOSED;
2169: CY_ATTENTION(cyminfo[ctlr]->um_addr);
2170: start += blk_siz;
2171: num -= blk_siz;
2172: if (cywait(&c_info->ccb))
2173: return(EFAULT);
2174: uncache(&c_info->tpb);
2175: if (c_info->tpb.status&CS_ERm) /* error */
2176: return (EIO);
2177: }
2178: for(num=0; num<2; num++) {
2179: c_info->tpb.cmd = WRIT_FM;
2180: c_info->tpb.control = u_info->control_proto;
2181: c_info->tpb.status = c_info->tpb.size = 0;
2182: c_info->tpb.count = MULTIBUS_SHORT(1);
2183: load_mbus_addr((char *)0, c_info->tpb.link_ptr);
2184: load_mbus_addr(c_info->rawbuf,&(c_info->tpb.data_ptr));
2185: load_mbus_addr(&c_info->tpb, c_info->ccb.tpb_ptr);
2186: c_info->ccb.gate = GATE_CLOSED;
2187: CY_ATTENTION(cyminfo[ctlr]->um_addr);
2188: if (cywait(&c_info->ccb))
2189: return(EFAULT);
2190: uncache(&c_info->tpb);
2191: if (c_info->tpb.status&CS_ERm) /* error */
2192: return (EIO);
2193: }
2194: c_info->tpb.cmd = REWD_OV;
2195: c_info->tpb.control = u_info->control_proto;
2196: c_info->tpb.status = c_info->tpb.size = 0;
2197: c_info->tpb.count = MULTIBUS_SHORT(1);
2198: load_mbus_addr((char *)0, c_info->tpb.link_ptr);
2199: load_mbus_addr(c_info->rawbuf,&(c_info->tpb.data_ptr));
2200: load_mbus_addr(&c_info->tpb, c_info->ccb.tpb_ptr);
2201: c_info->ccb.gate = GATE_CLOSED;
2202: CY_ATTENTION(cyminfo[ctlr]->um_addr);
2203: if (cywait(&c_info->ccb))
2204: return EFAULT;
2205: uncache(&c_info->tpb);
2206: return 0;
2207: }
2208:
2209:
2210: /*
2211: ** Poll until the controller is ready.
2212: */
2213:
2214: cywait(ccb_ptr)
2215: register fmt_ccb *ccb_ptr;
2216: {
2217: register int cnt = 5000;
2218:
2219: uncache(&ccb_ptr->gate);
2220: while ((cnt-- > 0) && (ccb_ptr->gate == GATE_CLOSED)) {
2221: DELAY(1000);
2222: uncache(&ccb_ptr->gate);
2223: }
2224: return cnt <= 0;
2225: }
2226:
2227:
2228: /*
2229: ** Load_mbus_addr is used to load a 20 bit pointer into the
2230: ** Tapemaster registers. Take note of all the strange convolutions
2231: ** this controller forces us through to get the job done.
2232: */
2233:
2234: load_mbus_addr(in, out)
2235: char *in;
2236: short *out;
2237: {
2238: register int tmp_in = (int)in;
2239: register char *out_ptr = (char *)out;
2240:
2241: *out_ptr++ = (char)(tmp_in & 0xff);
2242: *out_ptr++ = (char)((tmp_in >> 8) & 0xff);
2243: *out_ptr++ = (char)0;
2244: *out_ptr++ = (char)((tmp_in & 0xf0000) >> 12);
2245: }
2246:
2247:
2248: /*
2249: ** CYMINSIZE s supposed to adjust the buffer size for any raw i/o.
2250: ** since tapes can not read the tail end of partial blocks we ignore
2251: ** this request and strategy will return an appropriate error message later.
2252: **
2253: ** If this is not done UNIX will lose data that is on the tape.
2254: */
2255:
2256: unsigned cyminsize(request)
2257: register struct buf *request;
2258: {
2259: if(request->b_bcount > MAX_BLOCKSIZE)
2260: request->b_bcount = MAX_BLOCKSIZE;
2261: }
2262:
2263:
2264: /*
2265: ** cyreset is used to unconditionally reset all controllers to
2266: ** their initial state.
2267: */
2268:
2269: cyreset(vba)
2270: register int vba;
2271: {
2272: register int ctlr;
2273: register caddr_t ctlr_vaddr;
2274:
2275: for(ctlr = 0; ctlr<NCY; ctlr++)
2276: if(cyminfo[ctlr])
2277: if(cyminfo[ctlr]->um_vbanum == vba) {
2278: ctlr_vaddr = cyminfo[ctlr]->um_addr;
2279: CY_RESET(ctlr_vaddr);
2280: if(!cy_init_controller(ctlr_vaddr, ctlr, 0)) {
2281: printf("cy: controller #%d failed to reset!\n", ctlr);
2282: cyminfo[ctlr] = NULL;
2283: }
2284: }
2285: }
2286:
2287:
2288: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.