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