3 * Streamer tape driver for 386bsd and FreeBSD.
4 * Supports Archive and Wangtek compatible QIC-02/QIC-36 boards.
6 * Copyright (C) 1993 by:
7 * Sergey Ryzhkov <sir@kiae.su>
8 * Serge Vakulenko <vak@zebub.msk.su>
10 * This software is distributed with NO WARRANTIES, not even the implied
11 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * Authors grant any other persons or organisations permission to use
14 * or modify this software as long as this message is kept with the software,
15 * all derivative works or modified versions.
17 * This driver is derived from the old 386bsd Wangtek streamer tape driver,
18 * made by Robert Baron at CMU, based on Intel sources.
19 * Authors thank Robert Baron, CMU and Intel and retain here
20 * the original CMU copyright notice.
22 * Version 1.3, Thu Nov 11 12:09:13 MSK 1993
23 * $FreeBSD: src/sys/i386/isa/wt.c,v 1.57.2.1 2000/08/08 19:49:53 peter Exp $
24 * $DragonFly: src/sys/dev/disk/wt/wt.c,v 1.20 2008/01/06 16:55:49 swildner Exp $
29 * Code for MTERASE added by John Lind (john@starfire.mn.org) 95/09/02.
30 * This was very easy due to the excellent structure and clear coding
31 * of the original driver.
35 * Copyright (c) 1989 Carnegie-Mellon University.
36 * All rights reserved.
38 * Authors: Robert Baron
40 * Permission to use, copy, modify and distribute this software and
41 * its documentation is hereby granted, provided that both the copyright
42 * notice and this permission notice appear in all copies of the
43 * software, derivative works or modified versions, and any portions
44 * thereof, and that both notices appear in supporting documentation.
46 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
47 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
48 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
50 * Carnegie Mellon requests users of this software to return to
52 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
53 * School of Computer Science
54 * Carnegie Mellon University
55 * Pittsburgh PA 15213-3890
57 * any improvements or extensions that they make and grant Carnegie the
58 * rights to redistribute these changes.
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
67 #include <sys/fcntl.h>
68 #include <sys/malloc.h>
71 #include <sys/thread2.h>
74 #include <machine/clock.h>
76 #include <bus/isa/i386/isa_device.h>
77 #include <bus/isa/isavar.h>
82 * Uncomment this to enable internal device tracing.
84 #define TRACE(s) /* kprintf s */
87 * Wangtek controller ports
89 #define WT_CTLPORT(base) ((base)+0) /* control, write only */
90 #define WT_STATPORT(base) ((base)+0) /* status, read only */
91 #define WT_CMDPORT(base) ((base)+1) /* command, write only */
92 #define WT_DATAPORT(base) ((base)+1) /* data, read only */
93 #define WT_NPORT 2 /* 2 i/o ports */
95 /* status port bits */
96 #define WT_BUSY 0x01 /* not ready bit define */
97 #define WT_NOEXCEP 0x02 /* no exception bit define */
98 #define WT_RESETMASK 0x07 /* to check after reset */
99 #define WT_RESETVAL 0x05 /* state after reset */
101 /* control port bits */
102 #define WT_ONLINE 0x01 /* device selected */
103 #define WT_RESET 0x02 /* reset command */
104 #define WT_REQUEST 0x04 /* request command */
105 #define WT_IEN 0x08 /* enable dma */
108 * Archive controller ports
110 #define AV_DATAPORT(base) ((base)+0) /* data, read only */
111 #define AV_CMDPORT(base) ((base)+0) /* command, write only */
112 #define AV_STATPORT(base) ((base)+1) /* status, read only */
113 #define AV_CTLPORT(base) ((base)+1) /* control, write only */
114 #define AV_SDMAPORT(base) ((base)+2) /* start dma */
115 #define AV_RDMAPORT(base) ((base)+3) /* reset dma */
116 #define AV_NPORT 4 /* 4 i/o ports */
118 /* status port bits */
119 #define AV_BUSY 0x40 /* not ready bit define */
120 #define AV_NOEXCEP 0x20 /* no exception bit define */
121 #define AV_RESETMASK 0xf8 /* to check after reset */
122 #define AV_RESETVAL 0x50 /* state after reset */
124 /* control port bits */
125 #define AV_RESET 0x80 /* reset command */
126 #define AV_REQUEST 0x40 /* request command */
127 #define AV_IEN 0x20 /* enable interrupts */
130 UNKNOWN
= 0, /* unknown type, driver disabled */
131 ARCHIVE
, /* Archive Viper SC499, SC402 etc */
132 WANGTEK
/* Wangtek */
136 unsigned short err
; /* code for error encountered */
137 unsigned short ercnt
; /* number of error blocks */
138 unsigned short urcnt
; /* number of underruns */
142 enum wttype type
; /* type of controller */
143 unsigned unit
; /* unit number */
144 unsigned port
; /* base i/o port */
145 unsigned chan
; /* dma channel number, 1..3 */
146 unsigned flags
; /* state of tape drive */
147 unsigned dens
; /* tape density */
148 int bsize
; /* tape block size */
149 void *buf
; /* internal i/o buffer */
151 void *dmavaddr
; /* virtual address of dma i/o buffer */
152 unsigned dmatotal
; /* size of i/o buffer */
153 unsigned dmaflags
; /* i/o direction, ISADMA_READ or ISADMA_WRITE */
154 unsigned dmacount
; /* resulting length of dma i/o */
156 wtstatus_t error
; /* status of controller */
158 unsigned short DATAPORT
, CMDPORT
, STATPORT
, CTLPORT
, SDMAPORT
, RDMAPORT
;
159 unsigned char BUSY
, NOEXCEP
, RESETMASK
, RESETVAL
;
160 unsigned char ONLINE
, RESET
, REQUEST
, IEN
;
161 struct callout timeout_ch
;
164 static wtinfo_t wttab
[NWT
]; /* tape info by unit number */
166 static int wtwait (wtinfo_t
*t
, int catch, char *msg
);
167 static int wtcmd (wtinfo_t
*t
, int cmd
);
168 static int wtstart (wtinfo_t
*t
, unsigned flags
, void *vaddr
, unsigned len
);
169 static void wtdma (wtinfo_t
*t
);
170 static timeout_t wtimer
;
171 static void wtclock (wtinfo_t
*t
);
172 static int wtreset (wtinfo_t
*t
);
173 static int wtsense (wtinfo_t
*t
, int verb
, int ignor
);
174 static int wtstatus (wtinfo_t
*t
);
175 static void wtintr(void *);
176 static void wtrewind (wtinfo_t
*t
);
177 static int wtreadfm (wtinfo_t
*t
);
178 static int wtwritefm (wtinfo_t
*t
);
179 static int wtpoll (wtinfo_t
*t
, int mask
, int bits
);
181 static d_open_t wtopen
;
182 static d_close_t wtclose
;
183 static d_ioctl_t wtioctl
;
184 static d_strategy_t wtstrategy
;
186 #define CDEV_MAJOR 10
188 static struct dev_ops wt_ops
= {
189 { "wt", CDEV_MAJOR
, 0 },
193 .d_write
= physwrite
,
195 .d_strategy
= wtstrategy
,
200 * Probe for the presence of the device.
203 wtprobe (struct isa_device
*id
)
205 wtinfo_t
*t
= wttab
+ id
->id_unit
;
207 callout_init(&t
->timeout_ch
);
208 t
->unit
= id
->id_unit
;
209 t
->chan
= id
->id_drq
;
210 t
->port
= id
->id_iobase
;
211 if (t
->chan
<1 || t
->chan
>3) {
212 kprintf ("wt%d: Bad drq=%d, should be 1..3\n", t
->unit
, t
->chan
);
218 t
->CTLPORT
= WT_CTLPORT (t
->port
); t
->STATPORT
= WT_STATPORT (t
->port
);
219 t
->CMDPORT
= WT_CMDPORT (t
->port
); t
->DATAPORT
= WT_DATAPORT (t
->port
);
220 t
->SDMAPORT
= 0; t
->RDMAPORT
= 0;
221 t
->BUSY
= WT_BUSY
; t
->NOEXCEP
= WT_NOEXCEP
;
222 t
->RESETMASK
= WT_RESETMASK
; t
->RESETVAL
= WT_RESETVAL
;
223 t
->ONLINE
= WT_ONLINE
; t
->RESET
= WT_RESET
;
224 t
->REQUEST
= WT_REQUEST
; t
->IEN
= WT_IEN
;
230 t
->CTLPORT
= AV_CTLPORT (t
->port
); t
->STATPORT
= AV_STATPORT (t
->port
);
231 t
->CMDPORT
= AV_CMDPORT (t
->port
); t
->DATAPORT
= AV_DATAPORT (t
->port
);
232 t
->SDMAPORT
= AV_SDMAPORT (t
->port
); t
->RDMAPORT
= AV_RDMAPORT (t
->port
);
233 t
->BUSY
= AV_BUSY
; t
->NOEXCEP
= AV_NOEXCEP
;
234 t
->RESETMASK
= AV_RESETMASK
; t
->RESETVAL
= AV_RESETVAL
;
235 t
->ONLINE
= 0; t
->RESET
= AV_RESET
;
236 t
->REQUEST
= AV_REQUEST
; t
->IEN
= AV_IEN
;
240 /* Tape controller not found. */
246 * Device is found, configure it.
249 wtattach (struct isa_device
*id
)
251 wtinfo_t
*t
= wttab
+ id
->id_unit
;
253 id
->id_intr
= (inthand2_t
*)wtintr
;
254 if (t
->type
== ARCHIVE
) {
255 kprintf ("wt%d: type <Archive>\n", t
->unit
);
256 outb (t
->RDMAPORT
, 0); /* reset dma */
258 kprintf ("wt%d: type <Wangtek>\n", t
->unit
);
259 t
->flags
= TPSTART
; /* tape is rewound */
260 t
->dens
= -1; /* unknown density */
261 isa_dmainit(t
->chan
, 1024);
263 dev_ops_add(&wt_ops
, -1, id
->id_unit
);
264 make_dev(&wt_ops
, id
->id_unit
, 0, 0, 0600, "rwt%d", id
->id_unit
);
268 struct isa_driver wtdriver
= { wtprobe
, wtattach
, "wt", };
271 * Open routine, called on every device open.
274 wtopen (struct dev_open_args
*ap
)
276 cdev_t dev
= ap
->a_head
.a_dev
;
277 int u
= minor (dev
) & T_UNIT
;
278 wtinfo_t
*t
= wttab
+ u
;
281 if (u
>= NWT
|| t
->type
== UNKNOWN
)
284 /* Check that device is not in use */
285 if (t
->flags
& TPINUSE
)
288 /* If the tape is in rewound state, check the status and set density. */
289 if (t
->flags
& TPSTART
) {
290 /* If rewind is going on, wait */
291 error
= wtwait (t
, PCATCH
, "wtrew");
295 /* Check the controller status */
296 if (! wtsense (t
, 0, (ap
->a_oflags
& FWRITE
) ? 0 : TP_WRP
)) {
297 /* Bad status, reset the controller */
300 if (! wtsense (t
, 1, (ap
->a_oflags
& FWRITE
) ? 0 : TP_WRP
))
304 /* Set up tape density. */
305 if (t
->dens
!= (minor (dev
) & WT_DENSEL
)) {
308 switch (minor (dev
) & WT_DENSEL
) {
309 case WT_DENSDFLT
: default: break; /* default density */
310 case WT_QIC11
: d
= QIC_FMT11
; break; /* minor 010 */
311 case WT_QIC24
: d
= QIC_FMT24
; break; /* minor 020 */
312 case WT_QIC120
: d
= QIC_FMT120
; break; /* minor 030 */
313 case WT_QIC150
: d
= QIC_FMT150
; break; /* minor 040 */
314 case WT_QIC300
: d
= QIC_FMT300
; break; /* minor 050 */
315 case WT_QIC600
: d
= QIC_FMT600
; break; /* minor 060 */
318 /* Change tape density. */
321 if (! wtsense (t
, 1, TP_WRP
| TP_ILL
))
324 /* Check the status of the controller. */
325 if (t
->error
.err
& TP_ILL
) {
326 kprintf ("wt%d: invalid tape density\n", t
->unit
);
330 t
->dens
= minor (dev
) & WT_DENSEL
;
332 t
->flags
&= ~TPSTART
;
333 } else if (t
->dens
!= (minor (dev
) & WT_DENSEL
))
336 t
->bsize
= (minor (dev
) & WT_BSIZE
) ? 1024 : 512;
337 t
->buf
= kmalloc (t
->bsize
, M_TEMP
, M_WAITOK
);
339 if (isa_dma_acquire(t
->chan
))
344 if (ap
->a_oflags
& FREAD
)
346 if (ap
->a_oflags
& FWRITE
)
352 * Close routine, called on last device close.
355 wtclose (struct dev_close_args
*ap
)
357 cdev_t dev
= ap
->a_head
.a_dev
;
358 int u
= minor (dev
) & T_UNIT
;
359 wtinfo_t
*t
= wttab
+ u
;
361 if (u
>= NWT
|| t
->type
== UNKNOWN
)
364 /* If rewind is pending, do nothing */
365 if (t
->flags
& TPREW
)
368 /* If seek forward is pending and no rewind on close, do nothing */
369 if (t
->flags
& TPRMARK
) {
370 if (minor (dev
) & T_NOREWIND
)
373 /* If read file mark is going on, wait */
374 wtwait (t
, 0, "wtrfm");
377 if (t
->flags
& TPWANY
)
378 /* Tape was written. Write file mark. */
381 if (! (minor (dev
) & T_NOREWIND
)) {
382 /* Rewind tape to beginning of tape. */
383 /* Don't wait until rewind, though. */
387 if ((t
->flags
& TPRANY
) && ! (t
->flags
& (TPVOL
| TPWANY
)))
388 /* Space forward to after next file mark if no writing done. */
389 /* Don't wait for completion. */
392 t
->flags
&= TPREW
| TPRMARK
| TPSTART
| TPTIMER
;
393 kfree (t
->buf
, M_TEMP
);
394 isa_dma_release(t
->chan
);
399 * Ioctl routine. Compatible with BSD ioctls.
400 * There are two possible ioctls:
401 * ioctl (int fd, MTIOCGET, struct mtget *buf) -- get status
402 * ioctl (int fd, MTIOCTOP, struct mtop *buf) -- do BSD-like op
405 wtioctl (struct dev_ioctl_args
*ap
)
407 cdev_t dev
= ap
->a_head
.a_dev
;
408 caddr_t arg
= ap
->a_data
;
409 int u
= minor (dev
) & T_UNIT
;
410 wtinfo_t
*t
= wttab
+ u
;
411 int error
, count
, op
;
413 if (u
>= NWT
|| t
->type
== UNKNOWN
)
419 case MTIOCIEOT
: /* ignore EOT errors */
420 case MTIOCEEOT
: /* enable EOT errors */
423 ((struct mtget
*)arg
)->mt_type
=
424 t
->type
== ARCHIVE
? MT_ISVIPER1
: 0x11;
425 ((struct mtget
*)arg
)->mt_dsreg
= t
->flags
; /* status */
426 ((struct mtget
*)arg
)->mt_erreg
= t
->error
.err
; /* errors */
427 ((struct mtget
*)arg
)->mt_resid
= 0;
428 ((struct mtget
*)arg
)->mt_fileno
= 0; /* file */
429 ((struct mtget
*)arg
)->mt_blkno
= 0; /* block */
434 switch ((short) ((struct mtop
*)arg
)->mt_op
) {
436 case MTFSR
: /* forward space record */
437 case MTBSR
: /* backward space record */
438 case MTBSF
: /* backward space file */
440 case MTNOP
: /* no operation, sets status only */
441 case MTCACHE
: /* enable controller cache */
442 case MTNOCACHE
: /* disable controller cache */
444 case MTREW
: /* rewind */
445 case MTOFFL
: /* rewind and put the drive offline */
446 if (t
->flags
& TPREW
) /* rewind is running */
448 error
= wtwait (t
, PCATCH
, "wtorew");
453 case MTFSF
: /* forward space file */
454 for (count
=((struct mtop
*)arg
)->mt_count
; count
>0; --count
) {
455 error
= wtwait (t
, PCATCH
, "wtorfm");
458 error
= wtreadfm (t
);
463 case MTWEOF
: /* write an end-of-file record */
464 if (! (t
->flags
& TPWRITE
) || (t
->flags
& TPWP
))
466 error
= wtwait (t
, PCATCH
, "wtowfm");
469 error
= wtwritefm (t
);
473 case MTRETENS
: /* re-tension tape */
474 error
= wtwait (t
, PCATCH
, "wtretens");
480 case MTERASE
: /* erase to EOM */
481 if (! (t
->flags
& TPWRITE
) || (t
->flags
& TPWP
))
483 error
= wtwait (t
, PCATCH
, "wterase");
488 /* ERASE and RETENS operations work like REWIND. */
489 /* Simulate the rewind operation here. */
490 t
->flags
&= ~(TPRO
| TPWO
| TPVOL
);
493 t
->flags
|= TPSTART
| TPREW
;
505 wtstrategy (struct dev_strategy_args
*ap
)
507 cdev_t dev
= ap
->a_head
.a_dev
;
508 struct bio
*bio
= ap
->a_bio
;
509 struct buf
*bp
= bio
->bio_buf
;
510 int u
= minor(dev
) & T_UNIT
;
511 wtinfo_t
*t
= wttab
+ u
;
514 bp
->b_resid
= bp
->b_bcount
;
515 if (u
>= NWT
|| t
->type
== UNKNOWN
) {
520 /* at file marks and end of tape, we just return '0 bytes available' */
521 if (t
->flags
& TPVOL
)
524 if (bp
->b_bcount
% t
->bsize
!= 0) {
525 bp
->b_error
= EINVAL
;
529 if (bp
->b_cmd
== BUF_CMD_READ
) {
530 /* Check read access and no previous write to this tape. */
531 if (! (t
->flags
& TPREAD
) || (t
->flags
& TPWANY
))
534 /* For now, we assume that all data will be copied out */
535 /* If read command outstanding, just skip down */
536 if (! (t
->flags
& TPRO
)) {
537 if (! wtsense (t
, 1, TP_WRP
)) /* clear status */
539 if (! wtcmd (t
, QIC_RDDATA
)) { /* sed read mode */
540 wtsense (t
, 1, TP_WRP
);
543 t
->flags
|= TPRO
| TPRANY
;
547 /* Check write access and write protection. */
548 /* No previous read from this tape allowed. */
549 if (! (t
->flags
& TPWRITE
) || (t
->flags
& (TPWP
| TPRANY
)))
552 /* If write command outstanding, just skip down */
553 if (! (t
->flags
& TPWO
)) {
554 if (! wtsense (t
, 1, 0)) /* clear status */
556 if (! wtcmd (t
, QIC_WRTDATA
)) { /* set write mode */
560 t
->flags
|= TPWO
| TPWANY
;
562 flags
= ISADMA_WRITE
;
568 t
->flags
&= ~TPEXCEP
;
570 if (wtstart (t
, flags
, bp
->b_data
, bp
->b_bcount
)) {
571 wtwait (t
, 0, (flags
& ISADMA_READ
) ? "wtread" : "wtwrite");
572 bp
->b_resid
-= t
->dmacount
;
576 if (t
->flags
& TPEXCEP
) {
577 errxit
: bp
->b_error
= EIO
;
578 err2xit
: bp
->b_flags
|= B_ERROR
;
591 wtinfo_t
*t
= wttab
+ u
;
594 if (u
>= NWT
|| t
->type
== UNKNOWN
) {
595 TRACE (("wtintr() -- device not configured\n"));
599 s
= inb (t
->STATPORT
); /* get status */
600 TRACE (("wtintr() status=0x%x -- ", s
));
601 if ((s
& (t
->BUSY
| t
->NOEXCEP
)) == (t
->BUSY
| t
->NOEXCEP
)) {
603 return; /* device is busy */
607 * Check if rewind finished.
609 if (t
->flags
& TPREW
) {
610 TRACE (((s
& (t
->BUSY
| t
->NOEXCEP
)) == (t
->BUSY
| t
->NOEXCEP
) ?
611 "rewind busy?\n" : "rewind finished\n"));
612 t
->flags
&= ~TPREW
; /* Rewind finished. */
613 wtsense (t
, 1, TP_WRP
);
619 * Check if writing/reading of file mark finished.
621 if (t
->flags
& (TPRMARK
| TPWMARK
)) {
622 TRACE (((s
& (t
->BUSY
| t
->NOEXCEP
)) == (t
->BUSY
| t
->NOEXCEP
) ?
623 "marker r/w busy?\n" : "marker r/w finished\n"));
624 if (! (s
& t
->NOEXCEP
)) /* operation failed */
625 wtsense (t
, 1, (t
->flags
& TPRMARK
) ? TP_WRP
: 0);
626 t
->flags
&= ~(TPRMARK
| TPWMARK
); /* operation finished */
632 * Do we started any i/o? If no, just return.
634 if (! (t
->flags
& TPACTIVE
)) {
635 TRACE (("unexpected interrupt\n"));
642 if ((t
->dmaflags
& ISADMA_READ
) && (t
->dmatotal
- t
->dmacount
) < t
->bsize
) {
643 /* If reading short block, copy the internal buffer
644 * to the user memory. */
645 isa_dmadone (t
->dmaflags
, t
->buf
, t
->bsize
, t
->chan
);
646 bcopy (t
->buf
, t
->dmavaddr
, t
->dmatotal
- t
->dmacount
);
648 isa_dmadone (t
->dmaflags
, t
->dmavaddr
, t
->bsize
, t
->chan
);
650 t
->flags
&= ~TPACTIVE
;
651 t
->dmacount
+= t
->bsize
;
652 t
->dmavaddr
= (char *)t
->dmavaddr
+ t
->bsize
;
655 * On exception, check for end of file and end of volume.
657 if (! (s
& t
->NOEXCEP
)) {
658 TRACE (("i/o exception\n"));
659 wtsense (t
, 1, (t
->dmaflags
& ISADMA_READ
) ? TP_WRP
: 0);
660 if (t
->error
.err
& (TP_EOM
| TP_FIL
))
661 t
->flags
|= TPVOL
; /* end of file */
663 t
->flags
|= TPEXCEP
; /* i/o error */
668 if (t
->dmacount
< t
->dmatotal
) { /* continue i/o */
670 TRACE (("continue i/o, %d\n", t
->dmacount
));
673 if (t
->dmacount
> t
->dmatotal
) /* short last block */
674 t
->dmacount
= t
->dmatotal
;
675 wakeup ((caddr_t
)t
); /* wake up user level */
676 TRACE (("i/o finished, %d\n", t
->dmacount
));
679 /* start the rewind operation */
681 wtrewind (wtinfo_t
*t
)
683 int rwmode
= (t
->flags
& (TPRO
| TPWO
));
685 t
->flags
&= ~(TPRO
| TPWO
| TPVOL
);
687 * Wangtek strictly follows QIC-02 standard:
688 * clearing ONLINE in read/write modes causes rewind.
689 * REWIND command is not allowed in read/write mode
690 * and gives `illegal command' error.
692 if (t
->type
==WANGTEK
&& rwmode
) {
693 outb (t
->CTLPORT
, 0);
694 } else if (! wtcmd (t
, QIC_REWIND
))
696 t
->flags
|= TPSTART
| TPREW
;
700 /* start the `read marker' operation */
702 wtreadfm (wtinfo_t
*t
)
704 t
->flags
&= ~(TPRO
| TPWO
| TPVOL
);
705 if (! wtcmd (t
, QIC_READFM
)) {
706 wtsense (t
, 1, TP_WRP
);
709 t
->flags
|= TPRMARK
| TPRANY
;
711 /* Don't wait for completion here. */
715 /* write marker to the tape */
717 wtwritefm (wtinfo_t
*t
)
719 tsleep ((caddr_t
)wtwritefm
, 0, "wtwfm", hz
); /* timeout: 1 second */
720 t
->flags
&= ~(TPRO
| TPWO
);
721 if (! wtcmd (t
, QIC_WRITEFM
)) {
725 t
->flags
|= TPWMARK
| TPWANY
;
727 return (wtwait (t
, 0, "wtwfm"));
730 /* while controller status & mask == bits continue waiting */
732 wtpoll (wtinfo_t
*t
, int mask
, int bits
)
736 /* Poll status port, waiting for specified bits. */
737 for (i
=0; i
<1000; ++i
) { /* up to 1 msec */
738 s
= inb (t
->STATPORT
);
739 if ((s
& mask
) != bits
)
743 for (i
=0; i
<100; ++i
) { /* up to 10 msec */
744 s
= inb (t
->STATPORT
);
745 if ((s
& mask
) != bits
)
749 for (;;) { /* forever */
750 s
= inb (t
->STATPORT
);
751 if ((s
& mask
) != bits
)
753 tsleep ((caddr_t
)wtpoll
, 0, "wtpoll", 1); /* timeout: 1 tick */
757 /* execute QIC command */
759 wtcmd (wtinfo_t
*t
, int cmd
)
763 TRACE (("wtcmd() cmd=0x%x\n", cmd
));
765 s
= wtpoll (t
, t
->BUSY
| t
->NOEXCEP
, t
->BUSY
| t
->NOEXCEP
); /* ready? */
766 if (! (s
& t
->NOEXCEP
)) { /* error */
771 outb (t
->CMDPORT
, cmd
); /* output the command */
773 outb (t
->CTLPORT
, t
->REQUEST
| t
->ONLINE
); /* set request */
774 wtpoll (t
, t
->BUSY
, t
->BUSY
); /* wait for ready */
775 outb (t
->CTLPORT
, t
->IEN
| t
->ONLINE
); /* reset request */
776 wtpoll (t
, t
->BUSY
, 0); /* wait for not ready */
781 /* wait for the end of i/o, seeking marker or rewind operation */
783 wtwait (wtinfo_t
*t
, int catch, char *msg
)
787 TRACE (("wtwait() `%s'\n", msg
));
788 while (t
->flags
& (TPACTIVE
| TPREW
| TPRMARK
| TPWMARK
)) {
789 error
= tsleep ((caddr_t
)t
, catch, msg
, 0);
796 /* initialize dma for the i/o operation */
800 t
->flags
|= TPACTIVE
;
803 if (t
->type
== ARCHIVE
)
804 outb (t
->SDMAPORT
, 0); /* set dma */
806 if ((t
->dmaflags
& ISADMA_READ
) && (t
->dmatotal
- t
->dmacount
) < t
->bsize
)
807 /* Reading short block. Do it through the internal buffer. */
808 isa_dmastart (t
->dmaflags
, t
->buf
, t
->bsize
, t
->chan
);
810 isa_dmastart (t
->dmaflags
, t
->dmavaddr
, t
->bsize
, t
->chan
);
813 /* start i/o operation */
815 wtstart (wtinfo_t
*t
, unsigned flags
, void *vaddr
, unsigned len
)
819 TRACE (("wtstart()\n"));
821 s
= wtpoll (t
, t
->BUSY
| t
->NOEXCEP
, t
->BUSY
| t
->NOEXCEP
); /* ready? */
822 if (! (s
& t
->NOEXCEP
)) {
823 t
->flags
|= TPEXCEP
; /* error */
827 t
->flags
&= ~TPEXCEP
; /* clear exception flag */
839 wtclock (wtinfo_t
*t
)
841 if (! (t
->flags
& TPTIMER
)) {
843 /* Some controllers seem to lose dma interrupts too often.
844 * To make the tape stream we need 1 tick timeout. */
845 callout_reset(&t
->timeout_ch
, ((t
->flags
& TPACTIVE
) ? 1 : hz
),
851 * Simulate an interrupt periodically while i/o is going.
852 * This is necessary in case interrupts get eaten due to
853 * multiple devices on a single IRQ line.
858 wtinfo_t
*t
= (wtinfo_t
*)xt
;
860 t
->flags
&= ~TPTIMER
;
861 if (! (t
->flags
& (TPACTIVE
| TPREW
| TPRMARK
| TPWMARK
)))
864 /* If i/o going, simulate interrupt. */
866 if ((inb (t
->STATPORT
) & (t
->BUSY
| t
->NOEXCEP
)) != (t
->BUSY
| t
->NOEXCEP
)) {
867 TRACE (("wtimer() -- "));
868 wtintr ((void *)t
->unit
);
872 /* Restart timer if i/o pending. */
873 if (t
->flags
& (TPACTIVE
| TPREW
| TPRMARK
| TPWMARK
))
877 /* reset the controller */
879 wtreset (wtinfo_t
*t
)
881 /* Perform QIC-02 and QIC-36 compatible reset sequence. */
882 /* Thanks to Mikael Hybsch <micke@dynas.se>. */
885 outb (t
->CTLPORT
, t
->RESET
| t
->ONLINE
); /* send reset */
887 outb (t
->CTLPORT
, t
->ONLINE
); /* turn off reset */
890 /* Read the controller status. */
891 s
= inb (t
->STATPORT
);
892 if (s
== 0xff) /* no port at this address? */
895 /* Wait 3 sec for reset to complete. Needed for QIC-36 boards? */
896 for (i
=0; i
<3000; ++i
) {
897 if (! (s
& t
->BUSY
) || ! (s
& t
->NOEXCEP
))
900 s
= inb (t
->STATPORT
);
902 return ((s
& t
->RESETMASK
) == t
->RESETVAL
);
905 /* get controller status information */
906 /* return 0 if user i/o request should receive an i/o error code */
908 wtsense (wtinfo_t
*t
, int verb
, int ignor
)
913 TRACE (("wtsense() ignor=0x%x\n", ignor
));
914 t
->flags
&= ~(TPRO
| TPWO
);
917 if (! (t
->error
.err
& TP_ST0
))
918 t
->error
.err
&= ~TP_ST0MASK
;
919 if (! (t
->error
.err
& TP_ST1
))
920 t
->error
.err
&= ~TP_ST1MASK
;
921 t
->error
.err
&= ~ignor
; /* ignore certain errors */
922 err
= t
->error
.err
& (TP_FIL
| TP_BNL
| TP_UDA
| TP_EOM
| TP_WRP
|
923 TP_USL
| TP_CNI
| TP_MBD
| TP_NDT
| TP_ILL
);
929 /* lifted from tdriver.c from Wangtek */
930 if (err
& TP_USL
) msg
= "Drive not online";
931 else if (err
& TP_CNI
) msg
= "No cartridge";
932 else if ((err
& TP_WRP
) && !(t
->flags
& TPWP
)) {
933 msg
= "Tape is write protected";
936 else if (err
& TP_FIL
) msg
= 0 /*"Filemark detected"*/;
937 else if (err
& TP_EOM
) msg
= 0 /*"End of tape"*/;
938 else if (err
& TP_BNL
) msg
= "Block not located";
939 else if (err
& TP_UDA
) msg
= "Unrecoverable data error";
940 else if (err
& TP_NDT
) msg
= "No data detected";
941 else if (err
& TP_ILL
) msg
= "Illegal command";
943 kprintf ("wt%d: %s\n", t
->unit
, msg
);
947 /* get controller status information */
949 wtstatus (wtinfo_t
*t
)
954 wtpoll (t
, t
->BUSY
| t
->NOEXCEP
, t
->BUSY
| t
->NOEXCEP
); /* ready? */
955 outb (t
->CMDPORT
, QIC_RDSTAT
); /* send `read status' command */
957 outb (t
->CTLPORT
, t
->REQUEST
| t
->ONLINE
); /* set request */
958 wtpoll (t
, t
->BUSY
, t
->BUSY
); /* wait for ready */
959 outb (t
->CTLPORT
, t
->ONLINE
); /* reset request */
960 wtpoll (t
, t
->BUSY
, 0); /* wait for not ready */
962 p
= (char*) &t
->error
;
963 while (p
< (char*)&t
->error
+ 6) {
964 int s
= wtpoll (t
, t
->BUSY
| t
->NOEXCEP
, t
->BUSY
| t
->NOEXCEP
);
965 if (! (s
& t
->NOEXCEP
)) { /* error */
970 *p
++ = inb (t
->DATAPORT
); /* read status byte */
972 outb (t
->CTLPORT
, t
->REQUEST
| t
->ONLINE
); /* set request */
973 wtpoll (t
, t
->BUSY
, 0); /* wait for not ready */
975 outb (t
->CTLPORT
, t
->ONLINE
); /* unset request */